{ pkgs, config, lib, ... }: { # Define a new option for the admin user options.services.headscale = { adminUser = lib.mkOption { type = lib.types.str; default = "m3tam3re"; description = "Username for the headscale admin user"; }; }; config = let adminUser = config.services.headscale.adminUser; aclConfig = { # Groups definition groups = { "group:admins" = ["${adminUser}"]; }; acls = [ # Allow all connections within the tailnet { action = "accept"; src = ["*"]; dst = ["*:*"]; } # Allow admin to connect to their own services { action = "accept"; src = ["${adminUser}"]; dst = ["${adminUser}:*"]; } ]; # Auto-approvers section for routes autoApprovers = { routes = { "0.0.0.0/0" = ["${adminUser}"]; "10.0.0.0/8" = ["${adminUser}"]; "172.16.0.0/12" = ["${adminUser}"]; "192.168.0.0/16" = ["${adminUser}"]; }; exitNode = ["${adminUser}"]; }; }; # Convert to HuJSON format with comments aclHuJson = '' // Headscale ACL Policy - Generated by NixOS // Admin user: ${adminUser} ${builtins.toJSON aclConfig} ''; aclFile = pkgs.writeText "acl-policy.hujson" aclHuJson; in { services = { headscale = { enable = true; port = 3009; adminUser = "m3tam3re"; settings = { server_url = "https://va.m3tam3re.com"; dns = { base_domain = "m3ta.loc"; }; logtail.enabled = false; policy.path = "${aclFile}"; }; }; }; # Traefik configuration services.traefik.dynamicConfigOptions.http = { services.headscale.loadBalancer.servers = [ { url = "http://localhost:3009/"; } ]; routers.headscale = { rule = "Host(`va.m3tam3re.com`)"; tls = { certResolver = "godaddy"; }; service = "headscale"; entrypoints = "websecure"; }; }; # Create a systemd service to ensure the admin user exists systemd.services.headscale-ensure-admin = lib.mkIf config.services.headscale.enable { description = "Ensure Headscale admin user exists"; after = ["headscale.service"]; requires = ["headscale.service"]; wantedBy = ["multi-user.target"]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; User = "headscale"; Group = "headscale"; }; script = '' # Check if user exists and create if needed if ! ${pkgs.headscale}/bin/headscale users list | grep -q "${adminUser}"; then echo "Creating headscale admin user: ${adminUser}" ${pkgs.headscale}/bin/headscale users create "${adminUser}" else echo "Headscale admin user ${adminUser} already exists" fi ''; }; }; }