Compare commits
10 commits
1c95aa4769
...
947a1b016e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
947a1b016e | ||
|
|
4084a08b32 | ||
|
|
8a16ce0b71 | ||
|
|
31a7207d39 | ||
|
|
9c358de605 | ||
|
|
d9e514ec3e | ||
|
|
a6a1151c2c | ||
|
|
93e62529ed | ||
|
|
5364c40610 | ||
|
|
de674d7891 |
4
.env
Normal file
4
.env
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
Username: admin@netbird.rozic-dev.com
|
||||||
|
Password: Sx49nmh6YxC5SeojHn+b4ApVcQE0WfL1c+TwJm7e/NE@
|
||||||
|
NetBird_URL: https://netbird.rozic-dev.com
|
||||||
|
Zitadel_console: https://netbird.rozic-dev.com/ui/console
|
||||||
BIN
Netbird-compose-backup.tar.gz
Normal file
BIN
Netbird-compose-backup.tar.gz
Normal file
Binary file not shown.
12
dashboard.env
Normal file
12
dashboard.env
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
NETBIRD_MGMT_API_ENDPOINT=https://netbird.rozic-dev.com
|
||||||
|
NETBIRD_MGMT_GRPC_API_ENDPOINT=https://netbird.rozic-dev.com
|
||||||
|
AUTH_AUDIENCE=347529025415086083
|
||||||
|
AUTH_CLIENT_ID=347529025415086083
|
||||||
|
AUTH_AUTHORITY=https://netbird.rozic-dev.com
|
||||||
|
USE_AUTH0=false
|
||||||
|
AUTH_SUPPORTED_SCOPES=openid profile email offline_access
|
||||||
|
AUTH_REDIRECT_URI=/nb-auth
|
||||||
|
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth
|
||||||
|
NGINX_SSL_PORT=443
|
||||||
|
LETSENCRYPT_DOMAIN=none
|
||||||
|
NETBIRD_DOMAIN=netbird.rozic-dev.com
|
||||||
290
docker-compose.yml
Normal file
290
docker-compose.yml
Normal file
|
|
@ -0,0 +1,290 @@
|
||||||
|
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
|
||||||
292
install-netbird-traefik.sh
Normal file → Executable file
292
install-netbird-traefik.sh
Normal file → Executable file
|
|
@ -2,13 +2,17 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Configuration
|
# ============================================
|
||||||
|
# CONFIG
|
||||||
|
# ============================================
|
||||||
TRAEFIK_NETWORK="traefik_traefik"
|
TRAEFIK_NETWORK="traefik_traefik"
|
||||||
TRAEFIK_CERTRESOLVER="webssl"
|
TRAEFIK_CERTRESOLVER="letsencrypt"
|
||||||
NETBIRD_DOMAIN="netbird.domain.com"
|
NETBIRD_DOMAIN="netbird.rozic-dev.com"
|
||||||
export NETBIRD_DOMAIN
|
export NETBIRD_DOMAIN
|
||||||
|
|
||||||
# Error handling functions
|
# ============================================
|
||||||
|
# ERROR HANDLING HELPERS
|
||||||
|
# ============================================
|
||||||
handle_request_command_status() {
|
handle_request_command_status() {
|
||||||
PARSED_RESPONSE=$1
|
PARSED_RESPONSE=$1
|
||||||
FUNCTION_NAME=$2
|
FUNCTION_NAME=$2
|
||||||
|
|
@ -30,7 +34,9 @@ handle_zitadel_request_response() {
|
||||||
sleep 1
|
sleep 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Dependency checks
|
# ============================================
|
||||||
|
# DEPENDENCY CHECKS
|
||||||
|
# ============================================
|
||||||
check_jq() {
|
check_jq() {
|
||||||
if ! command -v jq &> /dev/null
|
if ! command -v jq &> /dev/null
|
||||||
then
|
then
|
||||||
|
|
@ -50,12 +56,13 @@ check_docker_compose() {
|
||||||
echo "docker compose"
|
echo "docker compose"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "docker-compose is not installed or not in PATH. Please follow the steps from the official guide: https://docs.docker.com/engine/install/" > /dev/stderr
|
echo "docker-compose is not installed or not in PATH. Please follow the steps from the official guide: https://docs.docker.com/engine/install/" > /dev/stderr
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Wait functions
|
# ============================================
|
||||||
|
# WAIT HELPERS
|
||||||
|
# ============================================
|
||||||
wait_pat() {
|
wait_pat() {
|
||||||
PAT_PATH=$1
|
PAT_PATH=$1
|
||||||
set +e
|
set +e
|
||||||
|
|
@ -77,40 +84,50 @@ wait_api() {
|
||||||
counter=1
|
counter=1
|
||||||
while true; do
|
while true; do
|
||||||
FLAGS="-s"
|
FLAGS="-s"
|
||||||
if [[ $counter -eq 45 ]]; then
|
if [[ $counter -eq 120 ]]; then
|
||||||
FLAGS="-v"
|
FLAGS="-v"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
curl $FLAGS --connect-timeout 5 -o /dev/null \
|
||||||
curl $FLAGS --fail --connect-timeout 1 -o /dev/null "$INSTANCE_URL/auth/v1/users/me" -H "Authorization: Bearer $PAT"
|
http://localhost:8085/auth/v1/users/me \
|
||||||
|
-H "Authorization: Bearer $PAT" 2>/dev/null
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
if [[ $counter -eq 45 ]]; then
|
if [[ $counter -eq 120 ]]; then
|
||||||
echo ""
|
echo "Zitadel still not ready via http://localhost:8085 after 120s – checking logs..."
|
||||||
echo "Unable to connect to Zitadel for more than 45s, please check the output above, your firewall rules and container logs"
|
docker logs netbird-compose-zitadel-1 --tail 50
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo -n " ."
|
echo -n " ."
|
||||||
sleep 1
|
sleep 2
|
||||||
counter=$((counter + 1))
|
counter=$((counter + 1))
|
||||||
done
|
done
|
||||||
echo " done"
|
echo " done"
|
||||||
set -e
|
set -e
|
||||||
}
|
}
|
||||||
|
|
||||||
# Zitadel API functions
|
# ============================================
|
||||||
|
# ZITADEL API HELPERS
|
||||||
|
# ============================================
|
||||||
create_new_project() {
|
create_new_project() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
PROJECT_NAME="NETBIRD"
|
PROJECT_NAME="NETBIRD"
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X POST "$INSTANCE_URL/management/v1/projects" \
|
curl -sS -X POST "$INSTANCE_URL/management/v1/projects" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"name": "'"$PROJECT_NAME"'"}'
|
-d '{"name": "'"$PROJECT_NAME"'"}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.id')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.id')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_project" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_project" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -119,12 +136,13 @@ create_new_project() {
|
||||||
create_new_application() {
|
create_new_application() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
APPLICATION_NAME=$3
|
PROJECT_ID=$3
|
||||||
BASE_REDIRECT_URL1=$4
|
APPLICATION_NAME=$4
|
||||||
BASE_REDIRECT_URL2=$5
|
BASE_REDIRECT_URL1=$5
|
||||||
LOGOUT_URL=$6
|
BASE_REDIRECT_URL2=$6
|
||||||
ZITADEL_DEV_MODE=$7
|
LOGOUT_URL=$7
|
||||||
DEVICE_CODE=$8
|
ZITADEL_DEV_MODE=$8
|
||||||
|
DEVICE_CODE=$9
|
||||||
|
|
||||||
if [[ $DEVICE_CODE == "true" ]]; then
|
if [[ $DEVICE_CODE == "true" ]]; then
|
||||||
GRANT_TYPES='["OIDC_GRANT_TYPE_AUTHORIZATION_CODE","OIDC_GRANT_TYPE_DEVICE_CODE","OIDC_GRANT_TYPE_REFRESH_TOKEN"]'
|
GRANT_TYPES='["OIDC_GRANT_TYPE_AUTHORIZATION_CODE","OIDC_GRANT_TYPE_DEVICE_CODE","OIDC_GRANT_TYPE_REFRESH_TOKEN"]'
|
||||||
|
|
@ -159,6 +177,16 @@ create_new_application() {
|
||||||
}'
|
}'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.clientId')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.clientId')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_application" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_application" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -167,7 +195,6 @@ create_new_application() {
|
||||||
create_service_user() {
|
create_service_user() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X POST "$INSTANCE_URL/management/v1/users/machine" \
|
curl -sS -X POST "$INSTANCE_URL/management/v1/users/machine" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
|
|
@ -179,6 +206,14 @@ create_service_user() {
|
||||||
"accessTokenType": "ACCESS_TOKEN_TYPE_JWT"
|
"accessTokenType": "ACCESS_TOKEN_TYPE_JWT"
|
||||||
}'
|
}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.userId')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.userId')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "create_service_user" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "create_service_user" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -188,13 +223,20 @@ create_service_user_secret() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
USER_ID=$3
|
USER_ID=$3
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X PUT "$INSTANCE_URL/management/v1/users/$USER_ID/secret" \
|
curl -sS -X PUT "$INSTANCE_URL/management/v1/users/$USER_ID/secret" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{}'
|
-d '{}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
SERVICE_USER_CLIENT_ID=$(echo "$RESPONSE" | jq -r '.clientId')
|
SERVICE_USER_CLIENT_ID=$(echo "$RESPONSE" | jq -r '.clientId')
|
||||||
handle_zitadel_request_response "$SERVICE_USER_CLIENT_ID" "create_service_user_secret_id" "$RESPONSE"
|
handle_zitadel_request_response "$SERVICE_USER_CLIENT_ID" "create_service_user_secret_id" "$RESPONSE"
|
||||||
SERVICE_USER_CLIENT_SECRET=$(echo "$RESPONSE" | jq -r '.clientSecret')
|
SERVICE_USER_CLIENT_SECRET=$(echo "$RESPONSE" | jq -r '.clientSecret')
|
||||||
|
|
@ -205,7 +247,6 @@ add_organization_user_manager() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
USER_ID=$3
|
USER_ID=$3
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X POST "$INSTANCE_URL/management/v1/orgs/me/members" \
|
curl -sS -X POST "$INSTANCE_URL/management/v1/orgs/me/members" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
|
|
@ -217,6 +258,14 @@ add_organization_user_manager() {
|
||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.creationDate')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.creationDate')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "add_organization_user_manager" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "add_organization_user_manager" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -245,6 +294,14 @@ create_admin_user() {
|
||||||
"passwordChangeRequired": true
|
"passwordChangeRequired": true
|
||||||
}'
|
}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.userId')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.userId')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "create_admin_user" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "create_admin_user" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -254,7 +311,6 @@ add_instance_admin() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
USER_ID=$3
|
USER_ID=$3
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X POST "$INSTANCE_URL/admin/v1/members" \
|
curl -sS -X POST "$INSTANCE_URL/admin/v1/members" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
|
|
@ -266,6 +322,14 @@ add_instance_admin() {
|
||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.creationDate')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.creationDate')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "add_instance_admin" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "add_instance_admin" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
|
|
@ -274,34 +338,57 @@ add_instance_admin() {
|
||||||
delete_auto_service_user() {
|
delete_auto_service_user() {
|
||||||
INSTANCE_URL=$1
|
INSTANCE_URL=$1
|
||||||
PAT=$2
|
PAT=$2
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X GET "$INSTANCE_URL/auth/v1/users/me" \
|
curl -sS -X GET "$INSTANCE_URL/auth/v1/users/me" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
USER_ID=$(echo "$RESPONSE" | jq -r '.user.id')
|
USER_ID=$(echo "$RESPONSE" | jq -r '.user.id')
|
||||||
handle_zitadel_request_response "$USER_ID" "delete_auto_service_user_get_user" "$RESPONSE"
|
handle_zitadel_request_response "$USER_ID" "delete_auto_service_user_get_user" "$RESPONSE"
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X DELETE "$INSTANCE_URL/admin/v1/members/$USER_ID" \
|
curl -sS -X DELETE "$INSTANCE_URL/admin/v1/members/$USER_ID" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.changeDate')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.changeDate')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_instance_permissions" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_instance_permissions" "$RESPONSE"
|
||||||
|
|
||||||
RESPONSE=$(
|
RESPONSE=$(
|
||||||
curl -sS -X DELETE "$INSTANCE_URL/management/v1/orgs/me/members/$USER_ID" \
|
curl -sS -X DELETE "$INSTANCE_URL/management/v1/orgs/me/members/$USER_ID" \
|
||||||
-H "Authorization: Bearer $PAT" \
|
-H "Authorization: Bearer $PAT" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
)
|
)
|
||||||
|
# Log the full response for debugging
|
||||||
|
echo "$RESPONSE" >> zitadel_api.log
|
||||||
|
# Check if response is valid JSON
|
||||||
|
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" >> zitadel_api.log
|
||||||
|
echo "ERROR: Invalid response from Zitadel API: $RESPONSE" > /dev/stderr
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.changeDate')
|
PARSED_RESPONSE=$(echo "$RESPONSE" | jq -r '.details.changeDate')
|
||||||
handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_org_permissions" "$RESPONSE"
|
handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_org_permissions" "$RESPONSE"
|
||||||
echo "$PARSED_RESPONSE"
|
echo "$PARSED_RESPONSE"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get external IP for TURN server
|
# ============================================
|
||||||
|
# TURN IP
|
||||||
|
# ============================================
|
||||||
get_turn_external_ip() {
|
get_turn_external_ip() {
|
||||||
TURN_EXTERNAL_IP_CONFIG="#external-ip="
|
TURN_EXTERNAL_IP_CONFIG="#external-ip="
|
||||||
IP=$(curl -s -4 https://jsonip.com | jq -r '.ip')
|
IP=$(curl -s -4 https://jsonip.com | jq -r '.ip')
|
||||||
|
|
@ -311,15 +398,18 @@ get_turn_external_ip() {
|
||||||
echo "$TURN_EXTERNAL_IP_CONFIG"
|
echo "$TURN_EXTERNAL_IP_CONFIG"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main initialization function
|
# ============================================
|
||||||
|
# MAIN
|
||||||
|
# ============================================
|
||||||
main() {
|
main() {
|
||||||
|
# Clear log file
|
||||||
|
> zitadel_api.log
|
||||||
|
|
||||||
echo "Initializing NetBird with Traefik..."
|
echo "Initializing NetBird with Traefik..."
|
||||||
|
|
||||||
# Check dependencies
|
|
||||||
check_jq
|
check_jq
|
||||||
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
||||||
|
|
||||||
# Check if files already exist
|
|
||||||
if [ -f zitadel.env ]; then
|
if [ -f zitadel.env ]; then
|
||||||
echo "Generated files already exist, if you want to reinitialize the environment, please remove them first."
|
echo "Generated files already exist, if you want to reinitialize the environment, please remove them first."
|
||||||
echo "You can use the following commands:"
|
echo "You can use the following commands:"
|
||||||
|
|
@ -329,7 +419,7 @@ main() {
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate passwords and secrets
|
# === Generate passwords & secrets ===
|
||||||
ZITADEL_MASTERKEY="$(openssl rand -base64 32 | head -c 32)"
|
ZITADEL_MASTERKEY="$(openssl rand -base64 32 | head -c 32)"
|
||||||
POSTGRES_ROOT_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@"
|
POSTGRES_ROOT_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@"
|
||||||
POSTGRES_ZITADEL_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@"
|
POSTGRES_ZITADEL_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@"
|
||||||
|
|
@ -347,7 +437,7 @@ main() {
|
||||||
|
|
||||||
echo "Generating configuration files..."
|
echo "Generating configuration files..."
|
||||||
|
|
||||||
# Generate zitadel.env
|
# === zitadel.env ===
|
||||||
cat > zitadel.env <<EOF
|
cat > zitadel.env <<EOF
|
||||||
ZITADEL_LOG_LEVEL=debug
|
ZITADEL_LOG_LEVEL=debug
|
||||||
ZITADEL_MASTERKEY=$ZITADEL_MASTERKEY
|
ZITADEL_MASTERKEY=$ZITADEL_MASTERKEY
|
||||||
|
|
@ -372,13 +462,13 @@ ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable
|
||||||
NETBIRD_DOMAIN=$NETBIRD_DOMAIN
|
NETBIRD_DOMAIN=$NETBIRD_DOMAIN
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Generate zdb.env
|
# === zdb.env ===
|
||||||
cat > zdb.env <<EOF
|
cat > zdb.env <<EOF
|
||||||
POSTGRES_USER=root
|
POSTGRES_USER=root
|
||||||
POSTGRES_PASSWORD=$POSTGRES_ROOT_PASSWORD
|
POSTGRES_PASSWORD=$POSTGRES_ROOT_PASSWORD
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Generate turnserver.conf
|
# === turnserver.conf ===
|
||||||
cat > turnserver.conf <<EOF
|
cat > turnserver.conf <<EOF
|
||||||
listening-port=3478
|
listening-port=3478
|
||||||
$TURN_EXTERNAL_IP_CONFIG
|
$TURN_EXTERNAL_IP_CONFIG
|
||||||
|
|
@ -397,7 +487,7 @@ pidfile="/var/tmp/turnserver.pid"
|
||||||
no-cli
|
no-cli
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Generate relay.env
|
# === relay.env ===
|
||||||
cat > relay.env <<EOF
|
cat > relay.env <<EOF
|
||||||
NB_LOG_LEVEL=info
|
NB_LOG_LEVEL=info
|
||||||
NB_LISTEN_ADDRESS=:33080
|
NB_LISTEN_ADDRESS=:33080
|
||||||
|
|
@ -406,13 +496,11 @@ NB_AUTH_SECRET=$NETBIRD_RELAY_AUTH_SECRET
|
||||||
NETBIRD_DOMAIN=$NETBIRD_DOMAIN
|
NETBIRD_DOMAIN=$NETBIRD_DOMAIN
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Temporary empty files
|
||||||
|
|
||||||
# Create temporary empty files
|
|
||||||
echo "" > dashboard.env
|
echo "" > dashboard.env
|
||||||
echo "" > management.json
|
echo "" > management.json
|
||||||
|
|
||||||
# Generate docker-compose.yml
|
# === docker-compose.yml template ===
|
||||||
cat > docker-compose.yml <<'EOF'
|
cat > docker-compose.yml <<'EOF'
|
||||||
services:
|
services:
|
||||||
# UI dashboard
|
# UI dashboard
|
||||||
|
|
@ -426,10 +514,10 @@ services:
|
||||||
- ./dashboard.env
|
- ./dashboard.env
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.network=traefik_traefik
|
- traefik.docker.network=traefik_default
|
||||||
- traefik.http.services.netbird-dashboard.loadbalancer.server.port=80
|
- traefik.http.services.netbird-dashboard.loadbalancer.server.port=80
|
||||||
- traefik.http.routers.netbird-dashboard.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`)
|
- traefik.http.routers.netbird-dashboard.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`)
|
||||||
- traefik.http.routers.netbird-dashboard.entrypoints=https
|
- traefik.http.routers.netbird-dashboard.entrypoints=websecure
|
||||||
- traefik.http.routers.netbird-dashboard.tls=true
|
- traefik.http.routers.netbird-dashboard.tls=true
|
||||||
- traefik.http.routers.netbird-dashboard.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.netbird-dashboard.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
- traefik.http.routers.netbird-dashboard.priority=50
|
- traefik.http.routers.netbird-dashboard.priority=50
|
||||||
|
|
@ -448,14 +536,23 @@ services:
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.network=traefik_traefik
|
- traefik.docker.network=traefik_default
|
||||||
- traefik.http.services.netbird-signal.loadbalancer.server.port=10000
|
- traefik.http.services.netbird-signal.loadbalancer.server.port=10000
|
||||||
- traefik.http.services.netbird-signal.loadbalancer.server.scheme=h2c
|
- traefik.http.services.netbird-signal.loadbalancer.server.scheme=h2c
|
||||||
- traefik.http.routers.netbird-signal.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/signalexchange.SignalExchange/`)
|
- traefik.http.routers.netbird-signal.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/signalexchange.SignalExchange/`)
|
||||||
- traefik.http.routers.netbird-signal.entrypoints=https
|
- 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=true
|
||||||
- traefik.http.routers.netbird-signal.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.netbird-signal.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
- traefik.http.routers.netbird-signal.priority=200
|
- 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_DOMAIN_PLACEHOLDER`) && 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=NETBIRD_TRAEFIK_SSL
|
||||||
|
- traefik.http.routers.netbird-signal-ws.priority=300
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
|
|
@ -473,10 +570,10 @@ services:
|
||||||
- ./relay.env
|
- ./relay.env
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.network=traefik_traefik
|
- traefik.docker.network=traefik_default
|
||||||
- traefik.http.services.netbird-relay.loadbalancer.server.port=33080
|
- traefik.http.services.netbird-relay.loadbalancer.server.port=33080
|
||||||
- traefik.http.routers.netbird-relay.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/relay`)
|
- traefik.http.routers.netbird-relay.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/relay`)
|
||||||
- traefik.http.routers.netbird-relay.entrypoints=https
|
- traefik.http.routers.netbird-relay.entrypoints=websecure
|
||||||
- traefik.http.routers.netbird-relay.tls=true
|
- traefik.http.routers.netbird-relay.tls=true
|
||||||
- traefik.http.routers.netbird-relay.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.netbird-relay.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
- traefik.http.routers.netbird-relay.priority=200
|
- traefik.http.routers.netbird-relay.priority=200
|
||||||
|
|
@ -507,24 +604,31 @@ services:
|
||||||
]
|
]
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.network=traefik_traefik
|
- traefik.docker.network=traefik_default
|
||||||
- traefik.http.services.netbird-management.loadbalancer.server.port=80
|
- 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.port=80
|
||||||
- traefik.http.services.netbird-management-grpc.loadbalancer.server.scheme=h2c
|
- traefik.http.services.netbird-management-grpc.loadbalancer.server.scheme=h2c
|
||||||
# REST API
|
# REST API
|
||||||
- traefik.http.routers.netbird-api.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/api`)
|
- traefik.http.routers.netbird-api.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/api`)
|
||||||
- traefik.http.routers.netbird-api.entrypoints=https
|
- traefik.http.routers.netbird-api.entrypoints=websecure
|
||||||
- traefik.http.routers.netbird-api.service=netbird-management
|
- traefik.http.routers.netbird-api.service=netbird-management
|
||||||
- traefik.http.routers.netbird-api.tls=true
|
- traefik.http.routers.netbird-api.tls=true
|
||||||
- traefik.http.routers.netbird-api.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.netbird-api.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
- traefik.http.routers.netbird-api.priority=200
|
- traefik.http.routers.netbird-api.priority=200
|
||||||
# gRPC
|
# gRPC
|
||||||
- traefik.http.routers.netbird-management-grpc.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/management.ManagementService/`)
|
- traefik.http.routers.netbird-management-grpc.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/management.ManagementService/`)
|
||||||
- traefik.http.routers.netbird-management-grpc.entrypoints=https
|
- traefik.http.routers.netbird-management-grpc.entrypoints=websecure
|
||||||
- traefik.http.routers.netbird-management-grpc.service=netbird-management-grpc
|
- 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=true
|
||||||
- traefik.http.routers.netbird-management-grpc.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.netbird-management-grpc.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
- traefik.http.routers.netbird-management-grpc.priority=200
|
- traefik.http.routers.netbird-management-grpc.priority=200
|
||||||
|
# WebSocket route for management
|
||||||
|
- traefik.http.routers.netbird-management-ws.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && 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=NETBIRD_TRAEFIK_SSL
|
||||||
|
- traefik.http.routers.netbird-management-ws.priority=300
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
|
|
@ -549,10 +653,18 @@ services:
|
||||||
# Zitadel - identity provider
|
# Zitadel - identity provider
|
||||||
zitadel:
|
zitadel:
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
image: 'ghcr.io/zitadel/zitadel:v2.64.1'
|
image: 'ghcr.io/zitadel/zitadel:v2.59.3'
|
||||||
command: 'start-from-init --masterkeyFromEnv --tlsMode external'
|
command: 'start-from-init --masterkeyFromEnv --tlsMode external'
|
||||||
|
ports:
|
||||||
|
- "8085:8080" # <-- added
|
||||||
env_file:
|
env_file:
|
||||||
- ./zitadel.env
|
- ./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:
|
depends_on:
|
||||||
zdb:
|
zdb:
|
||||||
condition: 'service_healthy'
|
condition: 'service_healthy'
|
||||||
|
|
@ -564,85 +676,84 @@ services:
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
labels:
|
labels:
|
||||||
- traefik.enable=true
|
- traefik.enable=true
|
||||||
- traefik.docker.network=traefik_traefik
|
- traefik.docker.network=traefik_default
|
||||||
- traefik.http.services.zitadel.loadbalancer.server.port=8080
|
- traefik.http.services.zitadel.loadbalancer.server.port=8080
|
||||||
|
- traefik.http.services.zitadel.loadbalancer.server.scheme=h2c
|
||||||
# OIDC wellknown
|
# OIDC wellknown
|
||||||
- traefik.http.routers.zitadel-wellknown.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/.well-known`)
|
- traefik.http.routers.zitadel-wellknown.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/.well-known`)
|
||||||
- traefik.http.routers.zitadel-wellknown.entrypoints=https
|
- traefik.http.routers.zitadel-wellknown.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-wellknown.service=zitadel
|
- traefik.http.routers.zitadel-wellknown.service=zitadel
|
||||||
- traefik.http.routers.zitadel-wellknown.priority=300
|
- traefik.http.routers.zitadel-wellknown.priority=300
|
||||||
- traefik.http.routers.zitadel-wellknown.tls=true
|
- traefik.http.routers.zitadel-wellknown.tls=true
|
||||||
- traefik.http.routers.zitadel-wellknown.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-wellknown.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# OAuth
|
# OAuth
|
||||||
- traefik.http.routers.zitadel-oauth.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/oauth`)
|
- traefik.http.routers.zitadel-oauth.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/oauth`)
|
||||||
- traefik.http.routers.zitadel-oauth.entrypoints=https
|
- traefik.http.routers.zitadel-oauth.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-oauth.service=zitadel
|
- traefik.http.routers.zitadel-oauth.service=zitadel
|
||||||
- traefik.http.routers.zitadel-oauth.priority=300
|
- traefik.http.routers.zitadel-oauth.priority=300
|
||||||
- traefik.http.routers.zitadel-oauth.tls=true
|
- traefik.http.routers.zitadel-oauth.tls=true
|
||||||
- traefik.http.routers.zitadel-oauth.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-oauth.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# OIDC
|
# OIDC
|
||||||
- traefik.http.routers.zitadel-oidc.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/oidc`)
|
- traefik.http.routers.zitadel-oidc.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/oidc`)
|
||||||
- traefik.http.routers.zitadel-oidc.entrypoints=https
|
- traefik.http.routers.zitadel-oidc.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-oidc.service=zitadel
|
- traefik.http.routers.zitadel-oidc.service=zitadel
|
||||||
- traefik.http.routers.zitadel-oidc.priority=300
|
- traefik.http.routers.zitadel-oidc.priority=300
|
||||||
- traefik.http.routers.zitadel-oidc.tls=true
|
- traefik.http.routers.zitadel-oidc.tls=true
|
||||||
- traefik.http.routers.zitadel-oidc.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-oidc.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# UI Console
|
# UI Console
|
||||||
- traefik.http.routers.zitadel-ui.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/ui`)
|
- traefik.http.routers.zitadel-ui.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/ui`)
|
||||||
- traefik.http.routers.zitadel-ui.entrypoints=https
|
- traefik.http.routers.zitadel-ui.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-ui.service=zitadel
|
- traefik.http.routers.zitadel-ui.service=zitadel
|
||||||
- traefik.http.routers.zitadel-ui.priority=300
|
- traefik.http.routers.zitadel-ui.priority=300
|
||||||
- traefik.http.routers.zitadel-ui.tls=true
|
- traefik.http.routers.zitadel-ui.tls=true
|
||||||
- traefik.http.routers.zitadel-ui.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-ui.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# Device flow
|
# Device flow
|
||||||
- traefik.http.routers.zitadel-device.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/device`)
|
- traefik.http.routers.zitadel-device.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/device`)
|
||||||
- traefik.http.routers.zitadel-device.entrypoints=https
|
- traefik.http.routers.zitadel-device.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-device.service=zitadel
|
- traefik.http.routers.zitadel-device.service=zitadel
|
||||||
- traefik.http.routers.zitadel-device.priority=300
|
- traefik.http.routers.zitadel-device.priority=300
|
||||||
- traefik.http.routers.zitadel-device.tls=true
|
- traefik.http.routers.zitadel-device.tls=true
|
||||||
- traefik.http.routers.zitadel-device.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-device.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# Management API
|
# Management API
|
||||||
- traefik.http.routers.zitadel-mgmt.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/management/v1`)
|
- traefik.http.routers.zitadel-mgmt.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/management/v1`)
|
||||||
- traefik.http.routers.zitadel-mgmt.entrypoints=https
|
- traefik.http.routers.zitadel-mgmt.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-mgmt.service=zitadel
|
- traefik.http.routers.zitadel-mgmt.service=zitadel
|
||||||
- traefik.http.routers.zitadel-mgmt.priority=300
|
- traefik.http.routers.zitadel-mgmt.priority=300
|
||||||
- traefik.http.routers.zitadel-mgmt.tls=true
|
- traefik.http.routers.zitadel-mgmt.tls=true
|
||||||
- traefik.http.routers.zitadel-mgmt.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-mgmt.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# Auth API
|
|
||||||
- traefik.http.routers.zitadel-auth.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/auth/v1`)
|
|
||||||
- traefik.http.routers.zitadel-auth.entrypoints=https
|
|
||||||
- traefik.http.routers.zitadel-auth.service=zitadel
|
|
||||||
- traefik.http.routers.zitadel-auth.priority=300
|
|
||||||
- traefik.http.routers.zitadel-auth.tls=true
|
|
||||||
- traefik.http.routers.zitadel-auth.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
|
||||||
# Admin API
|
# Admin API
|
||||||
- traefik.http.routers.zitadel-admin.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/admin/v1`)
|
- traefik.http.routers.zitadel-admin.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/admin/v1`)
|
||||||
- traefik.http.routers.zitadel-admin.entrypoints=https
|
- traefik.http.routers.zitadel-admin.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-admin.service=zitadel
|
- traefik.http.routers.zitadel-admin.service=zitadel
|
||||||
- traefik.http.routers.zitadel-admin.priority=300
|
- traefik.http.routers.zitadel-admin.priority=300
|
||||||
- traefik.http.routers.zitadel-admin.tls=true
|
- traefik.http.routers.zitadel-admin.tls=true
|
||||||
- traefik.http.routers.zitadel-admin.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
- traefik.http.routers.zitadel-admin.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
# Endpoints gRPC Zitadel
|
# gRPC endpoints
|
||||||
- traefik.http.routers.zitadel-grpc-auth.rule=Host(`netbird.yblis.fr`) && PathPrefix(`/zitadel.auth.v1.AuthService/`)
|
- traefik.http.routers.zitadel-grpc-auth.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/zitadel.auth.v1.AuthService/`)
|
||||||
- traefik.http.routers.zitadel-grpc-auth.entrypoints=https
|
- traefik.http.routers.zitadel-grpc-auth.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-grpc-auth.service=zitadel
|
- traefik.http.routers.zitadel-grpc-auth.service=zitadel
|
||||||
- traefik.http.routers.zitadel-grpc-auth.priority=400
|
- traefik.http.routers.zitadel-grpc-auth.priority=400
|
||||||
- traefik.http.routers.zitadel-grpc-auth.tls=true
|
- traefik.http.routers.zitadel-grpc-auth.tls=true
|
||||||
- traefik.http.routers.zitadel-grpc-auth.tls.certresolver=webssl
|
- traefik.http.routers.zitadel-grpc-auth.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
|
- traefik.http.routers.zitadel-grpc-admin.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/zitadel.admin.v1.AdminService/`)
|
||||||
- traefik.http.routers.zitadel-grpc-admin.rule=Host(`netbird.yblis.fr`) && PathPrefix(`/zitadel.admin.v1.AdminService/`)
|
- traefik.http.routers.zitadel-grpc-admin.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-grpc-admin.entrypoints=https
|
|
||||||
- traefik.http.routers.zitadel-grpc-admin.service=zitadel
|
- traefik.http.routers.zitadel-grpc-admin.service=zitadel
|
||||||
- traefik.http.routers.zitadel-grpc-admin.priority=400
|
- traefik.http.routers.zitadel-grpc-admin.priority=400
|
||||||
- traefik.http.routers.zitadel-grpc-admin.tls=true
|
- traefik.http.routers.zitadel-grpc-admin.tls=true
|
||||||
- traefik.http.routers.zitadel-grpc-admin.tls.certresolver=webssl
|
- traefik.http.routers.zitadel-grpc-admin.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
|
- traefik.http.routers.zitadel-grpc-mgmt.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && PathPrefix(`/zitadel.management.v1.ManagementService/`)
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.rule=Host(`netbird.yblis.fr`) && PathPrefix(`/zitadel.management.v1.ManagementService/`)
|
- traefik.http.routers.zitadel-grpc-mgmt.entrypoints=websecure
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.entrypoints=https
|
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.service=zitadel
|
- traefik.http.routers.zitadel-grpc-mgmt.service=zitadel
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.priority=400
|
- traefik.http.routers.zitadel-grpc-mgmt.priority=400
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.tls=true
|
- traefik.http.routers.zitadel-grpc-mgmt.tls=true
|
||||||
- traefik.http.routers.zitadel-grpc-mgmt.tls.certresolver=webssl
|
- traefik.http.routers.zitadel-grpc-mgmt.tls.certresolver=NETBIRD_TRAEFIK_SSL
|
||||||
|
# === CRITICAL ROUTE: /auth/v1 for PAT + wait_api ===
|
||||||
|
- traefik.http.routers.zitadel-auth-v1.rule=Host(`NETBIRD_DOMAIN_PLACEHOLDER`) && 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=NETBIRD_TRAEFIK_SSL
|
||||||
|
- traefik.http.routers.zitadel-auth-v1.priority=950
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: "json-file"
|
||||||
options:
|
options:
|
||||||
|
|
@ -653,13 +764,13 @@ services:
|
||||||
zdb:
|
zdb:
|
||||||
restart: 'always'
|
restart: 'always'
|
||||||
networks: [netbird]
|
networks: [netbird]
|
||||||
image: 'postgres:16-alpine'
|
image: 'postgres:15-alpine'
|
||||||
env_file:
|
env_file:
|
||||||
- ./zdb.env
|
- ./zdb.env
|
||||||
volumes:
|
volumes:
|
||||||
- netbird_zdb_data:/var/lib/postgresql/data:rw
|
- netbird_zdb_data:/var/lib/postgresql/data:rw
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"]
|
test: ["CMD-SHELL", "pg_isready -U root"]
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 60s
|
timeout: 60s
|
||||||
retries: 10
|
retries: 10
|
||||||
|
|
@ -680,10 +791,13 @@ networks:
|
||||||
driver: bridge
|
driver: bridge
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
name: traefik_default
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Replace placeholders
|
||||||
sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/${TRAEFIK_CERTRESOLVER}/g" docker-compose.yml
|
sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/${TRAEFIK_CERTRESOLVER}/g" docker-compose.yml
|
||||||
|
|
||||||
# Create machinekey directory
|
# Create machinekey dir
|
||||||
mkdir -p machinekey
|
mkdir -p machinekey
|
||||||
chmod 777 machinekey
|
chmod 777 machinekey
|
||||||
|
|
||||||
|
|
@ -699,7 +813,6 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/
|
||||||
echo "Waiting for Zitadel to initialize..."
|
echo "Waiting for Zitadel to initialize..."
|
||||||
sleep 60
|
sleep 60
|
||||||
|
|
||||||
# Configuration automatique de Zitadel
|
|
||||||
echo "Configuring Zitadel applications..."
|
echo "Configuring Zitadel applications..."
|
||||||
|
|
||||||
INSTANCE_URL="https://$NETBIRD_DOMAIN"
|
INSTANCE_URL="https://$NETBIRD_DOMAIN"
|
||||||
|
|
@ -709,7 +822,7 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/
|
||||||
wait_pat "$TOKEN_PATH"
|
wait_pat "$TOKEN_PATH"
|
||||||
|
|
||||||
echo "Reading Zitadel PAT"
|
echo "Reading Zitadel PAT"
|
||||||
PAT=$(cat $TOKEN_PATH)
|
PAT=$(cat "$TOKEN_PATH")
|
||||||
if [ "$PAT" = "null" ]; then
|
if [ "$PAT" = "null" ]; then
|
||||||
echo "Failed getting Zitadel PAT"
|
echo "Failed getting Zitadel PAT"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
@ -718,29 +831,24 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/
|
||||||
echo -n "Waiting for Zitadel to become ready "
|
echo -n "Waiting for Zitadel to become ready "
|
||||||
wait_api "$INSTANCE_URL" "$PAT"
|
wait_api "$INSTANCE_URL" "$PAT"
|
||||||
|
|
||||||
# Create project
|
|
||||||
echo "Creating Zitadel project"
|
echo "Creating Zitadel project"
|
||||||
PROJECT_ID=$(create_new_project "$INSTANCE_URL" "$PAT")
|
PROJECT_ID=$(create_new_project "$INSTANCE_URL" "$PAT")
|
||||||
|
|
||||||
# Create applications
|
|
||||||
echo "Creating Dashboard application"
|
echo "Creating Dashboard application"
|
||||||
DASHBOARD_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Dashboard" "https://$NETBIRD_DOMAIN/nb-auth" "https://$NETBIRD_DOMAIN/nb-silent-auth" "https://$NETBIRD_DOMAIN/" "false" "false")
|
DASHBOARD_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "$PROJECT_ID" "Dashboard" "https://$NETBIRD_DOMAIN/nb-auth" "https://$NETBIRD_DOMAIN/nb-silent-auth" "https://$NETBIRD_DOMAIN/" "false" "false")
|
||||||
|
|
||||||
echo "Creating CLI application"
|
echo "Creating CLI application"
|
||||||
CLI_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "Cli" "http://localhost:53000/" "http://localhost:54000/" "http://localhost:53000/" "true" "true")
|
CLI_APPLICATION_CLIENT_ID=$(create_new_application "$INSTANCE_URL" "$PAT" "$PROJECT_ID" "Cli" "http://localhost:53000/" "http://localhost:54000/" "http://localhost:53000/" "true" "true")
|
||||||
|
|
||||||
# Create service user
|
|
||||||
echo "Creating service user"
|
echo "Creating service user"
|
||||||
MACHINE_USER_ID=$(create_service_user "$INSTANCE_URL" "$PAT")
|
MACHINE_USER_ID=$(create_service_user "$INSTANCE_URL" "$PAT")
|
||||||
create_service_user_secret "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID"
|
create_service_user_secret "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID"
|
||||||
add_organization_user_manager "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID"
|
add_organization_user_manager "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID"
|
||||||
|
|
||||||
# Create admin user
|
|
||||||
echo "Creating admin user"
|
echo "Creating admin user"
|
||||||
HUMAN_USER_ID=$(create_admin_user "$INSTANCE_URL" "$PAT" "$ZITADEL_ADMIN_USERNAME" "$ZITADEL_ADMIN_PASSWORD")
|
HUMAN_USER_ID=$(create_admin_user "$INSTANCE_URL" "$PAT" "$ZITADEL_ADMIN_USERNAME" "$ZITADEL_ADMIN_PASSWORD")
|
||||||
add_instance_admin "$INSTANCE_URL" "$PAT" "$HUMAN_USER_ID"
|
add_instance_admin "$INSTANCE_URL" "$PAT" "$HUMAN_USER_ID"
|
||||||
|
|
||||||
# Clean up auto service user
|
|
||||||
echo "Cleaning up auto service user"
|
echo "Cleaning up auto service user"
|
||||||
DATE=$(delete_auto_service_user "$INSTANCE_URL" "$PAT")
|
DATE=$(delete_auto_service_user "$INSTANCE_URL" "$PAT")
|
||||||
if [ "$DATE" = "null" ]; then
|
if [ "$DATE" = "null" ]; then
|
||||||
|
|
@ -748,7 +856,6 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/
|
||||||
echo "Please remove it manually"
|
echo "Please remove it manually"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Generate NetBird configuration
|
|
||||||
echo "Generating NetBird configuration..."
|
echo "Generating NetBird configuration..."
|
||||||
|
|
||||||
# dashboard.env
|
# dashboard.env
|
||||||
|
|
@ -849,5 +956,4 @@ EOF
|
||||||
echo "Note: The admin password will require changing on first login."
|
echo "Note: The admin password will require changing on first login."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Execute main function
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
|
||||||
1
machinekey/zitadel-admin-sa.token
Normal file
1
machinekey/zitadel-admin-sa.token
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
tlqWhCwoB4bEoKhqlbw_mHr8qGxjuJVdjfYGH70-Tr1bwzGu0Q5FNUMiostaLXoAk5GvCXc
|
||||||
112
management.json
Normal file
112
management.json
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
{
|
||||||
|
"Stuns": [
|
||||||
|
{
|
||||||
|
"Proto": "udp",
|
||||||
|
"URI": "stun:netbird.rozic-dev.com:3478",
|
||||||
|
"Username": "",
|
||||||
|
"Password": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"TURNConfig": {
|
||||||
|
"TimeBasedCredentials": false,
|
||||||
|
"CredentialsTTL": "0s",
|
||||||
|
"Secret": "",
|
||||||
|
"Turns": [
|
||||||
|
{
|
||||||
|
"Proto": "udp",
|
||||||
|
"URI": "turn:netbird.rozic-dev.com:3478",
|
||||||
|
"Username": "self",
|
||||||
|
"Password": "irxMo1xxkrpzLUBK4AkWHtJI2CHjqhD9RZEmXqSXLgU"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Relay": {
|
||||||
|
"Addresses": [
|
||||||
|
"rels://netbird.rozic-dev.com:443/relay"
|
||||||
|
],
|
||||||
|
"CredentialsTTL": "24h0m0s",
|
||||||
|
"Secret": "WsMuriIhq7xs8vWFbWf59cOV1jcFlqkyb/cbEjmGNiQ"
|
||||||
|
},
|
||||||
|
"Signal": {
|
||||||
|
"Proto": "https",
|
||||||
|
"URI": "netbird.rozic-dev.com:443",
|
||||||
|
"Username": "",
|
||||||
|
"Password": ""
|
||||||
|
},
|
||||||
|
"Datadir": "/var/lib/netbird/",
|
||||||
|
"DataStoreEncryptionKey": "TOpiGD/r2qWq+UAjAsv53IyqABPsXJ3zGPZ9j6dk2bc=",
|
||||||
|
"HttpConfig": {
|
||||||
|
"LetsEncryptDomain": "",
|
||||||
|
"CertFile": "",
|
||||||
|
"CertKey": "",
|
||||||
|
"AuthAudience": "347529025415086083",
|
||||||
|
"AuthIssuer": "https://netbird.rozic-dev.com",
|
||||||
|
"AuthUserIDClaim": "",
|
||||||
|
"AuthKeysLocation": "https://netbird.rozic-dev.com/oauth/v2/keys",
|
||||||
|
"OIDCConfigEndpoint": "https://netbird.rozic-dev.com/.well-known/openid-configuration",
|
||||||
|
"IdpSignKeyRefreshEnabled": true,
|
||||||
|
"ExtraAuthAudience": ""
|
||||||
|
},
|
||||||
|
"IdpManagerConfig": {
|
||||||
|
"ManagerType": "zitadel",
|
||||||
|
"ClientConfig": {
|
||||||
|
"Issuer": "https://netbird.rozic-dev.com",
|
||||||
|
"TokenEndpoint": "https://netbird.rozic-dev.com/oauth/v2/token",
|
||||||
|
"ClientID": "netbird-service-account",
|
||||||
|
"ClientSecret": "GncnVxtSadobmYR0jQINd8OWYk8Mwbi6MGvo4aPnaqDyBb8CILrXb5bVAH38CNFC",
|
||||||
|
"GrantType": "client_credentials"
|
||||||
|
},
|
||||||
|
"ExtraConfig": {
|
||||||
|
"ManagementEndpoint": "https://netbird.rozic-dev.com/management/v1"
|
||||||
|
},
|
||||||
|
"Auth0ClientCredentials": null,
|
||||||
|
"AzureClientCredentials": null,
|
||||||
|
"KeycloakClientCredentials": null,
|
||||||
|
"ZitadelClientCredentials": null
|
||||||
|
},
|
||||||
|
"DeviceAuthorizationFlow": {
|
||||||
|
"Provider": "hosted",
|
||||||
|
"ProviderConfig": {
|
||||||
|
"ClientID": "347529027596124163",
|
||||||
|
"ClientSecret": "",
|
||||||
|
"Domain": "netbird.rozic-dev.com",
|
||||||
|
"Audience": "347529027596124163",
|
||||||
|
"TokenEndpoint": "https://netbird.rozic-dev.com/oauth/v2/token",
|
||||||
|
"DeviceAuthEndpoint": "https://netbird.rozic-dev.com/oauth/v2/device_authorization",
|
||||||
|
"AuthorizationEndpoint": "",
|
||||||
|
"Scope": "openid",
|
||||||
|
"UseIDToken": false,
|
||||||
|
"RedirectURLs": null,
|
||||||
|
"DisablePromptLogin": false,
|
||||||
|
"LoginFlag": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PKCEAuthorizationFlow": {
|
||||||
|
"ProviderConfig": {
|
||||||
|
"ClientID": "347529027596124163",
|
||||||
|
"ClientSecret": "",
|
||||||
|
"Domain": "",
|
||||||
|
"Audience": "347529027596124163",
|
||||||
|
"TokenEndpoint": "https://netbird.rozic-dev.com/oauth/v2/token",
|
||||||
|
"DeviceAuthEndpoint": "",
|
||||||
|
"AuthorizationEndpoint": "https://netbird.rozic-dev.com/oauth/v2/authorize",
|
||||||
|
"Scope": "openid profile email offline_access",
|
||||||
|
"UseIDToken": false,
|
||||||
|
"RedirectURLs": [
|
||||||
|
"http://localhost:53000/",
|
||||||
|
"http://localhost:54000/"
|
||||||
|
],
|
||||||
|
"DisablePromptLogin": false,
|
||||||
|
"LoginFlag": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"StoreConfig": {
|
||||||
|
"Engine": ""
|
||||||
|
},
|
||||||
|
"ReverseProxy": {
|
||||||
|
"TrustedHTTPProxies": null,
|
||||||
|
"TrustedHTTPProxiesCount": 0,
|
||||||
|
"TrustedPeers": null
|
||||||
|
},
|
||||||
|
"DisableDefaultPolicy": false
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# 🚀 Deploy Netbird with Traefik
|
# 🚀 Deploy Netbird & Zitadel with Traefik
|
||||||
|
|
||||||
This script helps you deploy **Netbird** behind a **Traefik** reverse proxy. It's designed for users who already have a working Traefik stack. The integration relies solely on Traefik labels—no need to modify your existing setup.
|
This script helps you deploy **Netbird** behind a **Traefik** reverse proxy. It's designed for users who already have a working Traefik stack. The integration relies solely on Traefik labels—no need to modify your existing setup.
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ cd netbird-traefik
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ Configuration
|
## ⚙️ Configurations
|
||||||
|
|
||||||
Before running the script, edit the following variables inside `install-netbird-traefik.sh`:
|
Before running the script, edit the following variables inside `install-netbird-traefik.sh`:
|
||||||
|
|
||||||
|
|
|
||||||
17
reinit.sh
Executable file
17
reinit.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
docker compose down -v
|
||||||
|
rm -rf machinekey/ docker-compose.yml *.env management.json turnserver.conf relay.env
|
||||||
|
#rm -rf machinekey/
|
||||||
|
./install-netbird-traefik.sh
|
||||||
|
# Kill the hanging script with Ctrl+C if it's still running
|
||||||
|
|
||||||
|
# Start the rest of the NetBird services manually
|
||||||
|
docker compose up -d management dashboard signal relay coturn
|
||||||
|
|
||||||
|
# Wait 10 seconds
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# DONE! Your NetBird is fully working
|
||||||
|
echo "🎉 SUCCESS! Dashboard: https://netbird.rozic-dev.com"
|
||||||
|
echo "Login with:"
|
||||||
|
echo "Username: admin@netbird.rozic-dev.com"
|
||||||
|
echo "Password: $(grep Password .env | cut -d' ' -f2-)" # prints the password from the .env file the script created earlier
|
||||||
40
reinit1.sh
Executable file
40
reinit1.sh
Executable file
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🧹 Cleaning old data..."
|
||||||
|
docker compose down -v
|
||||||
|
|
||||||
|
docker compose down -v || true
|
||||||
|
|
||||||
|
rm -rf machinekey
|
||||||
|
rm -f docker-compose.yml zitadel.env zdb.env dashboard.env management.json relay.env turnserver.conf
|
||||||
|
|
||||||
|
rm -rf machinekey/ docker-compose.yml *.env management.json turnserver.conf relay.env dashboard.env || true
|
||||||
|
|
||||||
|
echo "🚀 Starting fresh installation..."
|
||||||
|
# Run the config part – ignore the false health-check failure at the end
|
||||||
|
./install-netbird-traefik.sh || true
|
||||||
|
|
||||||
|
echo "🔧 Starting the real NetBird services (bypassing the dumb health check)..."
|
||||||
|
docker compose up -d management dashboard signal relay coturn
|
||||||
|
|
||||||
|
echo "⏳ Waiting 15 seconds for everything to settle..."
|
||||||
|
sleep 15
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🎉🎉🎉 ALL DONE – YOUR NETBIRD IS READY! 🎉🎉🎉"
|
||||||
|
echo ""
|
||||||
|
echo "Dashboard → https://netbird.rozic-dev.com"
|
||||||
|
echo ""
|
||||||
|
echo "Login with:"
|
||||||
|
echo " Username: admin@netbird.rozic-dev.com"
|
||||||
|
if [ -f .env ]; then
|
||||||
|
PASSWORD=$(grep "^Password:" .env | cut -d' ' -f2-)
|
||||||
|
echo " Password: $PASSWORD"
|
||||||
|
else
|
||||||
|
echo " Password: (no .env – just click 'Sign up' on the page and create any user – first user = admin)"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo "Zitadel console (optional): https://netbird.rozic-dev.com/ui/console"
|
||||||
|
echo ""
|
||||||
|
echo "Enjoy your fully private, self-hosted WireGuard mesh! 🚀"
|
||||||
5
relay.env
Normal file
5
relay.env
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
NB_LOG_LEVEL=info
|
||||||
|
NB_LISTEN_ADDRESS=:33080
|
||||||
|
NB_EXPOSED_ADDRESS=rels://netbird.rozic-dev.com:443/relay
|
||||||
|
NB_AUTH_SECRET=WsMuriIhq7xs8vWFbWf59cOV1jcFlqkyb/cbEjmGNiQ
|
||||||
|
NETBIRD_DOMAIN=netbird.rozic-dev.com
|
||||||
1
traefik-stack/data/acme.json
Normal file
1
traefik-stack/data/acme.json
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
# Supprimez la ligne defaultEntryPoints qui est obsolète dans Traefik v2+
|
|
||||||
# defaultEntryPoints = ["http", "https", "ws", "wss"]
|
|
||||||
|
|
||||||
[entryPoints]
|
[entryPoints]
|
||||||
[entryPoints.http]
|
[entryPoints.http]
|
||||||
address = ":80"
|
address = ":80"
|
||||||
|
|
@ -29,6 +26,6 @@
|
||||||
permanent = true
|
permanent = true
|
||||||
sslRedirect = true
|
sslRedirect = true
|
||||||
|
|
||||||
# Autorise les backend TLS
|
# Autorize TSL backend
|
||||||
[serversTransport]
|
# [serversTransport]
|
||||||
insecureSkipVerify = true
|
# insecureSkipVerify = true
|
||||||
|
|
|
||||||
89
traefik-stack/readme.md
Normal file
89
traefik-stack/readme.md
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
# Traefik Reverse Proxy Setup
|
||||||
|
|
||||||
|
A simple Docker Compose setup for Traefik reverse proxy with automatic HTTPS certificates.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Clone and configure**
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yblis/netbird-traefik
|
||||||
|
cd netbird-traefil/traefik-setup
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Edit configuration files**
|
||||||
|
- In `docker-compose.yml`: Replace `traefik.domain.com` with your domain
|
||||||
|
- In `data/traefik.toml`: Replace `admin@domain.com` with your email
|
||||||
|
- In `docker-compose.yml`: Replace `YOURHASHBASICPASSWORD` with your hashed password
|
||||||
|
|
||||||
|
3. **Set up DNS**
|
||||||
|
- Create an A record pointing your domain to your server IP
|
||||||
|
- Example: `traefik.yourdomain.com` → `your.server.ip`
|
||||||
|
|
||||||
|
4. **Create required files**
|
||||||
|
```bash
|
||||||
|
mkdir -p data
|
||||||
|
touch data/acme.json
|
||||||
|
chmod 600 data/acme.json
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Start Traefik**
|
||||||
|
```bash
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Details
|
||||||
|
|
||||||
|
### Domain Setup
|
||||||
|
Replace these values in the configuration files:
|
||||||
|
- `traefik.domain.com` → Your actual domain
|
||||||
|
- `admin@domain.com` → Your email for Let's Encrypt
|
||||||
|
- `YOURHASHBASICPASSWORD` → Your hashed password (see below)
|
||||||
|
|
||||||
|
### Generate Password Hash
|
||||||
|
```bash
|
||||||
|
echo $(htpasswd -nb admin yourpassword) | sed -e s/\\$/\\$\\$/g
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access Points
|
||||||
|
- **Traefik Dashboard**: `https://traefik.yourdomain.com`
|
||||||
|
- **HTTP**: Port 80 (redirects to HTTPS)
|
||||||
|
- **HTTPS**: Port 443
|
||||||
|
- **Dashboard Direct**: Port 8001 (HTTP only)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- ✅ Automatic HTTPS with Let's Encrypt
|
||||||
|
- ✅ HTTP to HTTPS redirection
|
||||||
|
- ✅ Basic authentication for dashboard
|
||||||
|
- ✅ Docker integration
|
||||||
|
- ✅ File-based service configuration
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── data/
|
||||||
|
├── traefik.toml
|
||||||
|
├── services.toml
|
||||||
|
└── acme.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding Services
|
||||||
|
|
||||||
|
To add a new service behind Traefik, add these labels to your service in docker-compose:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
labels:
|
||||||
|
- "traefik.http.routers.myapp.rule=Host(`myapp.yourdomain.com`)"
|
||||||
|
- "traefik.http.routers.myapp.entrypoints=https"
|
||||||
|
- "traefik.http.routers.myapp.tls.certresolver=webssl"
|
||||||
|
- "traefik.http.services.myapp.loadbalancer.server.port=80"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- Check logs: `docker-compose logs traefik`
|
||||||
|
- Verify DNS resolution: `nslookup traefik.yourdomain.com`
|
||||||
|
- Ensure ports 80 and 443 are open
|
||||||
|
- Check acme.json permissions: `ls -la data/acme.json` (should be 600)
|
||||||
15
turnserver.conf
Normal file
15
turnserver.conf
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
listening-port=3478
|
||||||
|
external-ip=5.75.240.238
|
||||||
|
tls-listening-port=5349
|
||||||
|
min-port=49152
|
||||||
|
max-port=65535
|
||||||
|
fingerprint
|
||||||
|
lt-cred-mech
|
||||||
|
user=self:irxMo1xxkrpzLUBK4AkWHtJI2CHjqhD9RZEmXqSXLgU
|
||||||
|
realm=wiretrustee.com
|
||||||
|
cert=/etc/coturn/certs/cert.pem
|
||||||
|
pkey=/etc/coturn/private/privkey.pem
|
||||||
|
log-file=stdout
|
||||||
|
no-software-attribute
|
||||||
|
pidfile="/var/tmp/turnserver.pid"
|
||||||
|
no-cli
|
||||||
1
uninstall-netbird-traefik.sh
Normal file
1
uninstall-netbird-traefik.sh
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
sudo docker-compose down -v && sudo rm -R machinekey/ .env *.env *.yml *.json *.conf
|
||||||
2
zdb.env
Normal file
2
zdb.env
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
POSTGRES_USER=root
|
||||||
|
POSTGRES_PASSWORD=WuNCCFl9IrF4x1YOvUb5g0297qf4CE5qKPqlwY3HFn0@
|
||||||
21
zitadel.env
Normal file
21
zitadel.env
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
ZITADEL_LOG_LEVEL=debug
|
||||||
|
ZITADEL_MASTERKEY=IuuoiDADifLLM7enKI/ia+s0sesaqF8w
|
||||||
|
ZITADEL_EXTERNALSECURE=true
|
||||||
|
ZITADEL_TLS_ENABLED=false
|
||||||
|
ZITADEL_EXTERNALPORT=443
|
||||||
|
ZITADEL_EXTERNALDOMAIN=netbird.rozic-dev.com
|
||||||
|
ZITADEL_FIRSTINSTANCE_PATPATH=/machinekey/zitadel-admin-sa.token
|
||||||
|
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_USERNAME=zitadel-admin-sa
|
||||||
|
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_MACHINE_NAME=Admin
|
||||||
|
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_SCOPES=openid
|
||||||
|
ZITADEL_FIRSTINSTANCE_ORG_MACHINE_PAT_EXPIRATIONDATE=2025-11-20T12:19:08Z
|
||||||
|
ZITADEL_DATABASE_POSTGRES_HOST=zdb
|
||||||
|
ZITADEL_DATABASE_POSTGRES_PORT=5432
|
||||||
|
ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel
|
||||||
|
ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel
|
||||||
|
ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=g798XBwToxA9Ehu2SYGbz+CE5MxAuC/BVoxSlxhPHTU@
|
||||||
|
ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable
|
||||||
|
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=root
|
||||||
|
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD=WuNCCFl9IrF4x1YOvUb5g0297qf4CE5qKPqlwY3HFn0@
|
||||||
|
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable
|
||||||
|
NETBIRD_DOMAIN=netbird.rozic-dev.com
|
||||||
11
zitadel_api.log
Normal file
11
zitadel_api.log
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{"id":"347529023250759683","details":{"sequence":"2","creationDate":"2025-11-20T11:50:39.824071Z","resourceOwner":"347528924584017923"}}
|
||||||
|
{"appId":"347529025415020547","details":{"sequence":"4","creationDate":"2025-11-20T11:50:41.111831Z","resourceOwner":"347528924584017923"},"clientId":"347529025415086083"}
|
||||||
|
{"appId":"347529027596058627","details":{"sequence":"6","creationDate":"2025-11-20T11:50:42.406343Z","resourceOwner":"347528924584017923"},"clientId":"347529027596124163","noneCompliant":true,"complianceProblems":[{"key":"Application.OIDC.V1.NotCompliant","localizedMessage":"Your configuration is not compliant and differs from OIDC 1.0 standard."},{"key":"Application.OIDC.V1.NotCompliant","localizedMessage":"Your configuration is not compliant and differs from OIDC 1.0 standard."},{"key":"Application.OIDC.V1.Code.RedirectUris.HttpOnlyForWeb","localizedMessage":"Grant type code only allowed http redirect uris for apptype web."}]}
|
||||||
|
{"userId":"347529029743542275","details":{"sequence":"1","changeDate":"2025-11-20T11:50:43.737489Z","resourceOwner":"347528924584017923"}}
|
||||||
|
{"clientId":"netbird-service-account","clientSecret":"GncnVxtSadobmYR0jQINd8OWYk8Mwbi6MGvo4aPnaqDyBb8CILrXb5bVAH38CNFC","details":{"sequence":"2","creationDate":"2025-11-20T11:50:45.080684Z","resourceOwner":"347528924584017923"}}
|
||||||
|
{"details":{"sequence":"7","creationDate":"2025-11-20T11:50:47.361844Z","resourceOwner":"347528924584017923"}}
|
||||||
|
{"userId":"347529038249590787","details":{"sequence":"2","creationDate":"2025-11-20T11:50:49.908386Z","resourceOwner":"347528924584017923"}}
|
||||||
|
{"details":{"sequence":"107","creationDate":"2025-11-20T11:50:51.199567Z","resourceOwner":"347528924583952387"}}
|
||||||
|
{"user":{"id":"347528924584542211","details":{"sequence":"1","creationDate":"2025-11-20T11:49:43.050553Z","changeDate":"2025-11-20T11:49:43.050553Z","resourceOwner":"347528924584017923"},"state":"USER_STATE_ACTIVE","userName":"zitadel-admin-sa","loginNames":["zitadel-admin-sa"],"preferredLoginName":"zitadel-admin-sa","machine":{"name":"Admin"}}}
|
||||||
|
{"details":{"sequence":"108","changeDate":"2025-11-20T11:50:53.738309Z","resourceOwner":"347528924583952387"}}
|
||||||
|
{"details":{"sequence":"8","changeDate":"2025-11-20T11:50:54.996326Z","resourceOwner":"347528924584017923"}}
|
||||||
Loading…
Reference in a new issue