{ config, lib, pkgs, ... }: { options.sysconfig.docker.netbird.enable = with lib; mkOption { type = with types; bool; default = false; }; config = lib.mkIf (config.sysconfig.docker.netbird.enable && config.sysconfig.docker.enable) { networking.firewall.allowedUDPPorts = [ 3478 ]; sops.secrets."netbird/secret_key" = {}; sops.templates."netbird-relay.env" = { content = '' NB_AUTH_SECRET=${config.sops.placeholder."netbird/secret_key"} NB_LOG_LEVEL=info NB_LISTEN_ADDRESS=:80 NB_EXPOSED_ADDRESS=rels://vpn.esotericbytes.com:443 NB_ENABLE_STUN=true NB_STUN_LOG_LEVEL=info NB_STUN_PORTS=3478 ''; }; environment.etc."netbird/management.json".source = ./config/management.json; # Containers virtualisation.oci-containers.containers."netbird-dashboard" = { image = "netbirdio/dashboard:latest"; environment = { "AUTH_AUDIENCE" = "netbird-dashboard"; "AUTH_AUTHORITY" = "https://vpn.esotericbytes.com/oauth2"; "AUTH_CLIENT_ID" = "netbird-dashboard"; "AUTH_CLIENT_SECRET" = ""; "AUTH_REDIRECT_URI" = "/nb-auth"; "AUTH_SILENT_REDIRECT_URI" = "/nb-silent-auth"; "AUTH_SUPPORTED_SCOPES" = "openid profile email groups"; "LETSENCRYPT_DOMAIN" = "none"; "NETBIRD_MGMT_API_ENDPOINT" = "https://vpn.esotericbytes.com"; "NETBIRD_MGMT_GRPC_API_ENDPOINT" = "https://vpn.esotericbytes.com"; "NGINX_SSL_PORT" = "443"; "USE_AUTH0" = "false"; }; labels = { "traefik.enable" = "true"; "traefik.http.routers.netbird-dashboard.entrypoints" = "websecure"; "traefik.http.routers.netbird-dashboard.priority" = "1"; "traefik.http.routers.netbird-dashboard.rule" = "Host(`vpn.esotericbytes.com`)"; "traefik.http.routers.netbird-dashboard.tls" = "true"; "traefik.http.services.netbird-dashboard.loadbalancer.server.port" = "80"; }; log-driver = "journald"; extraOptions = [ "--network-alias=dashboard" "--network=docker-main" ]; }; systemd.services."docker-netbird-dashboard" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; partOf = [ "docker-compose-netbird-root.target" ]; wantedBy = [ "docker-compose-netbird-root.target" ]; }; virtualisation.oci-containers.containers."netbird-management" = { image = "netbirdio/management:latest"; volumes = [ "/etc/netbird/management.json:/etc/netbird/management.json:rw" "netbird_netbird_management:/var/lib/netbird:rw" ]; cmd = [ "--port" "80" "--log-file" "console" "--log-level" "info" "--disable-anonymous-metrics=false" "--single-account-mode-domain=netbird.selfhosted" "--dns-domain=netbird.selfhosted" "--idp-sign-key-refresh-enabled" ]; labels = { "traefik.enable" = "true"; "traefik.http.routers.netbird-api.entrypoints" = "websecure"; "traefik.http.routers.netbird-api.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/api`)"; "traefik.http.routers.netbird-api.service" = "netbird-api"; "traefik.http.routers.netbird-api.tls" = "true"; "traefik.http.routers.netbird-mgmt-grpc.entrypoints" = "websecure"; "traefik.http.routers.netbird-mgmt-grpc.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/management.ManagementService/`)"; "traefik.http.routers.netbird-mgmt-grpc.service" = "netbird-mgmt-grpc"; "traefik.http.routers.netbird-mgmt-grpc.tls" = "true"; "traefik.http.routers.netbird-mgmt-ws.entrypoints" = "websecure"; "traefik.http.routers.netbird-mgmt-ws.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/ws-proxy/management`)"; "traefik.http.routers.netbird-mgmt-ws.service" = "netbird-mgmt-ws"; "traefik.http.routers.netbird-mgmt-ws.tls" = "true"; "traefik.http.routers.netbird-oauth2.entrypoints" = "websecure"; "traefik.http.routers.netbird-oauth2.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/oauth2`)"; "traefik.http.routers.netbird-oauth2.service" = "netbird-oauth2"; "traefik.http.routers.netbird-oauth2.tls" = "true"; "traefik.http.services.netbird-api.loadbalancer.server.port" = "80"; "traefik.http.services.netbird-mgmt-grpc.loadbalancer.server.port" = "80"; "traefik.http.services.netbird-mgmt-grpc.loadbalancer.server.scheme" = "h2c"; "traefik.http.services.netbird-mgmt-ws.loadbalancer.server.port" = "80"; "traefik.http.services.netbird-oauth2.loadbalancer.server.port" = "80"; }; log-driver = "journald"; extraOptions = [ "--network-alias=management" "--network=docker-main" ]; }; systemd.services."docker-netbird-management" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; after = [ "docker-volume-netbird_netbird_management.service" ]; requires = [ "docker-volume-netbird_netbird_management.service" ]; partOf = [ "docker-compose-netbird-root.target" ]; wantedBy = [ "docker-compose-netbird-root.target" ]; }; virtualisation.oci-containers.containers."netbird-relay" = { image = "netbirdio/relay:latest"; environmentFiles = [ config.sops.templates."netbird-relay.env".path ]; ports = [ "3478:3478/udp" ]; labels = { "traefik.enable" = "true"; "traefik.http.routers.netbird-relay.entrypoints" = "websecure"; "traefik.http.routers.netbird-relay.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/relay`)"; "traefik.http.routers.netbird-relay.tls" = "true"; "traefik.http.services.netbird-relay.loadbalancer.server.port" = "80"; }; log-driver = "journald"; extraOptions = [ "--network-alias=relay" "--network=docker-main" ]; }; systemd.services."docker-netbird-relay" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; partOf = [ "docker-compose-netbird-root.target" ]; wantedBy = [ "docker-compose-netbird-root.target" ]; }; virtualisation.oci-containers.containers."netbird-signal" = { image = "netbirdio/signal:latest"; labels = { "traefik.enable" = "true"; "traefik.http.routers.netbird-signal-grpc.entrypoints" = "websecure"; "traefik.http.routers.netbird-signal-grpc.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/signalexchange.SignalExchange/`)"; "traefik.http.routers.netbird-signal-grpc.service" = "netbird-signal-grpc"; "traefik.http.routers.netbird-signal-grpc.tls" = "true"; "traefik.http.routers.netbird-signal-ws.entrypoints" = "websecure"; "traefik.http.routers.netbird-signal-ws.rule" = "Host(`vpn.esotericbytes.com`) && PathPrefix(`/ws-proxy/signal`)"; "traefik.http.routers.netbird-signal-ws.service" = "netbird-signal-ws"; "traefik.http.routers.netbird-signal-ws.tls" = "true"; "traefik.http.services.netbird-signal-grpc.loadbalancer.server.port" = "10000"; "traefik.http.services.netbird-signal-grpc.loadbalancer.server.scheme" = "h2c"; "traefik.http.services.netbird-signal-ws.loadbalancer.server.port" = "80"; }; log-driver = "journald"; extraOptions = [ "--network-alias=signal" "--network=docker-main" ]; }; systemd.services."docker-netbird-signal" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; RestartMaxDelaySec = lib.mkOverride 90 "1m"; RestartSec = lib.mkOverride 90 "100ms"; RestartSteps = lib.mkOverride 90 9; }; partOf = [ "docker-compose-netbird-root.target" ]; wantedBy = [ "docker-compose-netbird-root.target" ]; }; # Volumes systemd.services."docker-volume-netbird_netbird_management" = { path = [ pkgs.docker ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' docker volume inspect netbird_netbird_management || docker volume create netbird_netbird_management ''; partOf = [ "docker-compose-netbird-root.target" ]; wantedBy = [ "docker-compose-netbird-root.target" ]; }; # Root service # When started, this will automatically create all resources and start # the containers. When stopped, this will teardown all resources. systemd.targets."docker-compose-netbird-root" = { unitConfig = { Description = "Root target generated by compose2nix."; }; wantedBy = [ "multi-user.target" ]; }; }; }