Deployment
Reference deployment (Railway)
Section titled “Reference deployment (Railway)”The reference instance runs at https://kyc-server-production.up.railway.app:
| Piece | Detail |
|---|---|
kyc-server | Built from server/Dockerfile; auto-deploys on push to main |
| PostgreSQL | Managed service, wired via a DATABASE_URL reference variable |
Volume at /data | Vault blobs, attestation key, archive staging, face models |
| Domain | Railway-managed TLS |
Migrations apply automatically on boot (Alembic). The first verification after a fresh deploy downloads the InsightFace models (~300 MB) to the volume — slow once, cached forever.
Secrets checklist
Section titled “Secrets checklist”Set as platform secrets (Railway variables, K8s secrets, etc.) — never in git:
| Variable | Requirement |
|---|---|
VAULT_MASTER_KEY | 32 bytes base64. Back up offline immediately — loss = unrecoverable vault, by design |
BAQSHI_API_KEYS | Comma-separated; one key per consuming product |
WEBHOOK_SIGNING_KEY | Share with webhook consumers out-of-band |
ANTHROPIC_API_KEY | Enables Claude document inspection; with neither AI key set everything routes to manual review (fail-safe) |
GEMINI_API_KEY | Enables Gemini document inspection (GEMINI_MODEL, default gemini-2.5-flash; force a provider with DOCUMENT_AI_PROVIDER) |
DATABASE_URL | Postgres in production (postgres:// URLs are auto-normalized) |
PUBLIC_BASE_URL, HANDOFF_WEB_URL | Must match your public domain — they’re baked into QR/handoff URLs |
Generate keys properly:
python -c "import os,base64; print(base64.b64encode(os.urandom(32)).decode())" # master keypython -c "import secrets; print('bk_live_' + secrets.token_urlsafe(32))" # API keySelf-hosting anywhere else
Section titled “Self-hosting anywhere else”The server is one container + Postgres + a persistent disk:
docker build -t baqshi-kyc server/docker run -p 8000:8000 -v kyc-data:/data \ -e DATABASE_URL=… -e VAULT_MASTER_KEY=… -e BAQSHI_API_KEYS=… \ -e PUBLIC_BASE_URL=https://kyc.example.com \ -e HANDOFF_WEB_URL=https://kyc.example.com/v \ baqshi-kycRequirements: Python 3.12 base (already in the Dockerfile — 3.14 lacks onnxruntime wheels), ~2 GB RAM for the face models, CPU-only is fine at moderate volume.
Local development:
cd serverpython3.12 -m venv .venv && . .venv/bin/activatepip install -e ".[dev,face]" # drop `,face` for a lighter install (fail-safe mode)uvicorn app.main:app --reload # SQLite + auto-generated dev keysProduction posture checklist
Section titled “Production posture checklist”- TLS on a real domain; update the two URL variables
- Master key backed up offline; consider KMS/HSM (see Keys)
-
ANTHROPIC_API_KEYorGEMINI_API_KEYset - CDN/WAF in front for volumetric protection (app-level limits are per-instance)
- Postgres backups enabled (the DB is PII-light, but it holds the wrapped keys — losing it strands the vault as surely as losing the master key)
- Archival job scheduled (Archival & erasure)
- Monitoring wired (Monitoring)
- Calibration run done (Fraud signals)