1{
2 config,
3 lib,
4 pkgs,
5 utils,
6 ...
7}:
8
9let
10 inherit (lib)
11 getExe'
12 mkEnableOption
13 mkIf
14 mkPackageOption
15 mkOption
16 ;
17
18 inherit (lib.types) enum port str;
19
20 inherit (utils) escapeSystemdExecArgs;
21
22 cfg = config.services.netbird.server.signal;
23in
24
25{
26 options.services.netbird.server.signal = {
27 enable = mkEnableOption "Netbird's Signal Service";
28
29 package = mkPackageOption pkgs "netbird" { };
30
31 enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird signal service.";
32
33 domain = mkOption {
34 type = str;
35 description = "The domain name for the signal service.";
36 };
37
38 port = mkOption {
39 type = port;
40 default = 8012;
41 description = "Internal port of the signal server.";
42 };
43
44 logLevel = mkOption {
45 type = enum [
46 "ERROR"
47 "WARN"
48 "INFO"
49 "DEBUG"
50 ];
51 default = "INFO";
52 description = "Log level of the netbird signal service.";
53 };
54 };
55
56 config = mkIf cfg.enable {
57 systemd.services.netbird-signal = {
58 after = [ "network.target" ];
59 wantedBy = [ "multi-user.target" ];
60
61 serviceConfig = {
62 ExecStart = escapeSystemdExecArgs [
63 (getExe' cfg.package "netbird-signal")
64 "run"
65 # Port to listen on
66 "--port"
67 cfg.port
68 # Log to stdout
69 "--log-file"
70 "console"
71 # Log level
72 "--log-level"
73 cfg.logLevel
74 ];
75
76 Restart = "always";
77 RuntimeDirectory = "netbird-mgmt";
78 StateDirectory = "netbird-mgmt";
79 WorkingDirectory = "/var/lib/netbird-mgmt";
80
81 # hardening
82 LockPersonality = true;
83 MemoryDenyWriteExecute = true;
84 NoNewPrivileges = true;
85 PrivateMounts = true;
86 PrivateTmp = true;
87 ProtectClock = true;
88 ProtectControlGroups = true;
89 ProtectHome = true;
90 ProtectHostname = true;
91 ProtectKernelLogs = true;
92 ProtectKernelModules = true;
93 ProtectKernelTunables = true;
94 ProtectSystem = true;
95 RemoveIPC = true;
96 RestrictNamespaces = true;
97 RestrictRealtime = true;
98 RestrictSUIDSGID = true;
99 };
100
101 stopIfChanged = false;
102 };
103
104 services.nginx = mkIf cfg.enableNginx {
105 enable = true;
106
107 virtualHosts.${cfg.domain} = {
108 locations."/signalexchange.SignalExchange/".extraConfig = ''
109 # This is necessary so that grpc connections do not get closed early
110 # see https://stackoverflow.com/a/67805465
111 client_body_timeout 1d;
112
113 grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
114
115 grpc_pass grpc://localhost:${builtins.toString cfg.port};
116 grpc_read_timeout 1d;
117 grpc_send_timeout 1d;
118 grpc_socket_keepalive on;
119 '';
120 };
121 };
122 };
123}