Environment Variables
CHAD is configured via environment variables. This page documents all available options.
Required Variables
These must be set for production deployments:
Security Secrets
| Variable | Description | Example |
|---|
JWT_SECRET_KEY | JWT signing key (32+ chars) | openssl rand -base64 32 |
SESSION_SECRET_KEY | Session middleware key (32+ chars) | openssl rand -base64 32 |
CHAD_ENCRYPTION_KEY | Credential encryption key (32+ chars) | openssl rand -base64 32 |
Never use default or weak secrets in production. Generate unique cryptographically random values.
Database
| Variable | Description | Default |
|---|
POSTGRES_HOST | PostgreSQL hostname | postgres |
POSTGRES_PORT | PostgreSQL port | 5432 |
POSTGRES_USER | PostgreSQL username | chad |
POSTGRES_PASSWORD | PostgreSQL password | Required |
POSTGRES_DB | PostgreSQL database name | chad |
Application
| Variable | Description | Default |
|---|
APP_URL | Public URL for CHAD | Required for CSRF |
Optional Variables
Logging
| Variable | Description | Default |
|---|
LOG_LEVEL | Logging level | warning |
Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
Use WARNING or higher in production. DEBUG can expose sensitive data in logs.
Security
| Variable | Description | Default |
|---|
ALLOWED_HOSTS | Comma-separated allowed hostnames | * |
DEBUG | Enable debug mode | false |
CHAD_SSO_ONLY | Disable local login | false |
JWT Configuration
| Variable | Description | Default |
|---|
JWT_ALGORITHM | JWT signing algorithm | HS256 |
JWT_ACCESS_TOKEN_EXPIRE_HOURS | Token expiration | 8 |
Database Tuning
| Variable | Description | Default |
|---|
DATABASE_POOL_SIZE | Connection pool size | 5 |
DATABASE_MAX_OVERFLOW | Max overflow connections | 10 |
DATABASE_POOL_TIMEOUT | Pool timeout seconds | 30 |
Backend Server
| Variable | Description | Default |
|---|
BACKEND_HOST | Bind host | 0.0.0.0 |
BACKEND_PORT | Bind port | 8000 |
BACKEND_WORKERS | Uvicorn workers | 1 |
Frontend
| Variable | Description | Default |
|---|
VITE_API_URL | Backend API URL | /api |
Example Configurations
Development
# .env
POSTGRES_PASSWORD=devpassword
JWT_SECRET_KEY=dev-only-not-for-production-12345
SESSION_SECRET_KEY=dev-only-not-for-production-12345
CHAD_ENCRYPTION_KEY=dev-only-not-for-production-12345
APP_URL=http://localhost:3000
LOG_LEVEL=debug
DEBUG=true
Production
# .env
POSTGRES_HOST=postgres.internal
POSTGRES_PASSWORD=<secure-generated-password>
POSTGRES_DB=chad
JWT_SECRET_KEY=<32-char-random-string>
SESSION_SECRET_KEY=<32-char-random-string>
CHAD_ENCRYPTION_KEY=<32-char-random-string>
APP_URL=https://chad.example.com
ALLOWED_HOSTS=chad.example.com
LOG_LEVEL=warning
DEBUG=false
DATABASE_POOL_SIZE=10
DATABASE_MAX_OVERFLOW=20
High Availability
# .env
POSTGRES_HOST=postgres-primary.internal
POSTGRES_PASSWORD=<secure-password>
JWT_SECRET_KEY=<shared-across-instances>
SESSION_SECRET_KEY=<shared-across-instances>
CHAD_ENCRYPTION_KEY=<shared-across-instances>
APP_URL=https://chad.example.com
ALLOWED_HOSTS=chad.example.com
BACKEND_WORKERS=4
DATABASE_POOL_SIZE=20
DATABASE_MAX_OVERFLOW=40
Generating Secrets
Using OpenSSL
# Generate 32-byte base64 secret
openssl rand -base64 32
Using Python
import secrets
print(secrets.token_urlsafe(32))
Using /dev/urandom
head -c 32 /dev/urandom | base64
Secrets Management
Environment Files
For Docker Compose, use .env file:
# Never commit .env to version control!
echo ".env" >> .gitignore
Docker Secrets
For Docker Swarm:
# docker-compose.yml
secrets:
jwt_secret:
external: true
services:
backend:
secrets:
- jwt_secret
environment:
JWT_SECRET_KEY_FILE: /run/secrets/jwt_secret
Kubernetes Secrets
apiVersion: v1
kind: Secret
metadata:
name: chad-secrets
type: Opaque
stringData:
jwt-secret: "<your-secret>"
session-secret: "<your-secret>"
encryption-key: "<your-secret>"
Vault Integration
For HashiCorp Vault:
# Store secrets
vault kv put secret/chad \
jwt_secret="<value>" \
session_secret="<value>" \
encryption_key="<value>"
# Retrieve in app
export JWT_SECRET_KEY=$(vault kv get -field=jwt_secret secret/chad)
Validation
CHAD validates configuration on startup:
Required Check
Missing required variables cause startup failure:
ERROR: JWT_SECRET_KEY is required
Security Check
Insecure defaults in production cause failure:
ERROR: JWT_SECRET_KEY appears to be a default/weak value
Invalid formats are reported:
ERROR: LOG_LEVEL must be one of: DEBUG, INFO, WARNING, ERROR, CRITICAL
Troubleshooting
”Secret key is insecure”
- Generate a proper random secret
- Ensure no default values
- Check for whitespace/encoding issues
Database connection failed
- Verify
POSTGRES_HOST is reachable
- Check
POSTGRES_PASSWORD is correct
- Ensure database exists
CSRF validation failed
- Set
APP_URL to your public URL
- Include protocol:
https://chad.example.com
- Match the URL users access
Workers not starting
- Check
BACKEND_WORKERS is a valid number
- Ensure adequate system resources
- Review startup logs for errors
Next Steps