{ config, pkgs, lib, ... }: with lib; let # Container config name = "netbird"; # Version tagging netbirdDashboardVersion = ""; netbirdServerVersion = ""; # Helper helper = import ../service-helper.nix { inherit config pkgs lib; }; cfg = config.numbus-server.services.netbird; in helper.mkPodmanService { inherit name; pod = "false"; description = "NetBird, an all-in-one ZTNA remote access platform"; defaultPort = "8888"; reverseProxied = false; dependencies = [ "sops-install-secrets.service" "traefik.service" "${config.numbus-server.services.dns}.service" ]; dirPermissions = [ "100999:100 ${cfg.configDir}" ]; secrets = [ "netbird/auth_key" "netbird/encryption_key" ]; composeText = '' services: netbird-dashboard: image: netbirdio/dashboard:${netbirdDashboardVersion} container_name: netbird-dashboard hostname: netbird-dashboard user: '1000:1000' networks: netbird: ipv4_address: 10.89.175.253 ports: - "${defaultPort}:8080/tcp" environment: # Endpoints - NETBIRD_MGMT_API_ENDPOINT=https://${cfg.subdomain}.${config.numbus-server.services.domain} - NETBIRD_MGMT_GRPC_API_ENDPOINT=https://${cfg.subdomain}.${config.numbus-server.services.domain} # OIDC - using embedded IdP - AUTH_AUDIENCE=netbird-dashboard - AUTH_CLIENT_ID=netbird-dashboard - AUTH_CLIENT_SECRET= - AUTH_AUTHORITY=https://${cfg.subdomain}.${config.numbus-server.services.domain}/oauth2 - USE_AUTH0=false - AUTH_SUPPORTED_SCOPES=openid profile email groups - AUTH_REDIRECT_URI=/nb-auth - AUTH_SILENT_REDIRECT_URI=/nb-silent-auth # SSL - NGINX_SSL_PORT=443 - LETSENCRYPT_DOMAIN=none logging: driver: "json-file" options: max-size: "500m" max-file: "2" security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped netbird-server: image: netbirdio/netbird-server:${netbirdServerVersion} container_name: netbird-server hostname: netbird-server user: '1000:1000' networks: netbird: ipv4_address: 10.89.175.252 ports: - "8889:8081/tcp" - "3478:3478/udp" volumes: - ${config.sops.templates."netbird-config".path}:/etc/netbird/config.yaml - ${cfg.configDir}:/var/lib/netbird command: ["--config", "/etc/netbird/config.yaml"] logging: driver: "json-file" options: max-size: "500m" max-file: "2" security_opt: - no-new-privileges:true cap_drop: - NET_RAW restart: unless-stopped networks: netbird: driver: bridge name: netbird ipam: config: - subnet: "10.89.175.0/24" gateway: "10.89.175.254" ''; extraConfig = { sops.templates."netbird-config" = { gid = "100"; uid = "100999"; mode = "0400"; content = '' server: listenAddress: ":80" exposedAddress: "https://${cfg.subdomain}.${config.numbus-server.services.domain}:443" stunPorts: - 3478 metricsPort: 9090 healthcheckAddress: ":9000" logLevel: "info" logFile: "console" authSecret: "${config.sops.placeholder."netbird/auth_key"}" dataDir: "/var/lib/netbird" auth: issuer: "https://${cfg.subdomain}.${config.numbus-server.services.domain}/oauth2" signKeyRefreshEnabled: true dashboardRedirectURIs: - "https://${cfg.subdomain}.${config.numbus-server.services.domain}/nb-auth" - "https://${cfg.subdomain}.${config.numbus-server.services.domain}/nb-silent-auth" cliRedirectURIs: - "http://localhost:53000/" reverseProxy: trustedHTTPProxies: - "10.89.175.1/32" store: engine: "sqlite" encryptionKey: "${config.sops.placeholder."netbird/encryption_key"}" ''; path = "/etc/netbird/netbird.yaml"; }; sops.templates."traefik/rules/${name}" = { gid = "100"; uid = "1000"; mode = "0400"; content = '' http: routers: ${name}-dashboard: rule: "Host(`${cfg.subdomain}.${config.numbus-server.services.domain}`)" entrypoints: - "websecure" middlewares: - secureHeaders tls: certresolver: "cloudflare" options: "secureTLS" priority: 1 ${name}-grpc: rule: "Host(`${cfg.subdomain}.${config.numbus-server.services.domain}`) && (PathPrefix(`/signalexchange.SignalExchange/`) || PathPrefix(`/management.ManagementService/`))" entrypoints: - "websecure" service: ${name}-server-h2c middlewares: - secureHeaders tls: certresolver: "cloudflare" options: "secureTLS" ${name}-backend: rule: "Host(`${cfg.subdomain}.${config.numbus-server.services.domain}`) && (PathPrefix(`/relay`) || PathPrefix(`/ws-proxy/`) || PathPrefix(`/api`) || PathPrefix(`/oauth2`))" entrypoints: - "websecure" service: ${name}-server middlewares: - secureHeaders tls: certresolver: "cloudflare" options: "secureTLS" services:${cfg.port} ${name}-dashboard: loadBalancer: servers: - url: "http://host.containers.internal:${cfg.port}" ${name}-server: loadBalancer: servers: - url: "http://host.containers.internal:8889" ${name}-server-h2c: loadBalancer: servers: - url: "h2c://host.containers.internal:3478" ''; path = "/etc/traefik/rules/${name}"; }; }; }