Configuration¶
Every environment variable the system reads, where it comes from, and where the example files lie.
How configuration is loaded¶
| Environment | Source |
|---|---|
| Local | backend/.env, frontend/.env, read by python-decouple and Vite |
| Staging | Environment variables on the compose services |
| Production | Docker Swarm secrets named TWTLNKPROD_*, exported by backend/entrypoint.sh:30-98 only when the variable is not already set |
The TWTLNKPROD_* list in entrypoint.sh is the authoritative inventory of production keys.
When you add a setting, add it there too or production will silently fall back to the
config() default.
Backend¶
Django core¶
| Variable | Purpose |
|---|---|
DEBUG |
Never true outside local development |
SECRET_KEY |
Django signing key |
TIME_ZONE |
Server timezone |
ALLOWED_HOSTS |
Comma-separated hostnames |
CSRF_TRUSTED_ORIGINS |
Origins allowed to post to the admin |
Database¶
DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, DB_PORT.
Use 5433 locally to match backend/docker-compose-dev.yml.
Object storage (MinIO / S3)¶
S3_ENDPOINT, S3_ACCESS_KEY, S3_SECRET_KEY, S3_BUCKET, S3_USE_HTTPS.
Recordings, voice messages and uploads live here; the API serves them as presigned URLs.
Twilio¶
| Variable | Purpose |
|---|---|
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN |
Account credentials; the auth token also verifies webhook signatures |
TWILIO_API_KEY, TWILIO_API_SECRET |
Used to mint Voice SDK access tokens |
TWILIO_TWIML_APP_SID |
The TwiML application backing outbound client calls |
TWILIO_CLIENT_TOKEN_TIME |
Access token lifetime |
TWILIO_WEB_HOOK_DOMAIN |
Public domain Twilio calls back into. Changing it means re-running backend/tools/set_webhooks.py |
TWILIO_FCM_TOKEN, TWILIO_APN_TOKEN |
Push credentials for Voice SDK notifications |
TWILIO_CALL_QUEUE_NAME, TWILIO_CALL_QUEUE_SID |
The hold queue |
TWILIO_CONF_WAIT_URL |
Hold music or message for conferences |
Real-time (inert)¶
WEBSOCKET_DOMAIN, CHANNELS_BACKEND (redis or rabbit), CHANNELS_REDIS_HOST,
CHANNELS_REDIS_PORT, CHANNELS_RABBIT, HEARTBEAT_TIMEOUT.
These configure Django Channels, which has no consumers registered. Only
HEARTBEAT_TIMEOUT affects behaviour. See
Known issues.
The three compose files disagree on the broker — production runs RabbitMQ, staging runs Redis, development runs RabbitMQ — and nothing depends on the answer today.
Stripe¶
STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, six PRODUCT_PRICE_ID_* entries and five
STRIPE_EVENT_* entries.
Email¶
EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, DEFAULT_FROM_EMAIL,
USER_RESET_PASS_TOKEN_TIME.
Integrations and operations¶
| Variable | Purpose |
|---|---|
PUSH_NOTIFICATIONS_CREDENTIAL |
Path to the Firebase service-account JSON (backend/settings/firebase/__init__.py:9) |
AUDIO_TRANSCRIPTION_SERVICE |
Whisper endpoint used for CallTranscription |
FRONTEND_LINK |
Base URL used in emails and redirects |
GRAYLOG_ENDPOINT |
Log shipping target |
LOG_LEVEL, LOG_LEVEL_DJANGO, LOG_OUT, LOG_OUT_CONSOLE_TYPE |
Logging configuration |
CELERY_BROKER |
Loaded by entrypoint.sh:89 and read by nothing |
backend/.env.example has drifted
It carries a stale STRIPE_KEY that nothing reads, and it is missing
CELERY_BROKER, S3_USE_HTTPS, TWILIO_CONF_WAIT_URL, TWILIO_CALL_QUEUE_NAME,
TWILIO_CALL_QUEUE_SID, CHANNELS_RABBIT and the four LOG_* variables. Copying it
verbatim produces a backend that starts and then fails at runtime. Cross-check against
backend/settings/settings.py and backend/entrypoint.sh.
Frontend¶
Only these are actually read by frontend/src/:
| Variable | Purpose |
|---|---|
VITE_API_URL |
REST base URL, including /api/v1 |
PUBLIC_FIREBASE_API_KEY and the other PUBLIC_FIREBASE_* keys |
Firebase app configuration, read through $env/static/public (src/lib/actions/firebase/FirebaseApp.ts:9-27) |
VITE_DEV |
Development-only behaviour |
VITE_TWILIO_ERROR_RELOAD_DISABLED |
Stops the softphone from re-initialising five seconds after a device error (TwilioClientWeb.ts:105-113) |
frontend/.env.example is wrong in two ways
- It names the Firebase keys
VITE_FIREBASE_*; the code readsPUBLIC_FIREBASE_*. With the default SvelteKit prefix, the file as written does not work. - It lists
VITE_TWILIO_URLandVITE_WSAPI_URL, neither of which appears anywhere insrc/.
Treat the working set above as the real contract until the example file is fixed.
In CI the console's environment used to be injected from the FRONTEND_ENV and
STAGING_FRONTEND_ENV repository secrets. Those workflows were deleted, so the secrets are
currently unused — see Deployment.
Repository root .env¶
Contains only MANAGE_PY_PATH, an absolute path to backend/manage.py on one developer's
machine, used by the VS Code launch configuration. It is not application configuration, and
the path it holds is valid on exactly one machine.