Files
2026-05-02 12:52:08 +02:00

203 lines
6.2 KiB
Nix

{ 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}";
};
};
}