blob: 3e44108267620ab07d7f4251481b036a06d6de6f (
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
{
config,
pkgs,
lib,
...
}:
let
url = "https://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" ];
};
autoApprovers = {
routes = {
"192.168.43.0/24" = [
"group:owner"
"tag:internal"
];
"192.168.38.0/24" = [
"group:owner"
"tag:internal"
];
};
exitNode = [
"group:owner"
"tag:internal"
];
};
acls = [
{
action = "accept";
src = [ "group:owner" ];
dst = [ "*:*" ];
}
{
action = "accept";
src = [ "group:bud" ];
dst = [ "tag:bud_clients:*" ];
}
];
};
in
{
sops.secrets = {
# server
"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;
# client
"headscale/pre_auth_key" = { };
};
networking.firewall = {
interfaces.ppp0.allowedUDPPorts = [ stunPort ];
trustedInterfaces = [ config.services.tailscale.interfaceName ];
};
services = {
headscale = {
enable = true;
port = 8139;
settings = {
logtail.enabled = false;
server_url = url;
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 = {
inherit url;
config_path = "${headscaleConfig}";
};
integration.agent = {
enabled = true;
pre_authkey_path = config.sops.secrets."headplane/preauth_key".path;
};
};
};
tailscale = {
enable = true;
interfaceName = "headscale";
openFirewall = true;
authKeyFile = config.sops.secrets."headscale/pre_auth_key".path;
extraUpFlags = [
"--login-server=${url}"
"--advertise-exit-node"
"--advertise-routes=192.168.43.0/24,192.168.38.0/24"
];
};
};
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = true;
"net.ipv6.conf.all.forwarding" = true;
};
environment.systemPackages = [ config.services.headscale.package ];
}
|