server-configs/machines/gerd/services/headscale/headscale.nix

80 lines
2 KiB
Nix

{ config, pkgs, ... }:
let
svc_domain = config.mine.shared.settings.headscale.domain;
svc_domain_dns_magic_domain = "ts.${config.mine.shared.settings.domain}";
grpc_port = 50443;
in {
services.headscale = {
enable = true;
settings = {
server_url = "https://${svc_domain}";
# grpc
grpc_listen_addr = "127.0.0.1:${builtins.toString grpc_port}";
grpc_allow_insecure = true;
# dns
dns.base_domain = svc_domain_dns_magic_domain;
dns.nameservers.global = [ "1.1.1.1" ];
# acl -> save in database
policy.mode = "database";
# auth
oidc = {
only_start_if_oidc_is_available = true;
issuer = "https://${config.mine.shared.settings.authelia.domain}";
client_id = "headscale";
client_secret_path = "$CREDENTIALS_DIRECTORY/authelia-secret";
};
# debug
log.level = "debug";
};
};
systemd.services.headscale.serviceConfig.LoadCredential = [
"authelia-secret:${config.age.secrets.headscale-authelia-secret.path}"
];
# setup for oidc
services.authelia.instances.main.settings.identity_providers.oidc.clients = [{
client_id = "headscale";
client_name = "Headscale";
client_secret = "$pbkdf2-sha512$310000$/xiUR1oDvUEn4OKEu31COw$Z.IMgW3Qb2.mgCyEq1UUDC0i7cX2GOiywUjY4MsNv4ixQCP1jFO7njctCW2mVCqvkgfylDpsWRM3z.uXTs89IA";
consent_mode = "implicit";
redirect_uris = [ "https://${svc_domain}/oidc/callback" ];
scopes = [
"openid"
"profile"
"email"
];
}];
# nginx
services.nginx.virtualHosts."${svc_domain}" = {
forceSSL = true;
enableACME = true;
# headscale gRPC API
locations."/headscale" = {
extraConfig = ''
grpc_pass 127.0.0.1:${builtins.toString grpc_port};
'';
priority = 0;
};
# fallback to headscale
locations."/" = {
proxyPass = "http://127.0.0.1:${builtins.toString config.services.headscale.port}";
proxyWebsockets = true;
};
};
# persistence
environment.persistence.root.directories = [
"/var/lib/headscale"
];
}