add headscale role
7 files changed, 115 insertions(+), 0 deletions(-)
A secrets/headplane-oidc.age
@@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 c9lWww EUstU6rDYzSnrcQAzKsQ92LS39+6JM4IEsC9GB0BpTw +szYKIIeq+BcUo5pHGOkXtdfjTs15GRUmejjej0k/irU +-> piv-p256 VBDKjg A+CSSR6Cuvxmzf/u5DRiNDW0LwfBtiTIsGA2nX/uAEYN +g46Go9rrKy/1m2AG+hdl1WzKTivom5DEykphbgzF2Q8 +--- pNHrD/JpiLg+TsfBzeQYtcpXEzL1bDFWHQeDDvVrpkU +æ4u9µ{IÅ�ZQ–=J(~´‚ìx\ó¢•ÿ‰6J9åˆB[Ê$ËPO92nö#ži;iÞ¬Exö�»uç8
A secrets/headscale-oidc.age
@@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> ssh-ed25519 c9lWww AbUImubvC+0jVP/4GewWOmq3Dkuc6fzYPHxTkWXDxzg +fORKnr7hE7wibMeDvu/CV+KYDUl+7tnNfWq+ybIVfMA +-> piv-p256 VBDKjg A745gR4QjDxBeNS6xUeCcNFy4i6Wf8MSMsTFaa4KbwZB +I3Jd7/w+h4ekQZLC4CXUEkq8gGE8ee2IihjuwgUqtK4 +--- eFGjnl+BXiAUHYy2kUH5Ye/DRROtt6yZh4ZbfeH0y34 +¨.2Ê6AÞSœ:�D1L<‡9lOÐ*^1ðûÊPc�´_u¦0"Ž•e[ —Üeµ•]’÷Šæ¯€
M secrets/secrets.nix → secrets/secrets.nix
@@ -43,6 +43,12 @@ codeberg-runner = [ hasel ]; + headscale-oidc = [ ulme ]; + + headplane-cookie = [ ulme ]; + headplane-headscale-api = [ ulme ]; + headplane-oidc = [ ulme ]; + dyndns = [ r5 ]; syncthing = [ r5 ]; };
M system/hosts/ulme.nix → system/hosts/ulme.nix
@@ -7,6 +7,7 @@ ./ulme-hardware.nix ../roles/remote.nix ../roles/server.nix + ../roles/headscale.nix ../roles/uptime-monitor.nix ../roles/webserver/reverse-proxy.nix ];
A system/roles/headscale.nix
@@ -0,0 +1,94 @@ +{ + config, + ... +}: +let + subdomain = "hs.alin.ovh"; + issuer = "https://id.alin.ovh"; + inherit (config.services) headscale headplane; +in +{ + age.secrets = { + headscale-oidc = { + file = ../../secrets/headscale-oidc.age; + owner = headscale.user; + group = headscale.group; + }; + headplane-cookie = { + file = ../../secrets/headplane-cookie.age; + owner = headscale.user; + group = headscale.group; + }; + headplane-headscale-api = { + file = ../../secrets/headplane-headscale-api.age; + owner = headscale.user; + group = headscale.group; + }; + headplane-oidc = { + file = ../../secrets/headplane-oidc.age; + owner = headscale.user; + group = headscale.group; + }; + }; + + services.headscale = { + enable = true; + port = 18443; + settings = { + # acme_url = config.security.acme.defaults.server; + # tls_letsencrypt_hostname = domain; + # tls_letsencrypt_listen = ":18080"; + server_url = "https://${subdomain}"; + tls_cert_path = null; + tls_key_path = null; + trusted_proxies = [ + "127.0.0.1/32" + "::1/128" + ]; + oidc = { + issuer = issuer; + client_id = "e1658483-71ee-4260-9862-a92b9fdadece"; + client_secret_path = config.age.secrets.headscale-oidc.path; + pkce = { + enabled = true; + method = "S256"; + }; + }; + prefixes.allocation = "random"; + node.expiry = "180d"; + dns = { + magic_dns = false; + override_local_dns = false; + }; + }; + }; + + services.headplane = { + enable = true; + settings = { + headscale = { + url = headscale.settings.server_url; + }; + server = { + base_url = headscale.settings.server_url; + cookie_secret_path = config.age.secrets.headplane-cookie.path; + }; + oidc = { + headscale_api_key_path = config.age.secrets.headplane-headscale-api.path; + client_id = "d7e09578-158a-4954-ba86-d3e9177c1a15"; + client_secret_path = config.age.secrets.headplane-oidc.path; + issuer = issuer; + }; + }; + }; + + services.caddy.virtualHosts = { + ${subdomain} = { + extraConfig = '' + reverse_proxy /admin/* localhost:${toString headplane.settings.server.port} + + reverse_proxy localhost:${toString headscale.port} + ''; + }; + }; +}