-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathnetbird.nix
160 lines (143 loc) · 4.87 KB
/
netbird.nix
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
153
154
155
156
157
158
159
160
{
config,
globals,
lib,
nodes,
...
}:
let
sentinelCfg = nodes.sentinel.config;
netbirdDomain = "netbird.${globals.domains.me}";
in
{
wireguard.proxy-sentinel = {
client.via = "sentinel";
firewallRuleForNode.sentinel.allowedTCPPorts = [
config.services.netbird.server.management.port
config.services.netbird.server.signal.port
];
};
# Mirror the original coturn password
age.secrets.coturn-password-netbird = {
inherit (sentinelCfg.age.secrets.coturn-password-netbird) rekeyFile;
};
age.secrets.coturn-secret = {
generator.script = "alnum";
};
age.secrets.netbird-data-store-encryption-key = {
generator.script =
{ pkgs, ... }:
''
${lib.getExe pkgs.openssl} rand -base64 32
'';
};
environment.persistence."/persist".directories = [
{
directory = "/var/lib/netbird-mgmt";
mode = "640";
user = "netbird";
group = "netbird";
}
];
services.netbird = {
server = {
enable = true;
domain = netbirdDomain;
dashboard.settings.AUTH_AUTHORITY = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird";
management = {
singleAccountModeDomain = "internal.${globals.domains.me}";
dnsDomain = "internal.${globals.domains.me}";
disableAnonymousMetrics = true;
oidcConfigEndpoint = "https://${globals.services.kanidm.domain}/oauth2/openid/netbird/.well-known/openid-configuration";
turnDomain = globals.services.coturn.domain;
turnPort = sentinelCfg.services.coturn.tls-listening-port;
settings = {
HttpConfig = {
# Audience must be set here, otherwise the grpc server will not initialize the jwt validator causing:
# failed validating JWT token sent from peer [...] no jwt validator set
AuthAudience = "netbird";
};
TURNConfig = {
Secret._secret = config.age.secrets.coturn-secret.path;
Turns = [
{
Proto = "udp";
URI = "turn:${config.services.netbird.server.management.turnDomain}:${builtins.toString config.services.netbird.server.management.turnPort}";
Username = "netbird";
Password._secret = config.age.secrets.coturn-password-netbird.path;
}
];
};
DataStoreEncryptionKey._secret = config.age.secrets.netbird-data-store-encryption-key.path;
};
};
};
};
globals.services.netbird.domain = netbirdDomain;
globals.monitoring.http.netbird = {
url = "https://${netbirdDomain}/api/users";
expectedStatus = 401;
expectedBodyRegex = "no valid authentication";
network = "internet";
};
nodes.sentinel = {
services.nginx = {
upstreams.netbird-mgmt = {
servers."${config.wireguard.proxy-sentinel.ipv4}:${builtins.toString config.services.netbird.server.management.port}" =
{ };
extraConfig = ''
zone netbird 64k;
keepalive 5;
'';
monitoring = {
enable = true;
path = "/api/users";
expectedStatus = 401;
expectedBodyRegex = "no valid authentication";
};
};
upstreams.netbird-signal = {
servers."${config.wireguard.proxy-sentinel.ipv4}:${builtins.toString config.services.netbird.server.signal.port}" =
{ };
extraConfig = ''
zone netbird 64k;
keepalive 5;
'';
};
virtualHosts.${netbirdDomain} = {
forceSSL = true;
useACMEWildcardHost = true;
locations = {
"/" = {
root = config.services.netbird.server.dashboard.finalDrv;
tryFiles = "$uri $uri.html $uri/ =404";
X-Frame-Options = "SAMEORIGIN";
};
"/signalexchange.SignalExchange/".extraConfig = ''
grpc_pass grpc://netbird-signal;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
grpc_read_timeout 1d;
grpc_send_timeout 1d;
grpc_socket_keepalive on;
'';
"/api".proxyPass = "http://netbird-mgmt";
"/management.ManagementService/".extraConfig = ''
grpc_pass grpc://netbird-mgmt;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
grpc_read_timeout 1d;
grpc_send_timeout 1d;
grpc_socket_keepalive on;
'';
};
# client_body_timeout is necessary so that grpc connections do not get closed early, see https://stackoverflow.com/a/67805465
extraConfig = ''
client_header_timeout 1d;
client_body_timeout 1d;
client_max_body_size 512M;
'';
};
};
};
systemd.services.netbird-signal.serviceConfig.RestartSec = "60"; # Retry every minute
systemd.services.netbird-management.serviceConfig.RestartSec = "60"; # Retry every minute
}