Skip to content

Operations

  • Deploying./deploy.sh, and why a restart is not a deploy.

  • Configuration — every environment variable, and the handful of settings that live in Redis instead.

  • Signing in — Authentik, the token flow, and the way back in when the provider breaks.

  • Background work — Celery, the beat schedule, and the one job that destroys anything.

  • Backups and restore — what is backed up, where, and what is not.

  • Running the tests — the unit suite and the end-to-end stack.

  • Command line — the eleven maintenance commands.

  • Troubleshooting — the failures that have actually happened here.

The services

Service Image / build Does
frontend ./frontend Nginx serving the built React app, proxying /api to the backend. Published on 127.0.0.1:8081.
backend ./backend FastAPI on uvicorn, 4 workers, --proxy-headers. No host port — nginx is the only thing that can reach it.
celery ./backend The workers, --concurrency=2. Scale this freely; it runs no scheduler.
celery-beat ./backend The scheduler. Exactly one, always.
postgres pgvector/pgvector:pg16 Rows and 1024-dimension embeddings in one place.
redis redis:7-alpine Broker, rate limits, site settings, job state, session keys.
minio minio/minio Object storage for media. Aliased quiz-minio on the network.
db-backup prodrigestivill/postgres-backup-local:16 Daily dumps into ./backups.
quiz-telegram-bot ./telegram-bot
loki, promtail, grafana Logs. Grafana on 127.0.0.1:3002, Loki on 127.0.0.1:3100.

Two aliases that exist because of a real outage

The backend and the worker sit on three external networks besides the default one, and two of those carry a service with a name this stack also uses.

  • Redis. danvics_litellm has its own redis, and Docker resolved that one for the backend and the worker while celery-beat, on the default network alone, resolved this one. Site settings, job state and the queue lived in the LLM proxy's Redis while the scheduler's tasks piled up here with no worker reading them. REDIS_URL must name quiz-redis-1, the container name.
  • MinIO. danvics_milvus has its own minio. Every object read failed with InvalidAccessKeyId while the bucket simply looked empty. This stack's MinIO carries the network alias quiz-minio.

Neither MinIO nor Redis publishes a host port.

Healthchecks

Service Check Why that one
postgres pg_isready -U pedquiz
celery celery -A app.tasks inspect ping A crash-looping worker used to be invisible: restart: unless-stopped plus an ImportError is a silent loop whose only symptom is that queued jobs never run. It went 69 restarts before anybody noticed.
celery-beat Reads /proc/*/cmdline for a process with beat in it Beat answers no ping — it is a clock, not a worker. pgrep and ps are not in python:3.11-slim, so the first version of this check reported a healthy beat as broken.
minio mc ready local
backend none

GET /api/health returns {"status": "ok"} and is deliberately unversioned as well as versioned: the thing that watches it is a monitor nobody edits for a year.