159 lines
4.0 KiB
Nix
159 lines
4.0 KiB
Nix
|
{
|
||
|
config,
|
||
|
lib,
|
||
|
pkgs,
|
||
|
secretsDir,
|
||
|
...
|
||
|
}:
|
||
|
let
|
||
|
inherit (lib)
|
||
|
mkEnableOption
|
||
|
mkIf
|
||
|
mkOption
|
||
|
recursiveUpdate
|
||
|
;
|
||
|
inherit (lib.types)
|
||
|
bool
|
||
|
enum
|
||
|
listOf
|
||
|
str
|
||
|
submodule
|
||
|
;
|
||
|
|
||
|
cfg = config.ataraxia.services.headscale;
|
||
|
nginx = config.ataraxia.services.nginx;
|
||
|
domain = "wg.ataraxiadev.com";
|
||
|
|
||
|
dnsEntry = submodule {
|
||
|
options = {
|
||
|
name = mkOption {
|
||
|
type = str;
|
||
|
};
|
||
|
type = mkOption {
|
||
|
type = enum [
|
||
|
"A"
|
||
|
"AAAA"
|
||
|
];
|
||
|
};
|
||
|
value = mkOption {
|
||
|
type = str;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
in
|
||
|
{
|
||
|
options.ataraxia.services.headscale = {
|
||
|
enable = mkEnableOption "Enable headscale service";
|
||
|
sopsDir = mkOption {
|
||
|
type = str;
|
||
|
default = config.networking.hostName;
|
||
|
description = ''
|
||
|
Name for sops secrets directory. Defaults to hostname.
|
||
|
'';
|
||
|
};
|
||
|
nginxHost = mkOption {
|
||
|
type = bool;
|
||
|
default = config.ataraxia.services.nginx.enable;
|
||
|
description = "Enable nginx vHost integration";
|
||
|
};
|
||
|
extraDns = mkOption {
|
||
|
type = listOf dnsEntry;
|
||
|
description = ''
|
||
|
Extra dns records for headscale.
|
||
|
'';
|
||
|
};
|
||
|
};
|
||
|
|
||
|
config = mkIf cfg.enable {
|
||
|
services.headscale = {
|
||
|
enable = true;
|
||
|
address = "0.0.0.0";
|
||
|
port = 8005;
|
||
|
settings = {
|
||
|
server_url = "https://${domain}";
|
||
|
ip_prefixes = [
|
||
|
"fd7a:115c:a1e0::/64"
|
||
|
"100.64.0.0/16"
|
||
|
];
|
||
|
dns = {
|
||
|
override_local_dns = true;
|
||
|
base_domain = "tailnet.ataraxiadev.com";
|
||
|
nameservers.global = [ "127.0.0.1" ];
|
||
|
extra_records = cfg.extraDns;
|
||
|
};
|
||
|
oidc = {
|
||
|
only_start_if_oidc_is_available = true;
|
||
|
issuer = "https://auth.ataraxiadev.com/application/o/headscale/";
|
||
|
client_id = "n6UBhK8PahexLPb7GkU1xzoFLcYxQX0HWDytpUoi";
|
||
|
client_secret_path = config.sops.secrets.headscale-oidc.path;
|
||
|
scope = [
|
||
|
"openid"
|
||
|
"profile"
|
||
|
"email"
|
||
|
"groups"
|
||
|
];
|
||
|
allowed_groups = [ "headscale" ];
|
||
|
};
|
||
|
grpc_listen_addr = "127.0.0.1:50443";
|
||
|
grpc_allow_insecure = true;
|
||
|
disable_check_updates = true;
|
||
|
ephemeral_node_inactivity_timeout = "4h";
|
||
|
};
|
||
|
};
|
||
|
|
||
|
services.nginx.virtualHosts = mkIf cfg.nginxHost {
|
||
|
${domain} = recursiveUpdate nginx.defaultSettings {
|
||
|
locations."/headscale." = {
|
||
|
extraConfig = ''
|
||
|
grpc_pass grpc://${config.services.headscale.settings.grpc_listen_addr};
|
||
|
'';
|
||
|
priority = 1;
|
||
|
};
|
||
|
locations."/metrics" = {
|
||
|
proxyPass = "http://127.0.0.1:${toString config.services.headscale.port}";
|
||
|
extraConfig = ''
|
||
|
allow 100.64.0.0/16;
|
||
|
allow 10.10.10.0/24;
|
||
|
deny all;
|
||
|
'';
|
||
|
priority = 2;
|
||
|
};
|
||
|
locations."/" = {
|
||
|
proxyPass = "http://127.0.0.1:${toString config.services.headscale.port}";
|
||
|
proxyWebsockets = true;
|
||
|
priority = 3;
|
||
|
};
|
||
|
};
|
||
|
};
|
||
|
|
||
|
sops.secrets.headscale-oidc = {
|
||
|
sopsFile = secretsDir + /${cfg.sopsDir}/headscale.yaml;
|
||
|
owner = "headscale";
|
||
|
restartUnits = [ "headscale.service" ];
|
||
|
};
|
||
|
systemd.services.headscale = {
|
||
|
serviceConfig.TimeoutStopSec = 15;
|
||
|
serviceConfig.ExecStartPre =
|
||
|
let
|
||
|
waitAuthnetikReady = pkgs.writeShellScript "waitAuthnetikReady" ''
|
||
|
# Check until authentik is alive
|
||
|
max_retry=100
|
||
|
counter=0
|
||
|
until ${lib.getExe pkgs.curl} -fsSL http://auth.ataraxiadev.com/-/health/ready/
|
||
|
do
|
||
|
echo "Waiting for the authentik..."
|
||
|
sleep 3
|
||
|
[[ counter -eq $max_retry ]] && echo "Could not connect to authentik!" && exit 1
|
||
|
echo "Trying again. Try #$counter"
|
||
|
((counter++))
|
||
|
done
|
||
|
echo "Authentik is alive!"
|
||
|
'';
|
||
|
in
|
||
|
waitAuthnetikReady;
|
||
|
};
|
||
|
|
||
|
persist.state.directories = [ "/var/lib/headscale" ];
|
||
|
};
|
||
|
}
|