x-default: &default restart: 'unless-stopped' logging: driver: 'json-file' options: max-size: '500m' max-file: '2' services: # Caddy reverse proxy caddy: <<: *default image: caddy:2 networks: [netbird] ports: - '443:443' - '443:443/udp' - '80:80' volumes: - netbird-caddy-data:/data - ./Caddyfile:/etc/caddy/Caddyfile:ro depends_on: zitadel: condition: service_healthy # UI dashboard dashboard: <<: *default image: netbirdio/dashboard:$NETBIRD_DASHBOARD_TAG networks: [netbird] environment: - NETBIRD_MGMT_API_ENDPOINT=$NETBIRD_MGMT_API_ENDPOINT - NETBIRD_MGMT_GRPC_API_ENDPOINT=$NETBIRD_MGMT_API_ENDPOINT - AUTH_AUDIENCE=$NETBIRD_AUTH_CLIENT_ID - AUTH_CLIENT_ID=$NETBIRD_AUTH_CLIENT_ID - AUTH_CLIENT_SECRET= - AUTH_AUTHORITY=$NETBIRD_AUTH_AUTHORITY - USE_AUTH0=false - AUTH_SUPPORTED_SCOPES=$NETBIRD_AUTH_SUPPORTED_SCOPES - AUTH_REDIRECT_URI=/nb-auth - AUTH_SILENT_REDIRECT_URI=/nb-silent-auth - NETBIRD_TOKEN_SOURCE=$NETBIRD_TOKEN_SOURCE - NGINX_SSL_PORT=443 - LETSENCRYPT_DOMAIN=none depends_on: zitadel: condition: service_healthy # Signal signal: <<: *default image: netbirdio/signal:$NETBIRD_SIGNAL_TAG networks: [netbird] volumes: - $SIGNAL_VOLUMENAME:/var/lib/netbird command: ["--log-file", "console"] # Relay relay: <<: *default image: netbirdio/relay:$NETBIRD_RELAY_TAG networks: [netbird] environment: - NB_LOG_LEVEL=info - NB_LISTEN_ADDRESS=:$NETBIRD_RELAY_INTERNAL_PORT - NB_EXPOSED_ADDRESS=$NETBIRD_RELAY_ENDPOINT - NB_AUTH_SECRET=$NETBIRD_RELAY_AUTH_SECRET # Management management: <<: *default image: netbirdio/management:$NETBIRD_MANAGEMENT_TAG networks: [netbird] volumes: - $MGMT_VOLUMENAME:/var/lib/netbird - ./management.json:/etc/netbird/management.json command: [ "--port", "80", "--log-file", "console", "--log-level", "info", "--disable-anonymous-metrics=$NETBIRD_DISABLE_ANONYMOUS_METRICS", "--single-account-mode-domain=$NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN", "--dns-domain=$NETBIRD_MGMT_DNS_DOMAIN", "--idp-sign-key-refresh-enabled" ] environment: - NETBIRD_STORE_ENGINE_POSTGRES_DSN=$NETBIRD_STORE_ENGINE_POSTGRES_DSN - NETBIRD_STORE_ENGINE_MYSQL_DSN=$NETBIRD_STORE_ENGINE_MYSQL_DSN depends_on: zitadel: condition: service_healthy # Coturn coturn: <<: *default image: coturn/coturn:$COTURN_TAG volumes: - ./turnserver.conf:/etc/turnserver.conf:ro network_mode: host command: - -c /etc/turnserver.conf # Zitadel Identity Provider (single container with SQLite) zitadel: <<: *default image: ghcr.io/zitadel/zitadel:$ZITADEL_TAG networks: [netbird] command: 'start-from-init --masterkeyFromEnv --tlsMode $ZITADEL_TLS_MODE' environment: - ZITADEL_LOG_LEVEL=info - ZITADEL_MASTERKEY=$ZITADEL_MASTERKEY - ZITADEL_EXTERNALSECURE=$ZITADEL_EXTERNALSECURE - ZITADEL_TLS_ENABLED=false - ZITADEL_EXTERNALPORT=$ZITADEL_EXTERNALPORT - ZITADEL_EXTERNALDOMAIN=$NETBIRD_DOMAIN # SQLite database (no separate PostgreSQL container needed) - ZITADEL_DATABASE_SQLITE_PATH=/data/zitadel.db # First instance: Admin user - ZITADEL_FIRSTINSTANCE_ORG_HUMAN_USERNAME=$ZITADEL_ADMIN_USERNAME - ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORD=$ZITADEL_ADMIN_PASSWORD - ZITADEL_FIRSTINSTANCE_ORG_HUMAN_PASSWORDCHANGEREQUIRED=true # First instance: Service account for NetBird management - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME=netbird-service - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME=NetBird Service Account - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINEKEY_TYPE=1 - ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE=$ZITADEL_PAT_EXPIRATION volumes: - netbird-zitadel-data:/data healthcheck: test: ["CMD", "/app/zitadel", "ready"] interval: 10s timeout: 5s retries: 5 start_period: 30s volumes: $MGMT_VOLUMENAME: $SIGNAL_VOLUMENAME: netbird-caddy-data: netbird-zitadel-data: networks: netbird: