diff --git a/.gitea/workflows/registry-build-deploy.yml b/.gitea/workflows/registry-build-deploy.yml index 211f33a..84e81a1 100644 --- a/.gitea/workflows/registry-build-deploy.yml +++ b/.gitea/workflows/registry-build-deploy.yml @@ -9,7 +9,8 @@ # DEPLOY_SECRETS_DIR absolute path on runner, e.g. C:/dyolink/secrets # # Optional: -# STAGING_HTTP_PORT host port for nginx (default 8088) +# STAGING_HTTP_PORT public port (default 8088) — Windows portproxy listens here +# STAGING_LOCAL_PORT Docker bind on 127.0.0.1 (default 18088) — must not equal 8088 if portproxy owns 8088 # CLONE_HOST git clone host when runner = Gitea host → 127.0.0.1:3000 # # Same Windows PC runs Gitea + runner + deploy: @@ -162,11 +163,14 @@ jobs: } $stagingPort = '${{ vars.STAGING_HTTP_PORT }}'.Trim() if ([string]::IsNullOrWhiteSpace($stagingPort)) { $stagingPort = '8088' } + $localPort = '${{ vars.STAGING_LOCAL_PORT }}'.Trim() + if ([string]::IsNullOrWhiteSpace($localPort)) { $localPort = '18088' } $imageTag = "${{ needs.build-and-push.outputs.image_tag }}" $lines = @( "REGISTRY_PREFIX=${{ vars.REGISTRY_HOST }}/${{ vars.REGISTRY_OWNER }}", "IMAGE_TAG=$imageTag", "STAGING_HTTP_PORT=$stagingPort", + "STAGING_LOCAL_PORT=$localPort", "DEPLOY_SECRETS_DIR=$SD" ) Set-Location infrastructure diff --git a/infrastructure/STAGING-DEPLOY.md b/infrastructure/STAGING-DEPLOY.md index 3b51cee..f402ff2 100644 --- a/infrastructure/STAGING-DEPLOY.md +++ b/infrastructure/STAGING-DEPLOY.md @@ -144,7 +144,8 @@ Rules: | `PUBLIC_BASE_URL` | `http://178.131.50.201:8088` | How **users** open staging in a browser (public IP OK) | | `DEPLOY_SECRETS_DIR` | `C:/dyolink/secrets` | Forward slashes OK on Windows | | `CLONE_HOST` | `127.0.0.1:3000` | Git clone (runs on Windows host, not inside Docker VM) | -| `STAGING_HTTP_PORT` | `8088` | Optional (8088 is default) | +| `STAGING_HTTP_PORT` | `8088` | Public port (router + portproxy). Optional. | +| `STAGING_LOCAL_PORT` | `18088` | Docker bind on `127.0.0.1`. Must not be `8088` if portproxy already uses 8088. | **Naming note:** Gitea rejects variable names starting with `GITEA_` or `GITHUB_`. Use `CLONE_HOST`, not `GITEA_CLONE_URL`. @@ -167,18 +168,22 @@ New-NetFirewallRule -DisplayName "Dyolink Staging 8088" -Direction Inbound -Prot ### 7. External access on Windows + Docker Desktop (portproxy) -Gitea on **:3000** runs natively on Windows and is reachable from your Mac. Staging **:8088** runs in **Docker Desktop** — `127.0.0.1:8088` works on the PC, but `http://:8088` from another machine may get **Empty reply from server** unless you forward the port. +Gitea on **:3000** runs natively on Windows. Staging nginx binds **127.0.0.1:18088** (not 8088). Windows **portproxy** then maps public **8088 → 18088**. Do **not** bind Docker on 8088 — portproxy already owns that port (`bind: access permissions` if you try). -Compose binds nginx to **127.0.0.1:8088** only. After deploy, run **once** in **PowerShell as Administrator**: +Run **once** in **PowerShell as Administrator** (replace the old 8088→8088 rule if you had one): ```powershell -netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8088 connectaddress=127.0.0.1 connectport=8088 +netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=8088 +netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8088 connectaddress=127.0.0.1 connectport=18088 netsh interface portproxy show all +Start-Service iphlpsvc +Set-Service iphlpsvc -StartupType Automatic ``` Verify on the server: ```powershell +curl http://127.0.0.1:18088/health curl http://127.0.0.1:8088/health ``` @@ -277,7 +282,8 @@ On the Windows host, from repo `infrastructure/`: | `Missing database.staging.env` | Check `DEPLOY_SECRETS_DIR` path and file names | | `docker login` denied | Token needs package permissions; check username/secret | | Git clone fails in workflow | Set `CLONE_HOST=127.0.0.1:3000` | -| Port 8088 unreachable from Mac / empty reply | Docker Desktop: run **portproxy** (§7). `127.0.0.1:8088/health` must work on Windows first. | +| Port 8088 bind forbidden / access permissions | Portproxy already owns 8088. Bind Docker to `18088` and point portproxy **8088 → 127.0.0.1:18088**. | +| Port 8088 unreachable from Mac / empty reply | Docker Desktop: run **portproxy** (§7). `127.0.0.1:18088/health` must work on Windows first. | | Backend restart loop | JWT secrets still placeholder; fix `backend.staging.env` | | Backend DB auth error | `DATABASE_URL` password ≠ `POSTGRES_PASSWORD` | | `dumb-init docker-entrypoint.sh: No such file or directory` | Windows CRLF in shell scripts — fixed in Dockerfiles (rebuild images). | diff --git a/infrastructure/deploy.registry.env.example b/infrastructure/deploy.registry.env.example index 87f1add..61c4389 100644 --- a/infrastructure/deploy.registry.env.example +++ b/infrastructure/deploy.registry.env.example @@ -11,8 +11,10 @@ REGISTRY_PREFIX=178.131.50.201:3000/yourgiteauser # Short git SHA from CI, or "latest" after a manual pull of :latest IMAGE_TAG=latest -# Host port published for nginx (URL = http://:) +# Public URL port (router + Windows portproxy listen here) STAGING_HTTP_PORT=8088 +# Docker nginx bind on localhost only (must differ from 8088 when portproxy owns 8088) +STAGING_LOCAL_PORT=18088 # Absolute path on the server where database.staging.env and backend.staging.env live. # Use forward slashes on Windows. Same path as Gitea Actions variable DEPLOY_SECRETS_DIR. diff --git a/infrastructure/docker-compose.registry.yml b/infrastructure/docker-compose.registry.yml index 2603d4f..7c708d8 100644 --- a/infrastructure/docker-compose.registry.yml +++ b/infrastructure/docker-compose.registry.yml @@ -91,8 +91,9 @@ services: frontend: condition: service_healthy ports: - # Localhost only — Docker Desktop on Windows often breaks 0.0.0.0; use netsh portproxy for LAN/public (see STAGING-DEPLOY.md). - - "127.0.0.1:${STAGING_HTTP_PORT:-8088}:80" + # Bind a private localhost port — Windows portproxy already owns public 8088. + # See STAGING-DEPLOY.md §7: portproxy 0.0.0.0:8088 → 127.0.0.1:18088 + - "127.0.0.1:${STAGING_LOCAL_PORT:-18088}:80" volumes: - ./nginx/http-only.conf:/etc/nginx/conf.d/default.conf:ro - ./logs/nginx-staging:/var/log/nginx diff --git a/infrastructure/docker-compose.staging.yml b/infrastructure/docker-compose.staging.yml index 54a5102..13ed5ca 100644 --- a/infrastructure/docker-compose.staging.yml +++ b/infrastructure/docker-compose.staging.yml @@ -93,7 +93,7 @@ services: frontend: condition: service_healthy ports: - - "127.0.0.1:${STAGING_HTTP_PORT:-8088}:80" + - "127.0.0.1:${STAGING_LOCAL_PORT:-18088}:80" volumes: - ./nginx/http-only.conf:/etc/nginx/conf.d/default.conf:ro - ./logs/nginx-staging:/var/log/nginx