diff --git a/hosts/desktopnix/default.nix b/hosts/desktopnix/default.nix index 16951da..0866843 100644 --- a/hosts/desktopnix/default.nix +++ b/hosts/desktopnix/default.nix @@ -57,4 +57,6 @@ nixpkgs.config.permittedInsecurePackages = lib.trace "remove when possible" [ "nix-2.16.2" ]; + + services.netbird.enable = true; } diff --git a/hosts/elisabeth/guests.nix b/hosts/elisabeth/guests.nix index 784670d..c936136 100644 --- a/hosts/elisabeth/guests.nix +++ b/hosts/elisabeth/guests.nix @@ -21,6 +21,7 @@ apispotify = "apisptfy"; kanidm = "auth"; oauth2-proxy = "oauth2"; + netbird = "netbird"; }; in "${domains.${hostName}}.${config.secrets.secrets.global.domains.web}"; # TODO hard coded elisabeth nicht so schön @@ -61,6 +62,49 @@ in { { enable = true; recommendedSetup = true; + upstreams.netbird = { + servers."${ipOf "netbird"}:80" = {}; + extraConfig = '' + zone netbird 64k ; + keepalive 5 ; + ''; + }; + upstreams.netbird-mgmt = { + servers."${ipOf "netbird"}:3000" = {}; + extraConfig = '' + zone netbird 64k ; + keepalive 5 ; + ''; + }; + virtualHosts.${domainOf "netbird"} = { + forceSSL = true; + useACMEHost = "web"; + locations = { + "/" = { + proxyPass = "http://netbird"; + proxyWebsockets = true; + X-Frame-Options = "SAMEORIGIN"; + }; + "/signalexchange.SignalExchange/".extraConfig = '' + grpc_pass grpc://${ipOf "netbird"}:3001; + grpc_read_timeout 1d; + grpc_send_timeout 1d; + grpc_socket_keepalive on; + ''; + + "/api".proxyPass = "http://netbird-mgmt"; + + "/management.ManagementService/".extraConfig = '' + grpc_pass grpc://${ipOf "netbird"}:3000; + grpc_read_timeout 1d; + grpc_send_timeout 1d; + grpc_socket_keepalive on; + ''; + }; + extraConfig = '' + client_max_body_size 500M ; + ''; + }; } (blockOf "vaultwarden" {maxBodySize = "1G";}) (blockOf "forgejo" {maxBodySize = "1G";}) @@ -154,7 +198,7 @@ in { } ]) (blockOf "paperless" {maxBodySize = "5G";}) - (blockOf "ttrss" {port = 80;}) + #(blockOf "ttrss" {port = 80;}) (blockOf "yourspotify" {port = 80;}) (blockOf "apispotify" { port = 80; @@ -262,8 +306,9 @@ in { // mkContainer "vaultwarden" {} // mkContainer "ddclient" {} // mkContainer "ollama" {} - // mkContainer "ttrss" {} + #// mkContainer "ttrss" {} // mkContainer "yourspotify" {} + // mkContainer "netbird" {} // mkContainer "kanidm" {} // mkContainer "nextcloud" { enablePanzer = true; diff --git a/hosts/elisabeth/secrets/kanidm/secrets.nix.age b/hosts/elisabeth/secrets/kanidm/secrets.nix.age index 2ec684f..ca3aa4e 100644 Binary files a/hosts/elisabeth/secrets/kanidm/secrets.nix.age and b/hosts/elisabeth/secrets/kanidm/secrets.nix.age differ diff --git a/hosts/elisabeth/secrets/netbird/host.pub b/hosts/elisabeth/secrets/netbird/host.pub new file mode 100644 index 0000000..5509a15 --- /dev/null +++ b/hosts/elisabeth/secrets/netbird/host.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF0+o9G3hA/5PbaxVy+EoOOJw5cHKu3p5yjAaHDHFQ8Q diff --git a/modules/netbird-dashboard.nix b/modules/netbird-dashboard.nix new file mode 100644 index 0000000..6f40045 --- /dev/null +++ b/modules/netbird-dashboard.nix @@ -0,0 +1,107 @@ +{ + pkgs, + config, + lib, + ... +}: let + inherit + (lib) + mkPackageOption + mkIf + mkEnableOption + mkOption + types + isBool + boolToString + ; + + toStringEnv = value: + if isBool value + then boolToString value + else toString value; + cfg = config.services.netbird-dashboard; +in { + options.services.netbird-dashboard = { + enable = mkEnableOption "the static netbird dashboard frontend"; + package = mkPackageOption pkgs "netbird-dashboard" {}; + enableNginx = mkEnableOption "Nginx as a webserver serving the backend"; + domain = mkOption { + type = types.str; + description = "The domain under which the dashboard runs."; + default = "localhost"; + }; + settings = mkOption { + type = types.submodule { + freeformType = types.attrsOf (types.oneOf [types.str types.bool]); + config = { + #AUTH_AUTHORITY = ""; #${AUTH_AUTHORITY:-https://$AUTH0_DOMAIN} + #AUTH_CLIENT_ID = ""; #${AUTH_CLIENT_ID:-$AUTH0_CLIENT_ID} + # Due to how the backend and frontend work this secret will be templated into the backend + # and then served statically from your website + # This enables you to login without the normally needed indirection through the backend + # but this also means anyone that can reach your website can + # fetch this secret, which is why there is no real need to put it into + # special options as its public anyway + # As far as I know leaking this secret is just + # an information leak as one can fetch some basic app + # informations from the IDP + # To actually do something one still needs to have login + # data and this secret so this being public will not + # suffice for anything just decreasing security + AUTH_CLIENT_SECRET = ""; #${AUTH_CLIENT_SECRET} + AUTH_AUDIENCE = "netbird"; #${AUTH_AUDIENCE:-$AUTH0_AUDIENCE} + #AUTH_REDIRECT_URI=${AUTH_REDIRECT_URI} + #AUTH_SILENT_REDIRECT_URI=${AUTH_SILENT_REDIRECT_URI} + USE_AUTH0 = false; #${USE_AUTH0:-true} + AUTH_SUPPORTED_SCOPES = "openid profile email"; #${AUTH_SUPPORTED_SCOPES:-openid profile email api offline_access email_verified} + + NETBIRD_MGMT_API_ENDPOINT = config.services.netbird-server.domain; #$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//') + NETBIRD_MGMT_GRPC_API_ENDPOINT = config.services.netbird-server.domain; #${NETBIRD_MGMT_GRPC_API_ENDPOINT} + #NETBIRD_HOTJAR_TRACK_ID=${NETBIRD_HOTJAR_TRACK_ID} + #NETBIRD_GOOGLE_ANALYTICS_ID=${NETBIRD_GOOGLE_ANALYTICS_ID} + NETBIRD_TOKEN_SOURCE = "idToken"; + #NETBIRD_DRAG_QUERY_PARAMS=${NETBIRD_DRAG_QUERY_PARAMS:-false} + }; + }; + }; + }; + config = let + deriv = pkgs.runCommand "template-netbird-dashboard" {} '' + cp -r ${cfg.package} ./temp + + + ${ + lib.concatStringsSep "\n" (lib.mapAttrsToList (name: value: ''export "${name}"="${toStringEnv value}"'') cfg.settings) + } + + # replace ENVs in the config + ENV_STR="\$\$USE_AUTH0 \$\$AUTH_AUDIENCE \$\$AUTH_AUTHORITY \$\$AUTH_CLIENT_ID \$\$AUTH_CLIENT_SECRET \$\$AUTH_SUPPORTED_SCOPES \$\$NETBIRD_MGMT_API_ENDPOINT \$\$NETBIRD_MGMT_GRPC_API_ENDPOINT \$\$NETBIRD_HOTJAR_TRACK_ID \$\$NETBIRD_GOOGLE_ANALYTICS_ID \$\$AUTH_REDIRECT_URI \$\$AUTH_SILENT_REDIRECT_URI \$\$NETBIRD_TOKEN_SOURCE \$\$NETBIRD_DRAG_QUERY_PARAMS" + + find temp -type d -exec chmod 755 {} \; + OIDC_TRUSTED_DOMAINS="./temp/OidcTrustedDomains.js" + ${pkgs.gettext}/bin/envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS" + for f in $(grep -R -l AUTH_SUPPORTED_SCOPES ./); do + ${pkgs.gettext}/bin/envsubst "$ENV_STR" < "$f" > "$f".copy + mv -f "$f".copy "$f" + done + mkdir -p $out + cp -r ./temp/. $out/ + ''; + in + mkIf cfg.enable + { + services.nginx = mkIf cfg.enableNginx { + enable = true; + virtualHosts = { + ${cfg.domain} = { + locations = { + "/" = { + root = "${deriv}/"; + tryFiles = "$uri /index.html"; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/netbird-server.nix b/modules/netbird-server.nix index 015e0b6..3d96266 100644 --- a/modules/netbird-server.nix +++ b/modules/netbird-server.nix @@ -9,39 +9,54 @@ mkEnableOption mkOption types - mkDefault + mkPackageOption mkIf ; - cfg = config.services.netbird; + cfg = config.services.netbird-server; - configFile = formatType.generate config.json cfg.settings; + configFile = formatType.generate "config.json" cfg.settings; - formatType = pkgs.format.json {}; + formatType = pkgs.formats.json {}; in { - options.services.netbird = { + options.services.netbird-server = { enable = mkEnableOption "netbird, a self hosted wireguard VPN"; + package = mkPackageOption pkgs "netbird" {}; domain = mkOption { description = "The domain of your netbird instance"; }; + port = mkOption { + description = "The port the management interface will listen on"; + type = types.port; + default = 3000; + }; oidcConfigEndpoint = mkOption { type = types.str; example = "https://example.eu.auth0.com/.well-known/openid-configuration"; description = "The oidc discovery endpoint"; }; - dataDir = mkOption { - description = "Runtime directory where netbird stores its data"; - types = types.path; - default = /var/lib/netbird; + signalPort = mkOption { + description = "The listening port for the signal protocol"; + default = 3001; + type = types.port; }; + + singleAccountModeDomain = mkOption { + description = "Optional domain for single account mode, set to null to disable singleAccountMode"; + type = types.nullOr types.str; + default = "netbird.selfhosted"; + example = null; + }; + turn = { domain = mkOption { description = "The domain under which the TURN server is reachable"; type = types.str; example = "localhost"; + default = cfg.domain; }; port = mkOption { description = "The port under which the TURN server is reachable"; - type = types.int; + type = types.port; default = 3478; }; userName = mkOption { @@ -56,15 +71,14 @@ in { }; }; settings = mkOption { + default = {}; type = types.submodule { freeformType = formatType.type; - options = { - }; - config = mkDefault { + config = { Stuns = [ { Proto = "udp"; - Uri = "stun:${cfg.turn.domain}:${cfg.turn.domain}"; + Uri = "turn:${cfg.turn.domain}:${toString cfg.turn.port}"; Username = ""; Password = null; } @@ -73,7 +87,7 @@ in { Turns = [ { Proto = "udp"; - Uri = "stun:${cfg.turn.domain}:${cfg.turn.port}"; + Uri = "stun:${cfg.turn.domain}:${toString cfg.turn.port}"; Username = cfg.turn.userName; Password = cfg.turn.password; } @@ -96,13 +110,13 @@ in { "0.0.0.0/0" ]; }; - Datadir = cfg.dataDir; - DataStoreEncryptionKey = lib.trace "uppsi wuppsi ich hab mein netbird unsiccccccher gemacht" "$NETBIRD_DATASTORE_ENC_KEY"; + Datadir = "/var/lib/netbird-mgmt"; + DataStoreEncryptionKey = lib.trace "uppsi wuppsi ich hab mein netbird unsiccccccher gemacht" "X4/obyAolDVhjGsz8NDb4TJqgCfwmCA7lOtJFHt9L3w="; StoreConfig = { Engine = "sqlite"; }; HttpConfig = { - Address = "0.0.0.0:3000"; + Address = "0.0.0.0:${toString cfg.port}"; #"AuthIssuer" = "$NETBIRD_AUTH_AUTHORITY"; #"AuthAudience" = "$NETBIRD_AUTH_AUDIENCE"; #"AuthKeysLocation" = "$NETBIRD_AUTH_JWT_CERTS"; @@ -127,198 +141,111 @@ in { #"KeycloakClientCredentials" = null; #"ZitadelClientCredentials" = null; }; - #DeviceAuthorizationFlow = { - # Provider = "$NETBIRD_AUTH_DEVICE_AUTH_PROVIDER"; - # "ProviderConfig" = { - # "Audience" = "$NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE"; - # "AuthorizationEndpoint" = ""; - # "Domain" = "$NETBIRD_AUTH0_DOMAIN"; - # "ClientID" = "$NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID"; - # "ClientSecret" = ""; - # "TokenEndpoint" = "$NETBIRD_AUTH_TOKEN_ENDPOINT"; - # "DeviceAuthEndpoint" = "$NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT"; - # "Scope" = "$NETBIRD_AUTH_DEVICE_AUTH_SCOPE"; - # "UseIDToken" = "$NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN"; - # "RedirectURLs" = null; - # }; - #}; + DeviceAuthorizationFlow = { + #Provider = "$NETBIRD_AUTH_DEVICE_AUTH_PROVIDER"; + ProviderConfig = { + Audience = "netbird"; + #"AuthorizationEndpoint" = ""; + #"Domain" = "$NETBIRD_AUTH0_DOMAIN"; + #"ClientID" = "$NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID"; + #"ClientSecret" = ""; + #"TokenEndpoint" = "$NETBIRD_AUTH_TOKEN_ENDPOINT"; + #"DeviceAuthEndpoint" = "$NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT"; + Scope = "openid profile email"; + #"UseIDToken" = "$NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN"; + #"RedirectURLs" = null; + }; + }; PKCEAuthorizationFlow = { ProviderConfig = { - #Audience = "$NETBIRD_AUTH_PKCE_AUDIENCE"; + Audience = "netbird"; ClientID = "netbird"; - ClientSecret = lib.trace "oho bei zo vielen sicherheitzlücken" "$NETBIRD_AUTH_CLIENT_SECRET"; + ClientSecret = lib.trace "oho bei zo vielen sicherheitzlücken" ""; Domain = ""; #AuthorizationEndpoint = "$NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT"; #TokenEndpoint = "$NETBIRD_AUTH_TOKEN_ENDPOINT"; Scope = "openid profile email"; - RedirectURLs = ["localhost:53000"]; - UseIDToken = "$NETBIRD_AUTH_PKCE_USE_ID_TOKEN"; + RedirectURLs = ["http://localhost:53000"]; + UseIDToken = true; }; }; }; }; }; }; - config = - mkIf cfg.enable { - systemd.services = { - netbird-setup = { - wantedBy = [ - "netbird-management.service" - "netbird-signal.service" - "multi-user.target" - ]; - serviceConfig = { - Type = "oneshot"; - RuntimeDirectory = "netbird-mgmt"; - StateDirectory = "netbird-mgmt"; - WorkingDirectory = cfg.dataDir; - EnvironmentFile = [ ]; - }; - unitConfig = { - StartLimitInterval = 5; - StartLimitBurst = 10; - }; + config = mkIf cfg.enable { + systemd.services = { + netbird-signal = { + after = ["network.target"]; + wantedBy = ["netbird-management.service"]; + restartTriggers = [ + configFile + ]; - path = - [ - pkgs.coreutils - pkgs.findutils - pkgs.gettext - pkgs.gnused - # ] - # ++ (optionals cfg.setupAutoOidc [ - # pkgs.curl - # pkgs.jq - ]; - - script = - '' - cp ${configFile} ${cfg.dataDir}/management.json - '' - #+ (optionalString cfg.setupAutoOidc '' - # mv ${stateDir}/management.json.copy ${stateDir}/management.json - # echo "loading OpenID configuration from $NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT to the openid-configuration.json file" - # curl "$NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT" -q -o ${stateDir}/openid-configuration.json - - # export NETBIRD_AUTH_AUTHORITY=$(jq -r '.issuer' ${stateDir}/openid-configuration.json) - # export NETBIRD_AUTH_JWT_CERTS=$(jq -r '.jwks_uri' ${stateDir}/openid-configuration.json) - # export NETBIRD_AUTH_TOKEN_ENDPOINT=$(jq -r '.token_endpoint' ${stateDir}/openid-configuration.json) - # export NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT=$(jq -r '.device_authorization_endpoint' ${stateDir}/openid-configuration.json) - # export NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT=$(jq -r '.authorization_endpoint' ${stateDir}/openid-configuration.json) - - # envsubst '$NETBIRD_AUTH_AUTHORITY $NETBIRD_AUTH_JWT_CERTS $NETBIRD_AUTH_TOKEN_ENDPOINT $NETBIRD_AUTH_DEVICE_AUTH_ENDPOINT $NETBIRD_AUTH_PKCE_AUTHORIZATION_ENDPOINT' < ${stateDir}/management.json > ${stateDir}/management.json.copy - #'') - #+ '' - # # Update secrets in management.json - # ${builtins.concatStringsSep "\n" ( - # builtins.attrValues ( - # builtins.mapAttrs (name: path: "export ${name}=$(cat ${path})") ( - # filterAttrs (_: p: p != null) cfg.secretFiles - # ) - # ) - # )} - + '' - - #envsubst '$TURN_PASSWORD $TURN_SECRET $STUN_PASSWORD $AUTH_CLIENT_SECRET $IDP_MGMT_CLIENT_SECRET' < ${cfg.dataDir}/management.json.copy > ${cfg.dataDir}/management.json - - rm -rf ${cfg.dataDir}/web-ui - mkdir -p ${cfg.dataDir}/web-ui - cp -R ${cfg.dashboard}/* ${cfg.dataDir}/web-ui - - export AUTH_AUTHORITY="$NETBIRD_AUTH_AUTHORITY" - export AUTH_CLIENT_ID="$NETBIRD_AUTH_CLIENT_ID" - ${optionalString (cfg.secretFiles.AUTH_CLIENT_SECRET == null) - ''export AUTH_CLIENT_SECRET="$NETBIRD_AUTH_CLIENT_SECRET"''} - export AUTH_AUDIENCE="$NETBIRD_AUTH_AUDIENCE" - export AUTH_REDIRECT_URI="$NETBIRD_AUTH_REDIRECT_URI" - export AUTH_SILENT_REDIRECT_URI="$NETBIRD_AUTH_SILENT_REDIRECT_URI" - export USE_AUTH0="$NETBIRD_USE_AUTH0" - export AUTH_SUPPORTED_SCOPES=$(echo $NETBIRD_AUTH_SUPPORTED_SCOPES | sed -E 's/"//g') - - export NETBIRD_MGMT_API_ENDPOINT=$(echo $NETBIRD_MGMT_API_ENDPOINT | sed -E 's/(:80|:443)$//') - - MAIN_JS=$(find ${cfg.dataDir}/web-ui/static/js/main.*js) - OIDC_TRUSTED_DOMAINS=${cfg.dataDir}/web-ui/OidcTrustedDomains.js - mv "$MAIN_JS" "$MAIN_JS".copy - envsubst '$USE_AUTH0 $AUTH_AUTHORITY $AUTH_CLIENT_ID $AUTH_CLIENT_SECRET $AUTH_SUPPORTED_SCOPES $AUTH_AUDIENCE $NETBIRD_MGMT_API_ENDPOINT $NETBIRD_MGMT_GRPC_API_ENDPOINT $NETBIRD_HOTJAR_TRACK_ID $AUTH_REDIRECT_URI $AUTH_SILENT_REDIRECT_URI $NETBIRD_TOKEN_SOURCE $NETBIRD_DRAG_QUERY_PARAMS' < "$MAIN_JS".copy > "$MAIN_JS" - envsubst '$NETBIRD_MGMT_API_ENDPOINT' < "$OIDC_TRUSTED_DOMAINS".tmpl > "$OIDC_TRUSTED_DOMAINS" - ''; + serviceConfig = { + ExecStart = '' + ${cfg.package}/bin/netbird-signal run \ + --log-file console \ + --port ${builtins.toString cfg.signalPort} + ''; + Restart = "always"; + RuntimeDirectory = "netbird-mgmt"; + StateDirectory = "netbird-mgmt"; + WorkingDirectory = "/var/lib/netbird-mgmt"; }; - - netbird-signal = { - after = [ "network.target" ]; - wantedBy = [ "netbird-management.service" ]; - restartTriggers = [ - settingsFile - managementFile - ]; - - serviceConfig = { - ExecStart = '' - ${cfg.package}/bin/netbird-signal run \ - --port ${builtins.toString cfg.ports.signal} \ - --log-file console \ - --log-level ${cfg.logLevel} - ''; - Restart = "always"; - RuntimeDirectory = "netbird-mgmt"; - StateDirectory = "netbird-mgmt"; - WorkingDirectory = cfg.dataDir; - }; - unitConfig = { - StartLimitInterval = 5; - StartLimitBurst = 10; - }; - stopIfChanged = false; - }; - - netbird-management = { - description = "The management server for Netbird, a wireguard VPN"; - documentation = [ "https://netbird.io/docs/" ]; - after = [ - "network.target" - "netbird-setup.service" - ]; - wantedBy = [ "multi-user.target" ]; - wants = [ - "netbird-signal.service" - "netbird-setup.service" - ]; - restartTriggers = [ - settingsFile - managementFile - ]; - - serviceConfig = { - ExecStart = '' - ${cfg.package}/bin/netbird-mgmt management \ - --config ${stateDir}/management.json \ - --datadir ${stateDir}/data \ - ${optionalString cfg.management.disableAnonymousMetrics "--disable-anonymous-metrics"} \ - ${optionalString cfg.management.disableSingleAccountMode "--disable-single-account-mode"} \ - --dns-domain ${cfg.management.dnsDomain} \ - --single-account-mode-domain ${cfg.management.singleAccountModeDomain} \ - --idp-sign-key-refresh-enabled \ - --port ${builtins.toString cfg.ports.management} \ - --log-file console \ - --log-level ${cfg.logLevel} - ''; - Restart = "always"; - RuntimeDirectory = "netbird-mgmt"; - StateDirectory = [ - "netbird-mgmt" - "netbird-mgmt/data" - ]; - WorkingDirectory = stateDir; - }; - unitConfig = { - StartLimitInterval = 5; - StartLimitBurst = 10; - }; - stopIfChanged = false; + unitConfig = { + StartLimitInterval = 5; + StartLimitBurst = 10; }; + stopIfChanged = false; + }; + + netbird-management = { + description = "The management server for Netbird, a wireguard VPN"; + documentation = ["https://netbird.io/docs/"]; + after = [ + "network.target" + "netbird-setup.service" + ]; + wantedBy = ["multi-user.target"]; + wants = [ + "netbird-signal.service" + "netbird-setup.service" + ]; + restartTriggers = [ + configFile + ]; + + serviceConfig = { + ExecStart = '' + ${cfg.package}/bin/netbird-mgmt management \ + --config ${configFile} \ + --datadir /var/lib/netbird-mgmt/data \ + --disable-anonymous-metrics \ + ${ + if cfg.singleAccountModeDomain == null + then "--disable-single-account-mode" + else "--single-account-mode-domain ${cfg.singleAccountModeDomain}" + } \ + --idp-sign-key-refresh-enabled \ + --port ${builtins.toString cfg.port} \ + --log-file consolef + ''; + # TODO add extraCOmmandLine option + Restart = "always"; + RuntimeDirectory = "netbird-mgmt"; + StateDirectory = [ + "netbird-mgmt" + "netbird-mgmt/data" + ]; + WorkingDirectory = "/var/lib/netbird-mgmt"; + }; + unitConfig = { + StartLimitInterval = 5; + StartLimitBurst = 10; + }; + stopIfChanged = false; }; - }) }; + }; } diff --git a/modules/services/kanidm.nix b/modules/services/kanidm.nix index ba3eba6..5dcc958 100644 --- a/modules/services/kanidm.nix +++ b/modules/services/kanidm.nix @@ -119,6 +119,8 @@ in { scopeMaps."immich.access" = ["openid" "email" "profile"]; preferShortUsername = true; }; + groups."netbird.access" = { + }; groups."forgejo.access" = { members = ["forgejo.admins"]; diff --git a/modules/services/netbird.nix b/modules/services/netbird.nix new file mode 100644 index 0000000..ac9fa7c --- /dev/null +++ b/modules/services/netbird.nix @@ -0,0 +1,68 @@ +{config, ...}: { + imports = [ + ../netbird-server.nix + ../netbird-dashboard.nix + ]; + wireguard.elisabeth = { + client.via = "elisabeth"; + firewallRuleForNode.elisabeth.allowedTCPPorts = [80 3000 3001]; + }; + + networking.firewall.allowedTCPPorts = [80 3000 3001]; + networking.firewall.allowedUDPPorts = [3478]; + services.netbird-dashboard = { + enable = true; + enableNginx = true; + domain = "netbird.${config.secrets.secrets.global.domains.web}"; + settings = { + AUTH_AUTHORITY = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird"; + AUTH_CLIENT_ID = "netbird"; + }; + }; + services.netbird-server = { + enable = true; + domain = "netbird.${config.secrets.secrets.global.domains.web}"; + # TODO remove + oidcConfigEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird/.well-known/openid-configuration"; + singleAccountModeDomain = "netbird.patrick"; + settings = { + HttpConfig = { + AuthIssuer = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird"; + AuthKeysLocation = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird/public_key.jwk"; + }; + # Seems to be only useful for idp that netbird supports + IdpManagerConfig.ClientConfig = { + Issuer = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/openid/netbird"; + TokenEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token"; + }; + DeviceAuthorizationFlow = { + Provider = "none"; + ProviderConfig = { + AuthorizationEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/ui/oauth2/"; + ClientID = "netbird"; + #ClientSecret = ""; + TokenEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/oauth2/token"; + #RedirectURLs = ["http://localhost:53000"]; + }; + }; + PKCEAuthorizationFlow.ProviderConfig = { + AuthorizationEndpoint = "https://auth.${config.secrets.secrets.global.domains.web}/ui/oauth2/"; + }; + }; + }; + services.coturn = { + enable = true; + + realm = "netbird.${config.secrets.secrets.global.domains.web}"; + lt-cred-mech = true; + no-cli = true; + + extraConfig = '' + fingerprint + + user=turn:netbird + no-software-attribute + external-ip=87.170.9.213 + ''; + }; +} diff --git a/secrets/secrets.nix.age b/secrets/secrets.nix.age index 81f6c19..5330234 100644 Binary files a/secrets/secrets.nix.age and b/secrets/secrets.nix.age differ diff --git a/secrets/wireguard/elisabeth/keys/elisabeth-netbird.age b/secrets/wireguard/elisabeth/keys/elisabeth-netbird.age new file mode 100644 index 0000000..1029bf0 --- /dev/null +++ b/secrets/wireguard/elisabeth/keys/elisabeth-netbird.age @@ -0,0 +1,16 @@ +age-encryption.org/v1 +-> X25519 zghXrLqQhlVqAAbMi1k8gvG5IjG9boIJCyEx63DwwGo +/ae8dzj7mPxZdpciA+lLiR6H/WCrIvTkUfaXGP+RZiY +-> piv-p256 XTQkUA A4PgmdpN1WmH++JUTIdADZBqDrCQ2N8HP9FzQ7DtyJuU +CIzSKNP8YYYfMycueE564094XeKJ9mNEceAuUEnvFFI +-> piv-p256 ZFgiIw AgxtRiqyF4Fo6Us/l8vXhWl2tQakCQGwd1Dogf/Wqnyv +Gi9O1lFR2hhfkXoC7cmlpT+iHx0DxeDFmuU9i+Gc4Ms +-> piv-p256 5vmPtQ AsbmH20Pc58VF7tBnoE5iqzlrsahCDTHkvuyAQ4W5SPy +BcJr9QsIDanypSNZ0UWrt0VnJK99LM0FOmCQWc+2rPY +-> piv-p256 ZFgiIw A5CT86jvz263c1GoDrtGVBXZx9EZeQwCL2d/tCXGqay3 +8kHhsuD77fPPLPe8JYTuHNcCtp0VJcdrTg220BVdyGc +-> v-"@h-grease sJN %C \ ?mh0`=L +FarOmtacPX3pzMNzucQdNxI8MpVZdumJghhEPiukRJxp5+3InvEp7lvBhtZv49i3 +QPoKNFjUweN6aXA9Vs1cpSQ +--- k49nSQRFr22Pc4QtH0WlYQ2/yMpBXSJasmQ97ZcxLkU +^shʏLv++'8{ZC}ZPQ0U$:Y1NO l' \ No newline at end of file diff --git a/secrets/wireguard/elisabeth/keys/elisabeth-netbird.pub b/secrets/wireguard/elisabeth/keys/elisabeth-netbird.pub new file mode 100644 index 0000000..9ef8bfe --- /dev/null +++ b/secrets/wireguard/elisabeth/keys/elisabeth-netbird.pub @@ -0,0 +1 @@ +yv8nqlqgBxDIf6oYrn01FRKoKnqZPfdenWIFHxfSLiA= diff --git a/secrets/wireguard/elisabeth/psks/elisabeth+elisabeth-netbird.age b/secrets/wireguard/elisabeth/psks/elisabeth+elisabeth-netbird.age new file mode 100644 index 0000000..d7e79b7 --- /dev/null +++ b/secrets/wireguard/elisabeth/psks/elisabeth+elisabeth-netbird.age @@ -0,0 +1,16 @@ +age-encryption.org/v1 +-> X25519 bq+eQrKzKWG2cvp+7cKzpkN7KEbxf4H8aSOBxOBNeVE +uiZloroeAw+q0T9CTGbAg6cdHShGaa5YOVk0iE5FLMM +-> piv-p256 XTQkUA A5CqoI0rxRrOyHv6LksBqtzWPapfCLi6IdK3KAUATzJF +d3VMdZpw0TjU8kZ6WNLcbvenDD4WWxJp2rEogNnW43o +-> piv-p256 ZFgiIw Ah/2IZobkAFu0r0rSHvB9RyQhXh+wk1R9Vlky8J44xib +5GXXZuXybVXcrpU8G8bWYwMOjnzdw7X+YjQaQlA1F4E +-> piv-p256 5vmPtQ AjmJ3ZgFxcbSbGefvufWZNzo0nOc8vl+4jA7kb5kwSbI +2ks2FzxZ/YloeAVCRT/0NEo4hRWzUbknj+pnwtGuEZM +-> piv-p256 ZFgiIw ApvFPxETdpXGYLa9srv+pKFHNOGfa7ie8oyOInKDbOqC +8rIukUZzrkWdH11pnTYfPd259ql/UGg5/Z6SuNvslUA +-> X=N9-grease CPXXj9j! Mf6?oC AuDyAWo z5x1TGOh +CYoYan7n +--- 9xwTgosTBqh7i3YCpHUhvkYV6bormJ3hYP4WHTwwQk4 +Iy0[۞$ތ- :k@ }9  +2l'*ԭ[Sr$*WjB,-wR1B&!.@ \ No newline at end of file