# Deployment Architecture ## Single published port Production Docker Compose (`compose.yml`) publishes **exactly one** host port: `edge` (Nginx), mapped via `APP_HTTPS_PORT` (default `443`). No other service (`api`, `worker`, `postgres`, `redis`) defines a Compose `ports:` mapping — they are reachable only over the internal `travel` bridge network via their service DNS names. `scripts/verify-compose-invariants.mjs` (wired into `pnpm test:compose`) fails the build if this invariant regresses. ## TLS The edge container listens on container port 443 only and requires a certificate and private key mounted at the paths configured by `TLS_CERT_FILE`/`TLS_KEY_FILE` (bind-mounted read-only to `/run/tls/tls.crt` and `/run/tls/tls.key`). There is no port-80 fallback in this phase. ## Internal reachability - PostgreSQL and Redis are not reachable from the host through Compose-published ports; only containers on the `travel` network can reach them. - The API is not reachable from the host directly; all external traffic reaches it through `edge`'s `/api/` and `/health/` proxy locations. - The worker process has neither `ports` nor `expose` — it accepts no inbound traffic at all. - Outbound egress from `api` and `worker` (e.g. to Mistral, web research, SMTP providers in later phases) remains allowed. ## Image tags TeamCity supplies immutable `IMAGE_TAG` values (see `scripts/teamcity/build-images.sh`); `latest`/floating tags are refused. `REGISTRY` and `IMAGE_TAG` together select the exact image digest-equivalent tag deployed to a host. ## TeamCity wiring | TeamCity stage | Repository entry point | |------------------------|----------------------------------| | Validate | `scripts/teamcity/validate.sh` | | Build + Push | `scripts/teamcity/build-images.sh` | | Deploy over SSH | `scripts/teamcity/deploy.sh` | | Post-deploy smoke | `scripts/teamcity/smoke.sh` | | Rollback | `scripts/teamcity/rollback.sh` | The existing TeamCity project configures these as command-line/SSH build steps; all deployment logic stays in version control, not in TeamCity step configuration.