Replace Traefik with host-webserver reverse proxy in prod deployment
CI / lint (push) Canceled after 0s
CI / typecheck (push) Canceled after 0s
CI / unit-tests (push) Canceled after 0s
CI / integration-tests (push) Canceled after 0s
CI / container-build (push) Canceled after 0s
CI / dependency-audit (push) Canceled after 0s

The production host runs cPanel, which already owns ports 80/443 for
other sites on the box -- there's no Traefik there. docker-compose.prod.yml
now binds the api container to 127.0.0.1:8000 only; the host's own
Apache/LiteSpeed (via cPanel) reverse-proxies api.amdbs.net to it and
terminates TLS itself (AutoSSL). Dropped the external traefik-public
network requirement and Traefik labels entirely.

Also corrected a separate latent inaccuracy while touching this: a bare
`docker compose up` (not `docker stack deploy`) never actually honored
deploy.replicas -- docs now say so and point at `--scale` instead of
implying free multi-replica scaling that was never really happening.

README's Production deployment section rewritten with concrete steps:
Cloudflare DNS record, cPanel subdomain + reverse proxy, then compose up.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
NixReaper
2026-09-05 20:49:55 -05:00
co-authored by Claude Sonnet 5
parent ec9b1c28e3
commit 905cd202eb
4 changed files with 59 additions and 47 deletions
+33 -21
View File
@@ -12,8 +12,8 @@ build specification this repository implements, and
## Architecture at a glance
A modular monolith (not microservices): a stateless FastAPI API behind
Traefik, PostgreSQL as the sole source of truth, Redis for disposable
A modular monolith (not microservices): a stateless FastAPI API behind a
reverse proxy, PostgreSQL as the sole source of truth, Redis for disposable
caching/rate-limiting/queueing, and arq workers for async metadata
ingestion. Full diagram and reasoning in
[`docs/architecture.md`](docs/architecture.md).
@@ -170,28 +170,40 @@ example. Concurrency per worker process is controlled by
## Production deployment
```bash
docker compose -f docker-compose.prod.yml up --build -d
```
The production host runs cPanel, which already owns ports 80/443 for other
sites on the box — there's no Traefik here. `docker-compose.prod.yml` binds
the API container to `127.0.0.1:8000` only; the host's own webserver
(Apache or LiteSpeed, via cPanel) reverse-proxies `api.amdbs.net` to it and
terminates TLS itself (cPanel's AutoSSL can issue the Let's Encrypt cert
once the subdomain exists and DNS resolves).
Traefik-ready (labels on the `api` service), PgBouncer in front of
PostgreSQL (transaction pooling — `DATABASE_BEHIND_TRANSACTION_POOLER=true`
disables asyncpg's server-side prepared statements, which don't survive
transaction-mode pooling), horizontally-scaled API and worker replicas. See
1. **DNS** (Cloudflare, where `amdbs.net` is managed): add an A record for
`api.amdbs.net` pointing at the server's IP.
2. **cPanel**: create the `api.amdbs.net` subdomain so AutoSSL picks it up
and issues a cert; then reverse-proxy that vhost to `127.0.0.1:8000` —
either cPanel/WHM's Application Manager if available, or a custom
Apache/LiteSpeed vhost include (`ProxyPass`/`ProxyPassReverse` for
Apache; LiteSpeed's External App + rewrite rule for LiteSpeed).
3. **`.env`** on the server (never committed), beyond the base vars in
`.env.example`:
```bash
CORS_ORIGINS=https://www.amdbs.net # must include the frontend's real origin
```
4. **Deploy**:
```bash
docker compose -f docker-compose.prod.yml up --build -d
```
PgBouncer sits in front of PostgreSQL (transaction pooling —
`DATABASE_BEHIND_TRANSACTION_POOLER=true` disables asyncpg's server-side
prepared statements, which don't survive transaction-mode pooling). See
[`docs/architecture.md`](docs/architecture.md).
Requires an external Traefik instance already running with a
`traefik-public` Docker network and a `letsencrypt` cert resolver
configured (`docker-compose.prod.yml` attaches to it, it doesn't run
Traefik itself). Aurora Core's production domain split is `api.amdbs.net`
(this backend) / `www.amdbs.net` (frontend, separate project) — the
production `.env` (never committed) needs, beyond the base vars in
`.env.example`:
```bash
AURORA_API_HOST=api.amdbs.net # Traefik router rule (docker-compose.prod.yml only, not read by the app)
CORS_ORIGINS=https://www.amdbs.net # must include the frontend's real origin
```
Aurora Core's production domain split is `api.amdbs.net` (this backend) /
`www.amdbs.net` (frontend, a separate project).
## Known limitations