This guide explains how environment variables work in the ShadowRealms AI Docker setup and how to configure them properly.
.envfile contains your local configuration- Used when running Flask directly (not in Docker)
- Contains sensitive information (API keys, secret keys)
- Environment variables are passed from host to containers
- Uses
${VARIABLE_NAME:-default_value}syntax - Falls back to default values if not set
- Reads environment variables using
os.environ.get() - Has fallback values for development
- Logs configuration for debugging
# Generate secure keys
python scripts/generate_secret_key.py
# Copy the hex key (most secure)
# Example: 7e99881cf6559187c323f08a1f3332cceccc7ceb2f641bab97b6f4fa73773e4e# Copy template
cp env.template .env
# Edit .env with your keys
nano .env
# Update these lines:
FLASK_SECRET_KEY=your-generated-secret-key-from-generate-script
JWT_SECRET_KEY=your-jwt-secret-key-here# Test local environment
python3 tests/test_flask_config.py
# Test Docker configuration
python3 tests/test_docker_env.pyOption A — root helper script (recommended)
From the repository root, docker-up.sh changes to that directory and runs docker compose up -d so every service starts in detached mode:
chmod +x docker-up.sh # only needed once if the file is not executable
./docker-up.shExtra Compose CLI arguments are forwarded (for example rebuild images before starting):
./docker-up.sh --buildOption B — Compose CLI
Equivalent manual commands:
# Build and start containers (foreground; add -d for detached)
docker compose up --build
# Check logs for environment variable loading
docker compose logs backendRequires Docker with the Compose V2 plugin (docker compose).
If you are using PostgreSQL (DATABASE_TYPE=postgresql), the database tables must exist before login/registration/campaign features will work.
At minimum (for login + create campaign + OOC room), PostgreSQL must have:
userscampaignscampaign_playerslocations
For the broader app/admin UI to function without “relation does not exist” errors, you should also have:
characterscharacter_locationsmessagesuser_moderation_logai_interactionsai_memorydice_rollsdice_roll_templatesnpcsnpc_messageslocation_deletion_log
docker compose exec postgresql psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c '\dt'If you see no relations, PostgreSQL started without initializing the schema.
docker-compose.yml mounts an init SQL file into Postgres:
./backend/init_postgresql_schema.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro
If backend/init_postgresql_schema.sql is missing or not a valid SQL file, Postgres will come up empty.
- Ensure
backend/init_postgresql_schema.sqlis present as a file - Recreate the Postgres volume so init scripts run:
docker compose down
docker volume rm shadowrealms-ai_postgresql_data
docker compose up -d postgresql
docker compose exec postgresql psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c '\dt'┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ .env file │ │ docker-compose │ │ Flask Container │
│ (local) │───►│ .yml │───►│ (config.py) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
.envfile:FLASK_SECRET_KEY=abc123...- docker-compose.yml:
FLASK_SECRET_KEY=${FLASK_SECRET_KEY:-default} - Container: Gets
abc123...from host environment - Flask app: Reads
FLASK_SECRET_KEYfrom container environment
FLASK_SECRET_KEY=your-secure-key-here
JWT_SECRET_KEY=your-jwt-key-hereFLASK_HOST=0.0.0.0
FLASK_PORT=5000
FLASK_DEBUG=false
DATABASE=/app/data/shadowrealms.db
CHROMADB_HOST=chromadb
REDIS_HOST=redisGPU_THRESHOLD_HIGH=80
GPU_THRESHOLD_MEDIUM=60
LOG_LEVEL=INFOpython3 tests/test_flask_config.pypython3 tests/test_docker_env.py# Check environment variables in container
docker-compose exec backend env | grep FLASK
# Test Flask config in container
docker-compose exec backend python -c "from config import Config; Config.debug_env_vars()"
# Check container health
curl http://localhost:5000/health- Generate unique secret keys for each environment
- Use different keys for development vs production
- Keep
.envfile in.gitignore - Rotate keys periodically in production
- Use default secret keys in production
- Commit
.envfiles to version control - Share secret keys between team members
- Use the same keys for different projects
# Check if .env file exists
ls -la .env
# Verify docker-compose.yml has environment section
grep -A 20 "environment:" docker-compose.yml
# Check container logs
docker-compose logs backend
# Test environment variables in container
docker-compose exec backend env | grep FLASK# Generate new keys
python scripts/generate_secret_key.py
# Update .env file
nano .env
# Restart containers
docker-compose down
docker-compose up --build# Test local config
python3 tests/test_flask_config.py
# Test Docker config
python3 tests/test_docker_env.py
# Check Python path in container
docker-compose exec backend python -c "import sys; print(sys.path)"# Development
cp env.template .env.development
# Production
cp env.template .env.production
# Use specific file
docker-compose --env-file .env.production up# docker-compose.override.yml (development)
services:
backend:
environment:
- FLASK_DEBUG=true
- LOG_LEVEL=DEBUG
# docker-compose.prod.yml (production)
services:
backend:
environment:
- FLASK_DEBUG=false
- LOG_LEVEL=WARNING- Generate secure keys using
scripts/generate_secret_key.py - Update .env file with your keys
- Test configuration using test scripts
- Start Docker containers with
docker-compose up --build - Verify environment variables are loaded correctly
Your Docker environment is now properly configured for secure Flask development! 🚀