summaryrefslogtreecommitdiff
path: root/os/kay/modules/network/headscale.nix
blob: 24df170e8193945b33aecc5ac755545842918f08 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 ];
}