diff --git a/deploy/templates/turnserver.remote.conf.template b/deploy/templates/turnserver.remote.conf.template index 0dcb2a5..6e6c222 100644 --- a/deploy/templates/turnserver.remote.conf.template +++ b/deploy/templates/turnserver.remote.conf.template @@ -9,8 +9,8 @@ tls-listening-port=5349 min-port=49152 max-port=49200 -# Network - external IP for NAT traversal -external-ip=__DOGRAH_SERVER_IP__ +# Network - external IP / host for NAT traversal +external-ip=__DOGRAH_TURN_EXTERNAL_IP__ # Realm realm=dograh.com diff --git a/docker-compose.yaml b/docker-compose.yaml index 307c6d6..4a980f2 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -59,21 +59,69 @@ services: networks: - app-network + dograh-init: + image: bash:5.2 + container_name: dograh_init + profiles: ["remote", "local-turn"] + environment: + ENVIRONMENT: "${ENVIRONMENT:-local}" + SERVER_IP: "${SERVER_IP:-}" + PUBLIC_HOST: "${PUBLIC_HOST:-}" + PUBLIC_BASE_URL: "${PUBLIC_BASE_URL:-}" + BACKEND_API_ENDPOINT: "${BACKEND_API_ENDPOINT:-http://localhost:8000}" + MINIO_PUBLIC_ENDPOINT: "${MINIO_PUBLIC_ENDPOINT:-http://localhost:9000}" + TURN_HOST: "${TURN_HOST:-}" + TURN_SECRET: "${TURN_SECRET:-}" + FASTAPI_WORKERS: "${FASTAPI_WORKERS:-1}" + volumes: + - ./scripts:/workspace/scripts:ro + - ./deploy:/workspace/deploy:ro + - ./certs:/certs:ro + - nginx-generated:/generated/nginx + - coturn-generated:/generated/coturn + command: + - /workspace/scripts/run_dograh_init.sh + nginx: image: nginx:alpine container_name: nginx_https profiles: ["remote"] depends_on: - - ui + dograh-init: + condition: service_completed_successfully + ui: + condition: service_started ports: - "80:80" - "443:443" volumes: - - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro + - nginx-generated:/etc/nginx/conf.d:ro - ./certs:/etc/nginx/certs:ro networks: - app-network + coturn: + image: coturn/coturn:4.8.0 + container_name: coturn + restart: unless-stopped + profiles: ["remote", "local-turn"] + depends_on: + dograh-init: + condition: service_completed_successfully + ports: + - "3478:3478/udp" + - "3478:3478/tcp" + - "5349:5349/udp" + - "5349:5349/tcp" + - "49152-49200:49152-49200/udp" + volumes: + - coturn-generated:/etc/coturn:ro + command: + - -c + - /etc/coturn/turnserver.conf + networks: + - app-network + api: image: ${REGISTRY:-dograhai}/dograh-api:latest volumes: @@ -195,25 +243,6 @@ services: networks: - app-network - coturn: - image: coturn/coturn:4.8.0 - container_name: coturn - restart: unless-stopped - profiles: ["remote", "local-turn"] - ports: - - "3478:3478/udp" - - "3478:3478/tcp" - - "5349:5349/udp" - - "5349:5349/tcp" - - "49152-49200:49152-49200/udp" - volumes: - - ./turnserver.conf:/etc/coturn/turnserver.conf:ro - command: - - -c - - /etc/coturn/turnserver.conf - networks: - - app-network - volumes: postgres_data: redis_data: @@ -221,6 +250,10 @@ volumes: driver: local shared-tmp: driver: local + nginx-generated: + driver: local + coturn-generated: + driver: local networks: app-network: diff --git a/scripts/lib/remote_common.sh b/scripts/lib/remote_common.sh index 2b72bfb..a1345c8 100644 --- a/scripts/lib/remote_common.sh +++ b/scripts/lib/remote_common.sh @@ -218,6 +218,21 @@ dograh_sync_remote_env_file() { dograh_set_env_key "$env_file" TURN_HOST "$public_host" } +dograh_validate_remote_runtime_env() { + [[ "${FASTAPI_WORKERS:-}" =~ ^[1-9][0-9]*$ ]] || dograh_fail "FASTAPI_WORKERS must be a positive integer" + [[ -n "${TURN_SECRET:-}" ]] || dograh_fail "TURN_SECRET is missing" + [[ -n "${PUBLIC_HOST:-}" ]] || dograh_fail "PUBLIC_HOST is missing" + [[ -n "${PUBLIC_BASE_URL:-}" ]] || dograh_fail "PUBLIC_BASE_URL is missing" + [[ -n "${BACKEND_API_ENDPOINT:-}" ]] || dograh_fail "BACKEND_API_ENDPOINT is missing" + [[ -n "${MINIO_PUBLIC_ENDPOINT:-}" ]] || dograh_fail "MINIO_PUBLIC_ENDPOINT is missing" + [[ -n "${TURN_HOST:-}" ]] || dograh_fail "TURN_HOST is missing" + dograh_is_ipv4 "${SERVER_IP:-}" || dograh_fail "SERVER_IP must be a valid IPv4 address" + [[ "${PUBLIC_BASE_URL}" =~ ^https?:// ]] || dograh_fail "PUBLIC_BASE_URL must include http:// or https://" + [[ "${BACKEND_API_ENDPOINT}" == "${PUBLIC_BASE_URL}" ]] || dograh_fail "BACKEND_API_ENDPOINT must match PUBLIC_BASE_URL" + [[ "${MINIO_PUBLIC_ENDPOINT}" == "${PUBLIC_BASE_URL}" ]] || dograh_fail "MINIO_PUBLIC_ENDPOINT must match PUBLIC_BASE_URL" + [[ "${TURN_HOST}" == "${PUBLIC_HOST}" ]] || dograh_fail "TURN_HOST must match PUBLIC_HOST" +} + dograh_render_remote_nginx_conf() { local project_dir=${1:-$(dograh_project_dir)} local destination=${2:-"$project_dir/nginx.conf"} @@ -263,15 +278,17 @@ dograh_render_remote_turn_conf() { local project_dir=${1:-$(dograh_project_dir)} local destination=${2:-"$project_dir/turnserver.conf"} local template="" + local external_ip="${TURN_EXTERNAL_IP:-${SERVER_IP:-}}" template="$(dograh_template_path "turnserver.remote.conf.template")" + [[ -n "$external_ip" ]] || dograh_fail "TURN external IP/host is missing" awk \ - -v server_ip="$SERVER_IP" \ + -v external_ip="$external_ip" \ -v turn_secret="$TURN_SECRET" \ ' { - gsub(/__DOGRAH_SERVER_IP__/, server_ip) + gsub(/__DOGRAH_TURN_EXTERNAL_IP__/, external_ip) gsub(/__DOGRAH_TURN_SECRET__/, turn_secret) print } @@ -357,7 +374,10 @@ dograh_download_remote_support_bundle() { dograh_download_bundle_file "$project_dir/remote_up.sh" "remote_up.sh" chmod +x "$project_dir/remote_up.sh" + mkdir -p "$project_dir/scripts" dograh_download_bundle_file "$project_dir/scripts/lib/remote_common.sh" "scripts/lib/remote_common.sh" + dograh_download_bundle_file "$project_dir/scripts/run_dograh_init.sh" "scripts/run_dograh_init.sh" + chmod +x "$project_dir/scripts/run_dograh_init.sh" dograh_download_bundle_file "$project_dir/deploy/templates/nginx.remote.conf.template" "deploy/templates/nginx.remote.conf.template" dograh_download_bundle_file "$project_dir/deploy/templates/turnserver.remote.conf.template" "deploy/templates/turnserver.remote.conf.template" } diff --git a/scripts/run_dograh_init.sh b/scripts/run_dograh_init.sh new file mode 100755 index 0000000..803375e --- /dev/null +++ b/scripts/run_dograh_init.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORKSPACE_DIR="${DOGRAH_INIT_WORKSPACE_DIR:-/workspace}" +OUTPUT_ROOT="${DOGRAH_INIT_OUTPUT_ROOT:-/generated}" +NGINX_OUTPUT_DIR="$OUTPUT_ROOT/nginx" +COTURN_OUTPUT_DIR="$OUTPUT_ROOT/coturn" +CERTS_DIR="${DOGRAH_INIT_CERTS_DIR:-/certs}" + +# shellcheck disable=SC1091 +. "$SCRIPT_DIR/lib/remote_common.sh" + +DOGRAH_REMOTE_PROJECT_DIR="$WORKSPACE_DIR" + +mkdir -p "$NGINX_OUTPUT_DIR" "$COTURN_OUTPUT_DIR" + +if [[ "${ENVIRONMENT:-local}" == "production" ]]; then + dograh_validate_remote_runtime_env + [[ -f "$CERTS_DIR/local.crt" ]] || dograh_fail "certs/local.crt not found" + [[ -f "$CERTS_DIR/local.key" ]] || dograh_fail "certs/local.key not found" + + export TURN_EXTERNAL_IP="$SERVER_IP" + dograh_render_remote_nginx_conf "$WORKSPACE_DIR" "$NGINX_OUTPUT_DIR/default.conf" + dograh_render_remote_turn_conf "$WORKSPACE_DIR" "$COTURN_OUTPUT_DIR/turnserver.conf" + dograh_success "✓ dograh-init rendered remote nginx and coturn config" + exit 0 +fi + +if [[ -n "${TURN_SECRET:-}" && -n "${TURN_HOST:-}" ]]; then + export TURN_EXTERNAL_IP="$TURN_HOST" + dograh_render_remote_turn_conf "$WORKSPACE_DIR" "$COTURN_OUTPUT_DIR/turnserver.conf" + dograh_success "✓ dograh-init rendered local TURN config" + exit 0 +fi + +dograh_success "✓ dograh-init no-op for current profile"