Secrets
Every secret in production, what it protects, where it lives and how to rotate it. Names only, never values.
All backend secrets live in one file on the server, ~/vod-app/infra/prod.env, which is git-ignored and never leaves the server. Frontend values live in the Vercel project settings. Nothing secret is committed to the repository.
Matrix of secrets × containers (api, worker, postgres, redis, minio, tusd).
Inventory
| Secret | Protects | Read by |
|---|---|---|
POSTGRES_PASSWORD (inside DATABASE_URL_SYNC / DATABASE_URL) | The database | postgres, api, worker |
REDIS_PASSWORD | Redis: Celery queue, processing lock, upload slots | redis, api, worker |
MINIO_ROOT_USER / MINIO_ROOT_PASSWORD | MinIO administrator | minio |
minio_access_key / minio_secret_key | S3 access used by the backend and tusd | api, worker, tusd |
jwt_secret_key | Signing of every access and refresh token | api, worker |
tus_hook_shared_secret | tusd → API hook calls | api, tusd |
RESEND_API_KEY | Sending email as the platform | api, worker |
PGADMIN_DEFAULT_PASSWORD | pgAdmin (local development only) | — in production |
Vercel: NEXT_PUBLIC_API_URL | Not secret (public in the bundle) | frontend build |
NEXT_PUBLIC_* values are compiled into JavaScript that every visitor downloads, so they must never contain anything secret.
Rules
- Generate values with a password manager or
openssl rand -base64 48. - Never reuse the defaults from
.env.exampleordocker-compose.local.yml. - Never paste
prod.envinto chats, issues or screenshots. Share variable names when asking for help. - Keep an offline copy of
prod.envin a password manager; it is not backed up anywhere else.
Rotation
Edit the value in prod.env, then restart the containers that read it. Some secrets also need a change inside the service itself.
dc up -d --force-recreate api workerEvery existing access and refresh token becomes invalid immediately, so all users are signed out. Use this as the emergency response to a suspected key leak.
After a suspected leak
- Rotate the leaked secret (JWT key first if unsure: it signs everyone out).
- Check
dc logs apifor unusual admin activity around the time of the leak. - Review recently created users and admins:
SELECT email, role, created_at FROM users ORDER BY created_at DESC LIMIT 20;