The app sits behind Nginx Proxy Manager which terminates TLS and
forwards plain HTTP. Without --proxy-headers, Starlette's request.url
keeps the inbound \`http\` scheme, so url_for() renders the static-CSS
\`<link>\` as http://… and the browser blocks it as mixed content under
the public https origin.
Adds --proxy-headers + --forwarded-allow-ips=* to the prod uvicorn
command. The wildcard is fine because the container has no host port —
only the intranet bridge (where NPM lives) can reach it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The shared \`intranet\` Docker network has many other containers
aliased as \`db\` and \`redis\` (mastodon-db, mailman redis, etc.).
Docker's embedded DNS resolved those before our own services, sending
the app's MySQL connection to the wrong IP and crashing it in a restart
loop.
Switched both DATABASE_URL and REDIS_URL in the prod overlay to use
the project-prefixed container names (readmarkets-db-1,
readmarkets-redis-1), which are globally unique on the Docker daemon.
Applied to both app and scheduler.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Compose merges list-typed fields like \`ports\` by concatenation, so the
previous prod overlay couldn't clear the base file's host port binding;
the VPS app ended up listening on both port 80 (intranet) AND host port
8800 simultaneously.
Restructured to the conventional dev/prod split:
- docker-compose.yml: no host port — prod-ready by default
- docker-compose.override.yml: dev-only host port binding (auto-loaded
by \`docker compose up\` locally, skipped when prod uses explicit -f)
- docker-compose.prod.yml: command-port 80 + intranet network only
Production invocation:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The VPS deployment sits behind Nginx Proxy Manager on a pre-existing
`intranet` Docker bridge network. The overlay drops the host port
binding from the base compose, switches uvicorn to listen on port 80
inside the container (uniform NPM upstreams), and joins the app to
both `default` (for db/redis) and `intranet` (for NPM ingress).
Apply with:
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Local dev (compose without the overlay) is unchanged — still binds
the host port from CASSANDRA_PORT in .env.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>