{ config, lib, pkgs, ... }: let inherit (lib) mkIf; cfg = config.pepe.services.headscale; in { options.pepe.services.headscale = with lib; { enable = mkEnableOption "Enable Headscale"; package = mkPackageOption pkgs "headscale" { }; domain = mkOption { type = types.str; default = null; description = "Domain for the Headscale service."; }; host = mkOption { type = types.str; default = "127.0.0.1"; description = "Host for the Headscale service."; }; port = mkOption { type = types.int; default = 1194; description = "Port for the Headscale service."; }; settings = mkOption { type = types.submodule { freeformType = types.attrsOf types.anything; options = { server_url = mkOption { type = types.str; default = "https://${cfg.domain}"; }; dns = mkOption { type = types.submodule { options = { magic_dns = mkOption { type = types.bool; default = false; }; override_local_dns = mkOption { type = types.bool; default = true; }; global = mkOption { type = types.listOf types.str; default = [ ]; }; nameservers = mkOption { type = types.submodule { options.global = mkOption { type = types.listOf types.str; default = [ ]; }; }; default = { }; }; }; }; default = { }; }; log.level = mkOption { type = types.str; default = "info"; }; logtail.enabled = mkOption { type = types.bool; default = false; }; prefixes.v4 = mkOption { type = types.str; default = null; }; noise.private_key_path = mkOption { type = types.path; default = "/var/lib/headscale/noise_private.key"; }; }; }; default = { }; description = "Configuration settings for Headscale."; }; }; config = mkIf cfg.enable { environment.systemPackages = [ cfg.package ]; services.headscale = { enable = true; package = cfg.package; port = cfg.port; settings = cfg.settings; }; pepe.core = { firewall.openUDP = [ cfg.port ]; vhost.hosts.${cfg.domain} = { locations."/" = { host = cfg.host; port = cfg.port; allowWAN = true; proxyWebsockets = true; extraConfig = '' add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; proxy_buffering off; ''; }; }; }; }; }