Netbird/docker-compose.yml

291 lines
12 KiB
YAML
Raw Permalink Normal View History

2025-11-23 18:38:45 +00:00
services:
# UI dashboard
dashboard:
image: netbirdio/dashboard:latest
restart: unless-stopped
networks:
- netbird
- traefik_traefik
env_file:
- ./dashboard.env
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.services.netbird-dashboard.loadbalancer.server.port=80
- traefik.http.routers.netbird-dashboard.rule=Host(`netbird.rozic-dev.com`)
- traefik.http.routers.netbird-dashboard.entrypoints=websecure
- traefik.http.routers.netbird-dashboard.tls=true
- traefik.http.routers.netbird-dashboard.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-dashboard.priority=50
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Signal
signal:
image: netbirdio/signal:latest
restart: unless-stopped
networks:
- netbird
- traefik_traefik
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.services.netbird-signal.loadbalancer.server.port=10000
- traefik.http.services.netbird-signal.loadbalancer.server.scheme=h2c
- traefik.http.routers.netbird-signal.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/signalexchange.SignalExchange/`)
- traefik.http.routers.netbird-signal.entrypoints=websecure
- traefik.http.routers.netbird-signal.service=netbird-signal
- traefik.http.routers.netbird-signal.tls=true
- traefik.http.routers.netbird-signal.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-signal.priority=200
# WebSocket route for signal - pass through without stripping prefix
- traefik.http.services.netbird-signal-ws.loadbalancer.server.port=80
- traefik.http.routers.netbird-signal-ws.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/ws-proxy/signal`)
- traefik.http.routers.netbird-signal-ws.entrypoints=websecure
- traefik.http.routers.netbird-signal-ws.service=netbird-signal-ws
- traefik.http.routers.netbird-signal-ws.tls=true
- traefik.http.routers.netbird-signal-ws.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-signal-ws.priority=300
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Relay
relay:
image: netbirdio/relay:latest
restart: unless-stopped
networks:
- netbird
- traefik_traefik
env_file:
- ./relay.env
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.services.netbird-relay.loadbalancer.server.port=33080
- traefik.http.routers.netbird-relay.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/relay`)
- traefik.http.routers.netbird-relay.entrypoints=websecure
- traefik.http.routers.netbird-relay.tls=true
- traefik.http.routers.netbird-relay.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-relay.priority=200
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Management
management:
image: netbirdio/management:latest
restart: unless-stopped
networks:
- netbird
- traefik_traefik
volumes:
- netbird_management:/var/lib/netbird
- ./management.json:/etc/netbird/management.json
command: [
"--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.docker.network=traefik_default
- traefik.http.services.netbird-management.loadbalancer.server.port=80
- traefik.http.services.netbird-management-grpc.loadbalancer.server.port=80
- traefik.http.services.netbird-management-grpc.loadbalancer.server.scheme=h2c
# REST API
- traefik.http.routers.netbird-api.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/api`)
- traefik.http.routers.netbird-api.entrypoints=websecure
- traefik.http.routers.netbird-api.service=netbird-management
- traefik.http.routers.netbird-api.tls=true
- traefik.http.routers.netbird-api.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-api.priority=200
# gRPC
- traefik.http.routers.netbird-management-grpc.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/management.ManagementService/`)
- traefik.http.routers.netbird-management-grpc.entrypoints=websecure
- traefik.http.routers.netbird-management-grpc.service=netbird-management-grpc
- traefik.http.routers.netbird-management-grpc.tls=true
- traefik.http.routers.netbird-management-grpc.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-management-grpc.priority=200
# WebSocket route for management
- traefik.http.routers.netbird-management-ws.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/ws-proxy/management`)
- traefik.http.routers.netbird-management-ws.entrypoints=websecure
- traefik.http.routers.netbird-management-ws.service=netbird-management
- traefik.http.routers.netbird-management-ws.tls=true
- traefik.http.routers.netbird-management-ws.tls.certresolver=letsencrypt
- traefik.http.routers.netbird-management-ws.priority=300
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Coturn
coturn:
image: coturn/coturn
restart: unless-stopped
volumes:
- ./turnserver.conf:/etc/turnserver.conf:ro
network_mode: host
command:
- -c /etc/turnserver.conf
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Zitadel - identity provider
zitadel:
restart: 'always'
image: 'ghcr.io/zitadel/zitadel:v2.59.3'
command: 'start-from-init --masterkeyFromEnv --tlsMode external'
ports:
- "8085:8080" # <-- added
env_file:
- ./zitadel.env
environment:
ZITADEL_PROJECTIONS_MAXFAILURES: "3"
ZITADEL_PROJECTIONS_RETRYDELAY: "2s"
ZITADEL_PROJECTIONS_MAXPARALLELPROJECTIONS: "4"
ZITADEL_PROJECTIONS_TARGETS1_PARALLEL_PREFILLS: "2"
ZITADEL_PROJECTIONS_TARGETS1_BATCHSIZE: "500"
depends_on:
zdb:
condition: 'service_healthy'
volumes:
- ./machinekey:/machinekey
- netbird_zitadel_certs:/zdb-certs:ro
networks:
- netbird
- traefik_traefik
labels:
- traefik.enable=true
- traefik.docker.network=traefik_default
- traefik.http.services.zitadel.loadbalancer.server.port=8080
- traefik.http.services.zitadel.loadbalancer.server.scheme=h2c
# OIDC wellknown
- traefik.http.routers.zitadel-wellknown.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/.well-known`)
- traefik.http.routers.zitadel-wellknown.entrypoints=websecure
- traefik.http.routers.zitadel-wellknown.service=zitadel
- traefik.http.routers.zitadel-wellknown.priority=300
- traefik.http.routers.zitadel-wellknown.tls=true
- traefik.http.routers.zitadel-wellknown.tls.certresolver=letsencrypt
# OAuth
- traefik.http.routers.zitadel-oauth.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/oauth`)
- traefik.http.routers.zitadel-oauth.entrypoints=websecure
- traefik.http.routers.zitadel-oauth.service=zitadel
- traefik.http.routers.zitadel-oauth.priority=300
- traefik.http.routers.zitadel-oauth.tls=true
- traefik.http.routers.zitadel-oauth.tls.certresolver=letsencrypt
# OIDC
- traefik.http.routers.zitadel-oidc.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/oidc`)
- traefik.http.routers.zitadel-oidc.entrypoints=websecure
- traefik.http.routers.zitadel-oidc.service=zitadel
- traefik.http.routers.zitadel-oidc.priority=300
- traefik.http.routers.zitadel-oidc.tls=true
- traefik.http.routers.zitadel-oidc.tls.certresolver=letsencrypt
# UI Console
- traefik.http.routers.zitadel-ui.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/ui`)
- traefik.http.routers.zitadel-ui.entrypoints=websecure
- traefik.http.routers.zitadel-ui.service=zitadel
- traefik.http.routers.zitadel-ui.priority=300
- traefik.http.routers.zitadel-ui.tls=true
- traefik.http.routers.zitadel-ui.tls.certresolver=letsencrypt
# Device flow
- traefik.http.routers.zitadel-device.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/device`)
- traefik.http.routers.zitadel-device.entrypoints=websecure
- traefik.http.routers.zitadel-device.service=zitadel
- traefik.http.routers.zitadel-device.priority=300
- traefik.http.routers.zitadel-device.tls=true
- traefik.http.routers.zitadel-device.tls.certresolver=letsencrypt
# Management API
- traefik.http.routers.zitadel-mgmt.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/management/v1`)
- traefik.http.routers.zitadel-mgmt.entrypoints=websecure
- traefik.http.routers.zitadel-mgmt.service=zitadel
- traefik.http.routers.zitadel-mgmt.priority=300
- traefik.http.routers.zitadel-mgmt.tls=true
- traefik.http.routers.zitadel-mgmt.tls.certresolver=letsencrypt
# Admin API
- traefik.http.routers.zitadel-admin.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/admin/v1`)
- traefik.http.routers.zitadel-admin.entrypoints=websecure
- traefik.http.routers.zitadel-admin.service=zitadel
- traefik.http.routers.zitadel-admin.priority=300
- traefik.http.routers.zitadel-admin.tls=true
- traefik.http.routers.zitadel-admin.tls.certresolver=letsencrypt
# gRPC endpoints
- traefik.http.routers.zitadel-grpc-auth.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/zitadel.auth.v1.AuthService/`)
- traefik.http.routers.zitadel-grpc-auth.entrypoints=websecure
- traefik.http.routers.zitadel-grpc-auth.service=zitadel
- traefik.http.routers.zitadel-grpc-auth.priority=400
- traefik.http.routers.zitadel-grpc-auth.tls=true
- traefik.http.routers.zitadel-grpc-auth.tls.certresolver=letsencrypt
- traefik.http.routers.zitadel-grpc-admin.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/zitadel.admin.v1.AdminService/`)
- traefik.http.routers.zitadel-grpc-admin.entrypoints=websecure
- traefik.http.routers.zitadel-grpc-admin.service=zitadel
- traefik.http.routers.zitadel-grpc-admin.priority=400
- traefik.http.routers.zitadel-grpc-admin.tls=true
- traefik.http.routers.zitadel-grpc-admin.tls.certresolver=letsencrypt
- traefik.http.routers.zitadel-grpc-mgmt.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/zitadel.management.v1.ManagementService/`)
- traefik.http.routers.zitadel-grpc-mgmt.entrypoints=websecure
- traefik.http.routers.zitadel-grpc-mgmt.service=zitadel
- traefik.http.routers.zitadel-grpc-mgmt.priority=400
- traefik.http.routers.zitadel-grpc-mgmt.tls=true
- traefik.http.routers.zitadel-grpc-mgmt.tls.certresolver=letsencrypt
# === CRITICAL ROUTE: /auth/v1 for PAT + wait_api ===
- traefik.http.routers.zitadel-auth-v1.rule=Host(`netbird.rozic-dev.com`) && PathPrefix(`/auth/v1`)
- traefik.http.routers.zitadel-auth-v1.entrypoints=websecure
- traefik.http.routers.zitadel-auth-v1.service=zitadel
- traefik.http.routers.zitadel-auth-v1.tls=true
- traefik.http.routers.zitadel-auth-v1.tls.certresolver=letsencrypt
- traefik.http.routers.zitadel-auth-v1.priority=950
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
# Postgres for Zitadel
zdb:
restart: 'always'
networks: [netbird]
image: 'postgres:15-alpine'
env_file:
- ./zdb.env
volumes:
- netbird_zdb_data:/var/lib/postgresql/data:rw
healthcheck:
test: ["CMD-SHELL", "pg_isready -U root"]
interval: 5s
timeout: 60s
retries: 10
start_period: 5s
logging:
driver: "json-file"
options:
max-size: "500m"
max-file: "2"
volumes:
netbird_zdb_data:
netbird_management:
netbird_zitadel_certs:
networks:
netbird:
driver: bridge
traefik_traefik:
external: true
name: traefik_default