06. Infra & Local Ops¶
Local topology¶
graph TD
classDef default fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#f8fafc
classDef highlight fill:#065f46,stroke:#34d399,stroke-width:2px,color:#f0fdf4
classDef warning fill:#78350f,stroke:#fbbf24,stroke-width:2px,color:#fffbeb
FE["Vite :5173"]:::highlight
API["Uvicorn :8000"]:::highlight
W["Celery worker"]:::highlight
PG["Postgres host :5433"]
RD["Redis :6379"]
MN["MinIO :9000 / :9001"]
MS["Meilisearch"]:::warning
QD["Qdrant"]:::warning
FE --> API
API --> PG
API --> RD
API --> MN
W --> PG
W --> RD
W --> MN
MS -.->|"compose-full only"| W
QD -.->|"compose-full only"| W
linkStyle default stroke:#64748b,stroke-width:2px
App processes run on the host via Makefile. Docker Compose provides data stores only (no app Dockerfiles in this checkout).
Compose services¶
| File | Services |
|---|---|
infra/docker-compose.yml |
Postgres 17 (5433:5432), Redis 7, MinIO |
infra/docker-compose-full.yml |
Above + Meilisearch + Qdrant |
Volumes live under volumes/ (gitignored pattern in project docs).
Common Makefile targets¶
Typical flow (see root Makefile for exact names):
- Bring up infra (
make up/ compose) - Start backend, Celery worker, frontend
make test,make lintmake docs-servefor in-repo MkDocs wiki
Logs are written under logs/ when using Makefile process wrappers.
Environment variables¶
Primary loader: backend/app/config.py with env_file="../.env".
| Concern | Settings fields | .env.example names |
|---|---|---|
| Object store | S3_ENDPOINT_URL, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET_DOCS |
MINIO_ENDPOINT, MINIO_ACCESS_KEY, MINIO_SECRET_KEY, MINIO_BUCKET_DOCS |
| Database | DATABASE_URL |
postgresql+asyncpg://...@localhost:5432/... |
| Compose Postgres | host port 5433 | example still 5432 |
Confirmed drift: copying .env.example alone does not populate S3_* fields the app reads. Host-run API likely needs localhost:5433 in DATABASE_URL.
Other important knobs: OCR_ENGINE, LLM keys/base URL, Sarvam/Paddle URLs, factsheet char limits, JWT_SECRET / OIDC placeholders.
Networking pitfalls¶
| Issue | Detail |
|---|---|
| Vite proxy | Targets localhost:8888; Makefile API default 8000 |
| CORS | API allows * origins with credentials |
| Paddle layout OCR | Expects external PADDLE_OCR_SERVICE_URL (often separate ocr-service) |
Secrets handling¶
.envgitignored;.env.examplecommitted with placeholders- No sealed-secrets / vault integration in repo
- Default
JWT_SECRET=change-meunsuitable for any shared environment
Observability¶
- Structured-ish request logging via
LoggingMiddleware - Job/chunk error strings in DB
- No Prometheus/OpenTelemetry wiring found
- In-repo MkDocs under
docs/for human ops/onboarding
Infra interview Q&A¶
Q: What do you Dockerize locally?
A: Postgres, Redis, MinIO (and optionally search). API, worker, and Vite run on the host for faster iteration.
Q: Why is search in compose-full if unused?
A: Forward-looking infra for UC3; keeps the full stack one command away without coupling the current pipeline to those services.