···137137138138- [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).
139139140140+- A self-hosted management server for the [Netbird](https://netbird.io). Available as [services.netbird.server](#opt-services.netbird.server.enable).
141141+140142- [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).
141143142144- [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).
···11+{
22+ config,
33+ lib,
44+ pkgs,
55+ ...
66+}:
77+88+let
99+ inherit (lib)
1010+ boolToString
1111+ concatStringsSep
1212+ hasAttr
1313+ isBool
1414+ mapAttrs
1515+ mkDefault
1616+ mkEnableOption
1717+ mkIf
1818+ mkOption
1919+ mkPackageOption
2020+ ;
2121+2222+ inherit (lib.types)
2323+ attrsOf
2424+ bool
2525+ either
2626+ package
2727+ str
2828+ submodule
2929+ ;
3030+3131+ toStringEnv = value: if isBool value then boolToString value else toString value;
3232+3333+ cfg = config.services.netbird.server.dashboard;
3434+in
3535+3636+{
3737+ options.services.netbird.server.dashboard = {
3838+ enable = mkEnableOption "the static netbird dashboard frontend";
3939+4040+ package = mkPackageOption pkgs "netbird-dashboard" { };
4141+4242+ enableNginx = mkEnableOption "Nginx reverse-proxy to serve the dashboard.";
4343+4444+ domain = mkOption {
4545+ type = str;
4646+ default = "localhost";
4747+ description = "The domain under which the dashboard runs.";
4848+ };
4949+5050+ managementServer = mkOption {
5151+ type = str;
5252+ description = "The address of the management server, used for the API endpoints.";
5353+ };
5454+5555+ settings = mkOption {
5656+ type = submodule { freeformType = attrsOf (either str bool); };
5757+5858+ defaultText = ''
5959+ {
6060+ AUTH_AUDIENCE = "netbird";
6161+ AUTH_CLIENT_ID = "netbird";
6262+ AUTH_SUPPORTED_SCOPES = "openid profile email";
6363+ NETBIRD_TOKEN_SOURCE = "idToken";
6464+ USE_AUTH0 = false;
6565+ }
6666+ '';
6767+6868+ description = ''
6969+ An attribute set that will be used to substitute variables when building the dashboard.
7070+ Any values set here will be templated into the frontend and be public for anyone that can reach your website.
7171+ The exact values sadly aren't documented anywhere.
7272+ A starting point when searching for valid values is this [script](https://github.com/netbirdio/dashboard/blob/main/docker/init_react_envs.sh)
7373+ The only mandatory value is 'AUTH_AUTHORITY' as we cannot set a default value here.
7474+ '';
7575+ };
7676+7777+ finalDrv = mkOption {
7878+ readOnly = true;
7979+ type = package;
8080+ description = ''
8181+ The derivation containing the final templated dashboard.
8282+ '';
8383+ };
8484+ };
8585+8686+ config = mkIf cfg.enable {
8787+ assertions = [
8888+ {
8989+ assertion = hasAttr "AUTH_AUTHORITY" cfg.settings;
9090+ message = "The setting AUTH_AUTHORITY is required for the dasboard to function.";
9191+ }
9292+ ];
9393+9494+ services.netbird.server.dashboard = {
9595+ settings =
9696+ {
9797+ # Due to how the backend and frontend work this secret will be templated into the backend
9898+ # and then served statically from your website
9999+ # This enables you to login without the normally needed indirection through the backend
100100+ # but this also means anyone that can reach your website can
101101+ # fetch this secret, which is why there is no real need to put it into
102102+ # special options as its public anyway
103103+ # As far as I know leaking this secret is just
104104+ # an information leak as one can fetch some basic app
105105+ # informations from the IDP
106106+ # To actually do something one still needs to have login
107107+ # data and this secret so this being public will not
108108+ # suffice for anything just decreasing security
109109+ AUTH_CLIENT_SECRET = "";
110110+111111+ NETBIRD_MGMT_API_ENDPOINT = cfg.managementServer;
112112+ NETBIRD_MGMT_GRPC_API_ENDPOINT = cfg.managementServer;
113113+ }
114114+ // (mapAttrs (_: mkDefault) {
115115+ # Those values have to be easily overridable
116116+ AUTH_AUDIENCE = "netbird"; # must be set for your devices to be able to log in
117117+ AUTH_CLIENT_ID = "netbird";
118118+ AUTH_SUPPORTED_SCOPES = "openid profile email";
119119+ NETBIRD_TOKEN_SOURCE = "idToken";
120120+ USE_AUTH0 = false;
121121+ });
122122+123123+ # The derivation containing the templated dashboard
124124+ finalDrv =
125125+ pkgs.runCommand "netbird-dashboard"
126126+ {
127127+ nativeBuildInputs = [ pkgs.gettext ];
128128+ env = {
129129+ ENV_STR = concatStringsSep " " [
130130+ "$AUTH_AUDIENCE"
131131+ "$AUTH_AUTHORITY"
132132+ "$AUTH_CLIENT_ID"
133133+ "$AUTH_CLIENT_SECRET"
134134+ "$AUTH_REDIRECT_URI"
135135+ "$AUTH_SILENT_REDIRECT_URI"
136136+ "$AUTH_SUPPORTED_SCOPES"
137137+ "$NETBIRD_DRAG_QUERY_PARAMS"
138138+ "$NETBIRD_GOOGLE_ANALYTICS_ID"
139139+ "$NETBIRD_HOTJAR_TRACK_ID"
140140+ "$NETBIRD_MGMT_API_ENDPOINT"
141141+ "$NETBIRD_MGMT_GRPC_API_ENDPOINT"
142142+ "$NETBIRD_TOKEN_SOURCE"
143143+ "$USE_AUTH0"
144144+ ];
145145+ } // (mapAttrs (_: toStringEnv) cfg.settings);
146146+ }
147147+ ''
148148+ cp -R ${cfg.package} build
149149+150150+ find build -type d -exec chmod 755 {} \;
151151+ OIDC_TRUSTED_DOMAINS="build/OidcTrustedDomains.js"
152152+153153+ envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS.tmpl" > "$OIDC_TRUSTED_DOMAINS"
154154+155155+ for f in $(grep -R -l AUTH_SUPPORTED_SCOPES build/); do
156156+ mv "$f" "$f.copy"
157157+ envsubst "$ENV_STR" < "$f.copy" > "$f"
158158+ rm "$f.copy"
159159+ done
160160+161161+ cp -R build $out
162162+ '';
163163+ };
164164+165165+ services.nginx = mkIf cfg.enableNginx {
166166+ enable = true;
167167+168168+ virtualHosts.${cfg.domain} = {
169169+ locations = {
170170+ "/" = {
171171+ root = cfg.finalDrv;
172172+ tryFiles = "$uri $uri.html $uri/ =404";
173173+ };
174174+175175+ "/404.html".extraConfig = ''
176176+ internal;
177177+ '';
178178+ };
179179+180180+ extraConfig = ''
181181+ error_page 404 /404.html;
182182+ '';
183183+ };
184184+ };
185185+ };
186186+}
···11+# Netbird server {#module-services-netbird-server}
22+33+NetBird is a VPN built on top of WireGuard® making it easy to create secure private networks for your organization or home.
44+55+## Quickstart {#module-services-netbird-server-quickstart}
66+77+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).
88+99+There are quite a few settings that need to be passed to Netbird for it to function, and a minimal config looks like :
1010+1111+```nix
1212+services.netbird.server = {
1313+ enable = true;
1414+1515+ domain = "netbird.example.selfhosted";
1616+1717+ enableNginx = true;
1818+1919+ coturn = {
2020+ enable = true;
2121+2222+ passwordFile = "/path/to/a/secret/password";
2323+ };
2424+2525+ management = {
2626+ oidcConfigEndpoint = "https://sso.example.selfhosted/oauth2/openid/netbird/.well-known/openid-configuration";
2727+2828+ settings = {
2929+ TURNConfig = {
3030+ Turns = [
3131+ {
3232+ Proto = "udp";
3333+ URI = "turn:netbird.example.selfhosted:3478";
3434+ Username = "netbird";
3535+ Password._secret = "/path/to/a/secret/password";
3636+ }
3737+ ];
3838+ };
3939+ };
4040+ };
4141+};
4242+```