···137138- [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
13900140- [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
141142- [Prometheus DNSSEC Exporter](https://github.com/chrj/prometheus-dnssec-exporter), check for validity and expiration in DNSSEC signatures and expose metrics for Prometheus. Available as [services.prometheus.exporters.dnssec](#opt-services.prometheus.exporters.dnssec.enable).
···137138- [Suwayomi Server](https://github.com/Suwayomi/Suwayomi-Server), a free and open source manga reader server that runs extensions built for [Tachiyomi](https://tachiyomi.org). Available as [services.suwayomi-server](#opt-services.suwayomi-server.enable).
139140+- A self-hosted management server for the [Netbird](https://netbird.io). Available as [services.netbird.server](#opt-services.netbird.server.enable).
141+142- [ping_exporter](https://github.com/czerwonk/ping_exporter), a Prometheus exporter for ICMP echo requests. Available as [services.prometheus.exporters.ping](#opt-services.prometheus.exporters.ping.enable).
143144- [Prometheus DNSSEC Exporter](https://github.com/chrj/prometheus-dnssec-exporter), check for validity and expiration in DNSSEC signatures and expose metrics for Prometheus. Available as [services.prometheus.exporters.dnssec](#opt-services.prometheus.exporters.dnssec.enable).
···1+{
2+ config,
3+ lib,
4+ pkgs,
5+ ...
6+}:
7+8+let
9+ inherit (lib)
10+ boolToString
11+ concatStringsSep
12+ hasAttr
13+ isBool
14+ mapAttrs
15+ mkDefault
16+ mkEnableOption
17+ mkIf
18+ mkOption
19+ mkPackageOption
20+ ;
21+22+ inherit (lib.types)
23+ attrsOf
24+ bool
25+ either
26+ package
27+ str
28+ submodule
29+ ;
30+31+ toStringEnv = value: if isBool value then boolToString value else toString value;
32+33+ cfg = config.services.netbird.server.dashboard;
34+in
35+36+{
37+ options.services.netbird.server.dashboard = {
38+ enable = mkEnableOption "the static netbird dashboard frontend";
39+40+ package = mkPackageOption pkgs "netbird-dashboard" { };
41+42+ enableNginx = mkEnableOption "Nginx reverse-proxy to serve the dashboard.";
43+44+ domain = mkOption {
45+ type = str;
46+ default = "localhost";
47+ description = "The domain under which the dashboard runs.";
48+ };
49+50+ managementServer = mkOption {
51+ type = str;
52+ description = "The address of the management server, used for the API endpoints.";
53+ };
54+55+ settings = mkOption {
56+ type = submodule { freeformType = attrsOf (either str bool); };
57+58+ defaultText = ''
59+ {
60+ AUTH_AUDIENCE = "netbird";
61+ AUTH_CLIENT_ID = "netbird";
62+ AUTH_SUPPORTED_SCOPES = "openid profile email";
63+ NETBIRD_TOKEN_SOURCE = "idToken";
64+ USE_AUTH0 = false;
65+ }
66+ '';
67+68+ description = ''
69+ An attribute set that will be used to substitute variables when building the dashboard.
70+ Any values set here will be templated into the frontend and be public for anyone that can reach your website.
71+ The exact values sadly aren't documented anywhere.
72+ A starting point when searching for valid values is this [script](https://github.com/netbirdio/dashboard/blob/main/docker/init_react_envs.sh)
73+ The only mandatory value is 'AUTH_AUTHORITY' as we cannot set a default value here.
74+ '';
75+ };
76+77+ finalDrv = mkOption {
78+ readOnly = true;
79+ type = package;
80+ description = ''
81+ The derivation containing the final templated dashboard.
82+ '';
83+ };
84+ };
85+86+ config = mkIf cfg.enable {
87+ assertions = [
88+ {
89+ assertion = hasAttr "AUTH_AUTHORITY" cfg.settings;
90+ message = "The setting AUTH_AUTHORITY is required for the dasboard to function.";
91+ }
92+ ];
93+94+ services.netbird.server.dashboard = {
95+ settings =
96+ {
97+ # Due to how the backend and frontend work this secret will be templated into the backend
98+ # and then served statically from your website
99+ # This enables you to login without the normally needed indirection through the backend
100+ # but this also means anyone that can reach your website can
101+ # fetch this secret, which is why there is no real need to put it into
102+ # special options as its public anyway
103+ # As far as I know leaking this secret is just
104+ # an information leak as one can fetch some basic app
105+ # informations from the IDP
106+ # To actually do something one still needs to have login
107+ # data and this secret so this being public will not
108+ # suffice for anything just decreasing security
109+ AUTH_CLIENT_SECRET = "";
110+111+ NETBIRD_MGMT_API_ENDPOINT = cfg.managementServer;
112+ NETBIRD_MGMT_GRPC_API_ENDPOINT = cfg.managementServer;
113+ }
114+ // (mapAttrs (_: mkDefault) {
115+ # Those values have to be easily overridable
116+ AUTH_AUDIENCE = "netbird"; # must be set for your devices to be able to log in
117+ AUTH_CLIENT_ID = "netbird";
118+ AUTH_SUPPORTED_SCOPES = "openid profile email";
119+ NETBIRD_TOKEN_SOURCE = "idToken";
120+ USE_AUTH0 = false;
121+ });
122+123+ # The derivation containing the templated dashboard
124+ finalDrv =
125+ pkgs.runCommand "netbird-dashboard"
126+ {
127+ nativeBuildInputs = [ pkgs.gettext ];
128+ env = {
129+ ENV_STR = concatStringsSep " " [
130+ "$AUTH_AUDIENCE"
131+ "$AUTH_AUTHORITY"
132+ "$AUTH_CLIENT_ID"
133+ "$AUTH_CLIENT_SECRET"
134+ "$AUTH_REDIRECT_URI"
135+ "$AUTH_SILENT_REDIRECT_URI"
136+ "$AUTH_SUPPORTED_SCOPES"
137+ "$NETBIRD_DRAG_QUERY_PARAMS"
138+ "$NETBIRD_GOOGLE_ANALYTICS_ID"
139+ "$NETBIRD_HOTJAR_TRACK_ID"
140+ "$NETBIRD_MGMT_API_ENDPOINT"
141+ "$NETBIRD_MGMT_GRPC_API_ENDPOINT"
142+ "$NETBIRD_TOKEN_SOURCE"
143+ "$USE_AUTH0"
144+ ];
145+ } // (mapAttrs (_: toStringEnv) cfg.settings);
146+ }
147+ ''
148+ cp -R ${cfg.package} build
149+150+ find build -type d -exec chmod 755 {} \;
151+ OIDC_TRUSTED_DOMAINS="build/OidcTrustedDomains.js"
152+153+ envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS.tmpl" > "$OIDC_TRUSTED_DOMAINS"
154+155+ for f in $(grep -R -l AUTH_SUPPORTED_SCOPES build/); do
156+ mv "$f" "$f.copy"
157+ envsubst "$ENV_STR" < "$f.copy" > "$f"
158+ rm "$f.copy"
159+ done
160+161+ cp -R build $out
162+ '';
163+ };
164+165+ services.nginx = mkIf cfg.enableNginx {
166+ enable = true;
167+168+ virtualHosts.${cfg.domain} = {
169+ locations = {
170+ "/" = {
171+ root = cfg.finalDrv;
172+ tryFiles = "$uri $uri.html $uri/ =404";
173+ };
174+175+ "/404.html".extraConfig = ''
176+ internal;
177+ '';
178+ };
179+180+ extraConfig = ''
181+ error_page 404 /404.html;
182+ '';
183+ };
184+ };
185+ };
186+}
···1+# Netbird server {#module-services-netbird-server}
2+3+NetBird is a VPN built on top of WireGuard® making it easy to create secure private networks for your organization or home.
4+5+## Quickstart {#module-services-netbird-server-quickstart}
6+7+To fully setup Netbird as a self-hosted server, we need both a Coturn server and an identity provider, the list of supported SSOs and their setup are available [on Netbird's documentation](https://docs.netbird.io/selfhosted/selfhosted-guide#step-3-configure-identity-provider-idp).
8+9+There are quite a few settings that need to be passed to Netbird for it to function, and a minimal config looks like :
10+11+```nix
12+services.netbird.server = {
13+ enable = true;
14+15+ domain = "netbird.example.selfhosted";
16+17+ enableNginx = true;
18+19+ coturn = {
20+ enable = true;
21+22+ passwordFile = "/path/to/a/secret/password";
23+ };
24+25+ management = {
26+ oidcConfigEndpoint = "https://sso.example.selfhosted/oauth2/openid/netbird/.well-known/openid-configuration";
27+28+ settings = {
29+ TURNConfig = {
30+ Turns = [
31+ {
32+ Proto = "udp";
33+ URI = "turn:netbird.example.selfhosted:3478";
34+ Username = "netbird";
35+ Password._secret = "/path/to/a/secret/password";
36+ }
37+ ];
38+ };
39+ };
40+ };
41+};
42+```