From 947a1b016ed0b0b31d46c4c773993838ad2a5ac0 Mon Sep 17 00:00:00 2001 From: "Dejan R." Date: Sun, 23 Nov 2025 18:38:45 +0000 Subject: [PATCH] =?UTF-8?q?first=20commit=C4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 4 + Netbird-compose-backup.tar.gz | Bin 0 -> 57664 bytes dashboard.env | 12 ++ docker-compose.yml | 290 ++++++++++++++++++++++++++++++ install-netbird-traefik.sh | 282 +++++++++++++++++++---------- machinekey/zitadel-admin-sa.token | 1 + management.json | 112 ++++++++++++ readme.md | 2 +- reinit.sh | 17 ++ reinit1.sh | 40 +++++ relay.env | 5 + turnserver.conf | 15 ++ zdb.env | 2 + zitadel.env | 21 +++ zitadel_api.log | 11 ++ 15 files changed, 716 insertions(+), 98 deletions(-) create mode 100644 .env create mode 100644 Netbird-compose-backup.tar.gz create mode 100644 dashboard.env create mode 100644 docker-compose.yml mode change 100644 => 100755 install-netbird-traefik.sh create mode 100644 machinekey/zitadel-admin-sa.token create mode 100644 management.json create mode 100755 reinit.sh create mode 100755 reinit1.sh create mode 100644 relay.env create mode 100644 turnserver.conf create mode 100644 zdb.env create mode 100644 zitadel.env create mode 100644 zitadel_api.log diff --git a/.env b/.env new file mode 100644 index 0000000..a455455 --- /dev/null +++ b/.env @@ -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 diff --git a/Netbird-compose-backup.tar.gz b/Netbird-compose-backup.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..93cf1ef3292578d3bbfe7a4b5ed2da5d5be4f06c GIT binary patch literal 57664 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 /dev/null then @@ -51,12 +56,13 @@ check_docker_compose() { echo "docker compose" return 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 exit 1 } -# Wait functions +# ============================================ +# WAIT HELPERS +# ============================================ wait_pat() { PAT_PATH=$1 set +e @@ -78,40 +84,50 @@ wait_api() { counter=1 while true; do FLAGS="-s" - if [[ $counter -eq 45 ]]; then + if [[ $counter -eq 120 ]]; then FLAGS="-v" echo "" fi - - curl $FLAGS --fail --connect-timeout 1 -o /dev/null "$INSTANCE_URL/auth/v1/users/me" -H "Authorization: Bearer $PAT" + curl $FLAGS --connect-timeout 5 -o /dev/null \ + http://localhost:8085/auth/v1/users/me \ + -H "Authorization: Bearer $PAT" 2>/dev/null if [[ $? -eq 0 ]]; then break fi - if [[ $counter -eq 45 ]]; then - echo "" - echo "Unable to connect to Zitadel for more than 45s, please check the output above, your firewall rules and container logs" + if [[ $counter -eq 120 ]]; then + echo "Zitadel still not ready via http://localhost:8085 after 120s – checking logs..." + docker logs netbird-compose-zitadel-1 --tail 50 exit 1 fi echo -n " ." - sleep 1 + sleep 2 counter=$((counter + 1)) done echo " done" set -e } -# Zitadel API functions +# ============================================ +# ZITADEL API HELPERS +# ============================================ create_new_project() { INSTANCE_URL=$1 PAT=$2 PROJECT_NAME="NETBIRD" - RESPONSE=$( curl -sS -X POST "$INSTANCE_URL/management/v1/projects" \ -H "Authorization: Bearer $PAT" \ -H "Content-Type: application/json" \ -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') handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_project" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -120,12 +136,13 @@ create_new_project() { create_new_application() { INSTANCE_URL=$1 PAT=$2 - APPLICATION_NAME=$3 - BASE_REDIRECT_URL1=$4 - BASE_REDIRECT_URL2=$5 - LOGOUT_URL=$6 - ZITADEL_DEV_MODE=$7 - DEVICE_CODE=$8 + PROJECT_ID=$3 + APPLICATION_NAME=$4 + BASE_REDIRECT_URL1=$5 + BASE_REDIRECT_URL2=$6 + LOGOUT_URL=$7 + ZITADEL_DEV_MODE=$8 + DEVICE_CODE=$9 if [[ $DEVICE_CODE == "true" ]]; then GRANT_TYPES='["OIDC_GRANT_TYPE_AUTHORIZATION_CODE","OIDC_GRANT_TYPE_DEVICE_CODE","OIDC_GRANT_TYPE_REFRESH_TOKEN"]' @@ -160,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') handle_zitadel_request_response "$PARSED_RESPONSE" "create_new_application" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -168,7 +195,6 @@ create_new_application() { create_service_user() { INSTANCE_URL=$1 PAT=$2 - RESPONSE=$( curl -sS -X POST "$INSTANCE_URL/management/v1/users/machine" \ -H "Authorization: Bearer $PAT" \ @@ -180,6 +206,14 @@ create_service_user() { "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') handle_zitadel_request_response "$PARSED_RESPONSE" "create_service_user" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -189,13 +223,20 @@ create_service_user_secret() { INSTANCE_URL=$1 PAT=$2 USER_ID=$3 - RESPONSE=$( curl -sS -X PUT "$INSTANCE_URL/management/v1/users/$USER_ID/secret" \ -H "Authorization: Bearer $PAT" \ -H "Content-Type: application/json" \ -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') handle_zitadel_request_response "$SERVICE_USER_CLIENT_ID" "create_service_user_secret_id" "$RESPONSE" SERVICE_USER_CLIENT_SECRET=$(echo "$RESPONSE" | jq -r '.clientSecret') @@ -206,7 +247,6 @@ add_organization_user_manager() { INSTANCE_URL=$1 PAT=$2 USER_ID=$3 - RESPONSE=$( curl -sS -X POST "$INSTANCE_URL/management/v1/orgs/me/members" \ -H "Authorization: Bearer $PAT" \ @@ -218,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') handle_zitadel_request_response "$PARSED_RESPONSE" "add_organization_user_manager" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -246,6 +294,14 @@ create_admin_user() { "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') handle_zitadel_request_response "$PARSED_RESPONSE" "create_admin_user" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -255,7 +311,6 @@ add_instance_admin() { INSTANCE_URL=$1 PAT=$2 USER_ID=$3 - RESPONSE=$( curl -sS -X POST "$INSTANCE_URL/admin/v1/members" \ -H "Authorization: Bearer $PAT" \ @@ -267,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') handle_zitadel_request_response "$PARSED_RESPONSE" "add_instance_admin" "$RESPONSE" echo "$PARSED_RESPONSE" @@ -275,34 +338,57 @@ add_instance_admin() { delete_auto_service_user() { INSTANCE_URL=$1 PAT=$2 - RESPONSE=$( curl -sS -X GET "$INSTANCE_URL/auth/v1/users/me" \ -H "Authorization: Bearer $PAT" \ -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') handle_zitadel_request_response "$USER_ID" "delete_auto_service_user_get_user" "$RESPONSE" - RESPONSE=$( curl -sS -X DELETE "$INSTANCE_URL/admin/v1/members/$USER_ID" \ -H "Authorization: Bearer $PAT" \ -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') handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_instance_permissions" "$RESPONSE" - RESPONSE=$( curl -sS -X DELETE "$INSTANCE_URL/management/v1/orgs/me/members/$USER_ID" \ -H "Authorization: Bearer $PAT" \ -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') handle_zitadel_request_response "$PARSED_RESPONSE" "delete_auto_service_user_remove_org_permissions" "$RESPONSE" echo "$PARSED_RESPONSE" } -# Get external IP for TURN server +# ============================================ +# TURN IP +# ============================================ get_turn_external_ip() { TURN_EXTERNAL_IP_CONFIG="#external-ip=" IP=$(curl -s -4 https://jsonip.com | jq -r '.ip') @@ -312,15 +398,18 @@ get_turn_external_ip() { echo "$TURN_EXTERNAL_IP_CONFIG" } -# Main initialization function +# ============================================ +# MAIN +# ============================================ main() { + # Clear log file + > zitadel_api.log + echo "Initializing NetBird with Traefik..." - # Check dependencies check_jq DOCKER_COMPOSE_COMMAND=$(check_docker_compose) - # Check if files already exist if [ -f zitadel.env ]; then echo "Generated files already exist, if you want to reinitialize the environment, please remove them first." echo "You can use the following commands:" @@ -330,7 +419,7 @@ main() { exit 1 fi - # Generate passwords and secrets + # === Generate passwords & secrets === ZITADEL_MASTERKEY="$(openssl rand -base64 32 | head -c 32)" POSTGRES_ROOT_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@" POSTGRES_ZITADEL_PASSWORD="$(openssl rand -base64 32 | sed 's/=//g')@" @@ -348,7 +437,7 @@ main() { echo "Generating configuration files..." - # Generate zitadel.env + # === zitadel.env === cat > zitadel.env < zdb.env < turnserver.conf < relay.env < dashboard.env echo "" > management.json - # Generate docker-compose.yml + # === docker-compose.yml template === cat > docker-compose.yml <<'EOF' services: # UI dashboard dashboard: image: netbirdio/dashboard:latest restart: unless-stopped - networks: + networks: - netbird - traefik_traefik env_file: - ./dashboard.env labels: - traefik.enable=true - - traefik.docker.network=traefik_traefik + - traefik.docker.network=traefik_default - traefik.http.services.netbird-dashboard.loadbalancer.server.port=80 - 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.certresolver=NETBIRD_TRAEFIK_SSL - traefik.http.routers.netbird-dashboard.priority=50 @@ -444,16 +531,16 @@ services: signal: image: netbirdio/signal:latest restart: unless-stopped - networks: + networks: - netbird - traefik_traefik labels: - 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.scheme=h2c - 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.certresolver=NETBIRD_TRAEFIK_SSL @@ -461,7 +548,7 @@ services: # 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=https + - 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 @@ -476,17 +563,17 @@ services: relay: image: netbirdio/relay:latest restart: unless-stopped - networks: + networks: - netbird - traefik_traefik env_file: - ./relay.env labels: - traefik.enable=true - - traefik.docker.network=traefik_traefik + - traefik.docker.network=traefik_default - 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.entrypoints=https + - traefik.http.routers.netbird-relay.entrypoints=websecure - traefik.http.routers.netbird-relay.tls=true - traefik.http.routers.netbird-relay.tls.certresolver=NETBIRD_TRAEFIK_SSL - traefik.http.routers.netbird-relay.priority=200 @@ -500,7 +587,7 @@ services: management: image: netbirdio/management:latest restart: unless-stopped - networks: + networks: - netbird - traefik_traefik volumes: @@ -517,27 +604,27 @@ services: ] labels: - 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-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_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.tls=true - traefik.http.routers.netbird-api.tls.certresolver=NETBIRD_TRAEFIK_SSL - traefik.http.routers.netbird-api.priority=200 # gRPC - 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.tls=true - traefik.http.routers.netbird-management-grpc.tls.certresolver=NETBIRD_TRAEFIK_SSL - traefik.http.routers.netbird-management-grpc.priority=200 - # WebSocket route for management - pass through without stripping prefix + # 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=https + - 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 @@ -566,101 +653,107 @@ services: # Zitadel - identity provider zitadel: 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' + 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: + networks: - netbird - traefik_traefik labels: - 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.scheme=h2c # OIDC wellknown - 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.priority=300 - traefik.http.routers.zitadel-wellknown.tls=true - traefik.http.routers.zitadel-wellknown.tls.certresolver=NETBIRD_TRAEFIK_SSL # 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.priority=300 - traefik.http.routers.zitadel-oauth.tls=true - traefik.http.routers.zitadel-oauth.tls.certresolver=NETBIRD_TRAEFIK_SSL # 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.priority=300 - traefik.http.routers.zitadel-oidc.tls=true - traefik.http.routers.zitadel-oidc.tls.certresolver=NETBIRD_TRAEFIK_SSL # UI Console - 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.priority=300 - traefik.http.routers.zitadel-ui.tls=true - traefik.http.routers.zitadel-ui.tls.certresolver=NETBIRD_TRAEFIK_SSL # Device flow - 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.priority=300 - traefik.http.routers.zitadel-device.tls=true - traefik.http.routers.zitadel-device.tls.certresolver=NETBIRD_TRAEFIK_SSL # Management API - 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.priority=300 - traefik.http.routers.zitadel-mgmt.tls=true - 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 - 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.priority=300 - traefik.http.routers.zitadel-admin.tls=true - traefik.http.routers.zitadel-admin.tls.certresolver=NETBIRD_TRAEFIK_SSL - # Endpoints gRPC Zitadel + # gRPC endpoints - 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.priority=400 - traefik.http.routers.zitadel-grpc-auth.tls=true - 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.entrypoints=https + - 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=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.entrypoints=https + - 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=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: driver: "json-file" options: @@ -671,13 +764,13 @@ services: zdb: restart: 'always' networks: [netbird] - image: 'postgres:16-alpine' + image: 'postgres:15-alpine' env_file: - ./zdb.env volumes: - netbird_zdb_data:/var/lib/postgresql/data:rw healthcheck: - test: ["CMD-SHELL", "pg_isready", "-d", "db_prod"] + test: ["CMD-SHELL", "pg_isready -U root"] interval: 5s timeout: 60s retries: 10 @@ -698,10 +791,13 @@ networks: driver: bridge traefik_traefik: external: true + name: traefik_default EOF -sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/${TRAEFIK_CERTRESOLVER}/g" docker-compose.yml - # Create machinekey directory + # Replace placeholders + sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/${TRAEFIK_CERTRESOLVER}/g" docker-compose.yml + + # Create machinekey dir mkdir -p machinekey chmod 777 machinekey @@ -717,7 +813,6 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/ echo "Waiting for Zitadel to initialize..." sleep 60 - # Configuration automatique de Zitadel echo "Configuring Zitadel applications..." INSTANCE_URL="https://$NETBIRD_DOMAIN" @@ -727,7 +822,7 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/ wait_pat "$TOKEN_PATH" echo "Reading Zitadel PAT" - PAT=$(cat $TOKEN_PATH) + PAT=$(cat "$TOKEN_PATH") if [ "$PAT" = "null" ]; then echo "Failed getting Zitadel PAT" exit 1 @@ -736,29 +831,24 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/ echo -n "Waiting for Zitadel to become ready " wait_api "$INSTANCE_URL" "$PAT" - # Create project echo "Creating Zitadel project" PROJECT_ID=$(create_new_project "$INSTANCE_URL" "$PAT") - # Create applications 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" - 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" MACHINE_USER_ID=$(create_service_user "$INSTANCE_URL" "$PAT") create_service_user_secret "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID" add_organization_user_manager "$INSTANCE_URL" "$PAT" "$MACHINE_USER_ID" - # Create admin user echo "Creating admin user" HUMAN_USER_ID=$(create_admin_user "$INSTANCE_URL" "$PAT" "$ZITADEL_ADMIN_USERNAME" "$ZITADEL_ADMIN_PASSWORD") add_instance_admin "$INSTANCE_URL" "$PAT" "$HUMAN_USER_ID" - # Clean up auto service user echo "Cleaning up auto service user" DATE=$(delete_auto_service_user "$INSTANCE_URL" "$PAT") if [ "$DATE" = "null" ]; then @@ -766,7 +856,6 @@ sed -i "s/NETBIRD_DOMAIN_PLACEHOLDER/${NETBIRD_DOMAIN}/g; s/NETBIRD_TRAEFIK_SSL/ echo "Please remove it manually" fi - # Generate NetBird configuration echo "Generating NetBird configuration..." # dashboard.env @@ -867,5 +956,4 @@ EOF echo "Note: The admin password will require changing on first login." } -# Execute main function main "$@" diff --git a/machinekey/zitadel-admin-sa.token b/machinekey/zitadel-admin-sa.token new file mode 100644 index 0000000..20bcf96 --- /dev/null +++ b/machinekey/zitadel-admin-sa.token @@ -0,0 +1 @@ +tlqWhCwoB4bEoKhqlbw_mHr8qGxjuJVdjfYGH70-Tr1bwzGu0Q5FNUMiostaLXoAk5GvCXc diff --git a/management.json b/management.json new file mode 100644 index 0000000..23c39fb --- /dev/null +++ b/management.json @@ -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 +} \ No newline at end of file diff --git a/readme.md b/readme.md index 352f400..d9969f3 100644 --- a/readme.md +++ b/readme.md @@ -13,7 +13,7 @@ cd netbird-traefik --- -## ⚙️ Configuration +## ⚙️ Configurations Before running the script, edit the following variables inside `install-netbird-traefik.sh`: diff --git a/reinit.sh b/reinit.sh new file mode 100755 index 0000000..baa0c6d --- /dev/null +++ b/reinit.sh @@ -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 diff --git a/reinit1.sh b/reinit1.sh new file mode 100755 index 0000000..90a4a82 --- /dev/null +++ b/reinit1.sh @@ -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! 🚀" \ No newline at end of file diff --git a/relay.env b/relay.env new file mode 100644 index 0000000..d990e9c --- /dev/null +++ b/relay.env @@ -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 diff --git a/turnserver.conf b/turnserver.conf new file mode 100644 index 0000000..d639469 --- /dev/null +++ b/turnserver.conf @@ -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 diff --git a/zdb.env b/zdb.env new file mode 100644 index 0000000..4e44d07 --- /dev/null +++ b/zdb.env @@ -0,0 +1,2 @@ +POSTGRES_USER=root +POSTGRES_PASSWORD=WuNCCFl9IrF4x1YOvUb5g0297qf4CE5qKPqlwY3HFn0@ diff --git a/zitadel.env b/zitadel.env new file mode 100644 index 0000000..33fdfa9 --- /dev/null +++ b/zitadel.env @@ -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 diff --git a/zitadel_api.log b/zitadel_api.log new file mode 100644 index 0000000..2e3759b --- /dev/null +++ b/zitadel_api.log @@ -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"}}