summaryrefslogtreecommitdiff
path: root/os/kay/modules/network/headscale.nix
diff options
context:
space:
mode:
authorsinanmohd <sinan@sinanmohd.com>2025-10-17 08:31:18 +0530
committersinanmohd <sinan@sinanmohd.com>2025-10-17 08:45:14 +0530
commit84c39b405972516a9be2e8be8729097f8691050f (patch)
tree5a63186f3004e36a0f7560ee90ef358bd3662aa9 /os/kay/modules/network/headscale.nix
parent5fd8a7084e907f4c1b4c2c86cfd69f622b4c294a (diff)
chore(os/kay): refactor
Diffstat (limited to 'os/kay/modules/network/headscale.nix')
-rw-r--r--os/kay/modules/network/headscale.nix112
1 files changed, 112 insertions, 0 deletions
diff --git a/os/kay/modules/network/headscale.nix b/os/kay/modules/network/headscale.nix
new file mode 100644
index 0000000..24df170
--- /dev/null
+++ b/os/kay/modules/network/headscale.nix
@@ -0,0 +1,112 @@
+{
+ config,
+ pkgs,
+ lib,
+ ...
+}:
+let
+ domain = "headscale.${config.global.userdata.domain}";
+ stunPort = 3478;
+
+ # A workaround generate a valid Headscale config accepted by Headplane when `config_strict == true`.
+ settings = lib.recursiveUpdate config.services.headscale.settings {
+ tls_cert_path = "/dev/null";
+ tls_key_path = "/dev/null";
+ policy.path = "/dev/null";
+ };
+ format = pkgs.formats.yaml { };
+ headscaleConfig = format.generate "headscale.yml" settings;
+
+ policyFormat = pkgs.formats.json { };
+ policy = {
+ groups = {
+ "group:owner" = [ "sinan@" ];
+ "group:bud" = [
+ "sinan@"
+ "ann@"
+ ];
+ };
+ tagOwners = {
+ "tag:bud_clients" = [ "group:bud" ];
+ "tag:internal" = [ "group:owner" ];
+ "tag:cusat" = [ "group:owner" ];
+ "tag:gaijin" = [ "group:owner" ];
+ };
+ acls = [
+ {
+ action = "accept";
+ src = [ "group:owner" ];
+ dst = [ "*:*" ];
+ }
+
+ {
+ action = "accept";
+ src = [ "group:bud" ];
+ dst = [ "tag:bud_clients:*" ];
+ }
+ ];
+ };
+in
+{
+ sops.secrets = {
+ "headplane/cookie_secret".owner = config.services.headscale.user;
+ "headplane/preauth_key".owner = config.services.headscale.user;
+ "headscale/noise_private_key".owner = config.services.headscale.user;
+ "headscale/derp_private_key".owner = config.services.headscale.user;
+ };
+
+ networking.firewall.interfaces.ppp0.allowedUDPPorts = [ stunPort ];
+
+ services = {
+ headscale = {
+ enable = true;
+ port = 8139;
+
+ settings = {
+ logtail.enabled = false;
+ server_url = "https://${domain}";
+ noise.private_key_path = config.sops.secrets."headscale/noise_private_key".path;
+ dns = {
+ base_domain = "tsnet.${config.global.userdata.domain}";
+ override_local_dns = false;
+ };
+ derp = {
+ server = {
+ enabled = true;
+ private_key_path = config.sops.secrets."headscale/derp_private_key".path;
+ region_code = config.networking.hostName;
+ region_name = config.networking.hostName;
+ stun_listen_addr = "0.0.0.0:${toString stunPort}";
+ region_id = 6969;
+ automatically_add_embedded_derp_region = true;
+ };
+ urls = [ ];
+ };
+ policy = {
+ mode = "file";
+ path = policyFormat.generate "acl.json" policy;
+ };
+ };
+ };
+
+ headplane = {
+ enable = true;
+ settings = {
+ server = {
+ port = 8140;
+ cookie_secret_path = config.sops.secrets."headplane/cookie_secret".path;
+ };
+ headscale = {
+ url = "https://${domain}";
+ config_path = "${headscaleConfig}";
+ };
+ integration.agent = {
+ enabled = true;
+ pre_authkey_path = config.sops.secrets."headplane/preauth_key".path;
+ };
+ };
+ };
+ };
+
+ environment.systemPackages = [ config.services.headscale.package ];
+}