Environment Variable Management Guide
Environment Variable Management Guide
This guide explains how to manage environment variables across all Seed & Source templates.
Overview
Environment variables are used to configure applications without hardcoding values. This is essential for:
- Separating configuration from code
- Supporting multiple environments (dev, staging, production)
- Protecting sensitive data (API keys, secrets)
- Enabling feature flags
Validation Scripts
Each template includes a validation script to check environment variables:
Python SaaS
python bin/validate_env.py # Validate with warningspython bin/validate_env.py --strict # Exit with error if missingpython bin/validate_env.py --help # Show detailed helpRails API
ruby bin/validate_env.rb # Validate with warningsruby bin/validate_env.rb --strict # Exit with error if missingruby bin/validate_env.rb --help # Show detailed helpReact Client
node bin/validate_env.js # Validate with warningsnode bin/validate_env.js --strict # Exit with error if missingnode bin/validate_env.js --help # Show detailed helpStatic Landing (Astro)
node bin/validate_env.js # Validate with warningsnode bin/validate_env.js --strict # Exit with error if missingnode bin/validate_env.js --help # Show detailed helpEnvironment Files
File Priority (highest to lowest)
.env.local- Local overrides (gitignored, highest priority).env.production- Production-specific values.env.development- Development-specific values.env- Default values.env.example- Template/documentation (committed to git)
Best Practices
- ✅ DO: Commit
.env.examplefiles - ✅ DO: Use
.env.localfor local development - ❌ DON’T: Commit
.env,.env.local, or.env.production - ❌ DON’T: Store secrets in git
Template-Specific Requirements
Python SaaS
Required Variables:
APP_ENV- Application environment (development, production)DATABASE_URL- Database connection stringSECRET_KEY- Secret key for cryptographic operations
Recommended Variables:
OPENAI_API_KEY- For AI featuresREDIS_URL- For cachingSENTRY_DSN- For error tracking
Example:
# Generate SECRET_KEYopenssl rand -hex 32
# Set environment variablesexport SECRET_KEY=your_generated_secretexport DATABASE_URL=postgresql://user:pass@localhost/dbRails API
Required Variables:
SECRET_KEY_BASE- Rails secret key baseDATABASE_URL- PostgreSQL connection stringREDIS_URL- Redis connection stringALLOWED_ORIGINS- CORS allowed origins
Recommended Variables:
JWT_SECRET- For JWT authenticationLICENSE_SERVER_URL- License server integrationSENTRY_DSN- Error tracking
Example:
# Generate SECRET_KEY_BASEbundle exec rails secret
# Generate JWT_SECRETopenssl rand -hex 32
# Set environment variablesexport SECRET_KEY_BASE=your_generated_secretexport DATABASE_URL=postgresql://user:pass@localhost/dbexport ALLOWED_ORIGINS=https://app.example.comReact Client (Vite)
Important: Only variables prefixed with VITE_ are exposed to the client!
Required Variables:
VITE_BACKEND_URL- Backend API base URLVITE_API_ROOT- API root path (e.g., /api/v1)
Recommended Variables:
VITE_SENTRY_DSN- Error trackingVITE_LICENSE_SERVER_URL- License server URL
Example:
VITE_BACKEND_URL=https://api.example.comVITE_API_ROOT=/api/v1VITE_SENTRY_DSN=https://...@sentry.io/...Access in Code:
const apiUrl = import.meta.env.VITE_BACKEND_URL;Static Landing (Astro)
Important: Only variables prefixed with PUBLIC_ are exposed to the client!
Required Variables:
PUBLIC_SITE_URL- Base URL of the websitePUBLIC_SITE_NAME- Name of the websitePUBLIC_CONTACT_EMAIL- Contact email address
Optional Variables:
PUBLIC_ANALYTICS_ID- Analytics tracking IDPUBLIC_ENABLE_ANALYTICS- Enable analyticsPUBLIC_API_URL- API endpoint if needed
Example:
PUBLIC_SITE_URL=https://seedsource.devPUBLIC_SITE_NAME=Seed & SourcePUBLIC_CONTACT_EMAIL=hello@seedsource.devPUBLIC_ENABLE_ANALYTICS=truePUBLIC_ANALYTICS_ID=G-XXXXXXXXXXAccess in Code:
const siteUrl = import.meta.env.PUBLIC_SITE_URL;Docker Compose Integration
Environment variables can be set in docker-compose.yml:
services: api: env_file: - .env - .env.local # Override with local settings environment: - DATABASE_URL=${DATABASE_URL} - SECRET_KEY_BASE=${SECRET_KEY_BASE}Production Deployment
Pre-Deployment Checklist
- All required variables set
- Secrets generated (not placeholders like “changeme”)
- URLs use HTTPS in production
- CORS origins updated for production
- Validation script passes (
--strictmode) - Secrets stored in secure vault (Doppler, AWS Secrets Manager, etc.)
Platform-Specific Instructions
Render
# Set via Render dashboard or CLIrender config:set SECRET_KEY_BASE=xxxFly.io
# Set secrets via flyctlflyctl secrets set SECRET_KEY_BASE=xxxHeroku
# Set config varsheroku config:set SECRET_KEY_BASE=xxxDocker Swarm
# Use Docker secretsecho "secret_value" | docker secret create secret_key_base -Secrets Management
Doppler (Recommended)
# Install Doppler CLIbrew install dopplerhq/cli/doppler # macOScurl -Ls https://cli.doppler.com/install.sh | sh # Linux
# Login and setupdoppler logindoppler setup
# Run with Dopplerdoppler run -- npm startdoppler run -- docker-compose upAWS Secrets Manager
# Store secretaws secretsmanager create-secret \ --name /myapp/secret_key_base \ --secret-string "xxx"
# Retrieve in application codeHashiCorp Vault
# Store secretvault kv put secret/myapp secret_key_base=xxx
# Retrieve in application codeTroubleshooting
”Environment variable not set”
- Check
.envfile exists - Verify variable name is correct (case-sensitive)
- Restart container:
docker-compose restart - Check docker-compose.yml has
env_fileorenvironmentsection
”CORS error” in browser
- Check
ALLOWED_ORIGINS/CORS_ALLOWED_ORIGINS - Include protocol (http/https) and port
- No trailing slashes in URLs
- Restart backend after changes
Variables not available in Vite/Astro
- Ensure variable has correct prefix (
VITE_orPUBLIC_) - Restart dev server after changes
- Variables are embedded at BUILD time, not runtime
- Check build output for warnings
”Cannot connect to database”
- Check
DATABASE_URLformat - Verify database is running:
docker-compose ps postgres - Test connection:
psql $DATABASE_URL - Check credentials are correct
Testing
Run validation tests:
# Python SaaSpytest tests/test_env_validation.py
# Rails APIrspec spec/bin/validate_env_spec.rb
# React Clientnpm test -- validate_env.test.js
# Static Landingnpm test -- validate_env.spec.jsSecurity Best Practices
-
Never commit secrets to git
- Add
.env*to.gitignore(except.env.example) - Use git-secrets or similar tools to prevent accidental commits
- Add
-
Rotate secrets regularly
- Change secrets every 90 days
- Rotate immediately if exposed
-
Use strong secrets
- Minimum 32 characters
- Use cryptographically secure random generation
- Don’t use dictionary words or patterns
-
Limit access
- Use least-privilege principle
- Different secrets per environment
- Audit access logs
-
Use secrets management
- Doppler, AWS Secrets Manager, or HashiCorp Vault
- Never store secrets in CI/CD logs
- Encrypt secrets at rest