🔐 Environment Variables Setup Guide¶
📁 Where to Set Environment Variables¶
Root .env (for Docker Compose)¶
Location: .env (project root, same directory as docker-compose.yml)
Used by: - Docker Compose (reads from root directory) - Can be accessed by backend if needed
Required Variables:
# ============================================
# SECURITY - REQUIRED (No Defaults)
# ============================================
# API Key for backend authentication
API_KEY=your_new_secure_api_key_here
# Database Configuration
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_strong_password_here
POSTGRES_DB=pcbstackup
# ============================================
# APPLICATION CONFIGURATION
# ============================================
# Environment
ENVIRONMENT=development
# Server Port (FastAPI backend — read by backend/main.py, defaults to 8000)
PORT=8000
# ============================================
# DATABASE & CACHE
# ============================================
# Database URL (auto-constructed from POSTGRES_* vars in docker-compose)
# Or set manually if not using docker-compose:
# DATABASE_URL=postgresql://postgres:password@localhost:5432/pcbstackup
REDIS_URL=redis://localhost:6379/0
# ============================================
# SUPABASE AUTHENTICATION
# ============================================
SUPABASE_URL=https://orjmlibnlzkyuauaysye.supabase.co
SUPABASE_JWT_SECRET=your_jwt_secret_here
SUPABASE_SERVICE_KEY=your_service_key_here
SUPABASE_WEBHOOK_SECRET=your_webhook_secret_here
# Frontend Supabase (public keys - safe to expose)
VITE_SUPABASE_URL=https://orjmlibnlzkyuauaysye.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key_here
# ============================================
# EXTERNAL APIs
# ============================================
# Nexar API
NEXAR_CLIENT_ID=your_nexar_client_id
NEXAR_CLIENT_SECRET=your_nexar_client_secret
# DigiKey API
DIGIKEY_CLIENT_ID=your_digikey_client_id
DIGIKEY_CLIENT_SECRET=your_digikey_client_secret
ENABLE_DIGIKEY_API=true
# Gemini/Google AI
GEMINI_API_KEY=your_gemini_api_key
GOOGLE_API_KEY=your_google_api_key
# ============================================
# EMAIL SERVICE
# ============================================
# SendGrid
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD=your_sendgrid_api_key
EMAIL_SERVICE=sendgrid
# Or MailerSend
# EMAIL_SERVICE=mailersend
# SMTP_HOST=smtp.mailersend.com
# SMTP_PORT=587
# SMTP_USER=your_mailersend_user
# SMTP_PASSWORD=your_mailersend_password
# ============================================
# CORS & SECURITY
# ============================================
# CORS Origins (comma-separated)
CORS_ORIGINS=http://localhost:5180,http://localhost:3000
# Trusted Hosts
TRUSTED_HOSTS=localhost,127.0.0.1,pcbgenerator.com,www.pcbgenerator.com
# HTTPS (set to true in production)
FORCE_HTTPS=false
# ============================================
# LOGGING
# ============================================
LOG_LEVEL=DEBUG
# ============================================
# FRONTEND CONFIGURATION
# ============================================
# API URLs
VITE_API_URL=http://localhost:8000
VITE_FASTAPI_URL=http://localhost:8000
VITE_API_KEY=your_api_key_here
# ============================================
# OLLAMA (Local AI)
# ============================================
OLLAMA_URL=http://localhost:11434
DEFAULT_MODEL=mistral:latest
backend/.env (for local backend development)¶
Location: backend/.env
Used by:
- Backend Python code when running locally (not in Docker)
- backend/main.py loads the root .env first, then backend/.env as a legacy fallback (lines 34-35; first call wins — root .env values are not overridden)
When to use:
- Running backend locally with python backend/main.py
- Not using Docker Compose
- Need backend-specific overrides
Template:
# ============================================
# Backend Local Development Overrides
# ============================================
#
# These override root .env when running backend locally
# Most variables should be in root .env for consistency
# Only add backend-specific overrides here
# Example: Override database connection for local testing
# DATABASE_URL=postgresql://postgres:password@localhost:5432/pcbstackup
# Example: Override API key for local development
# API_KEY=local_dev_key_123
Note: If you're using Docker Compose, you don't need backend/.env - root .env is sufficient.
Frontend (VITE_*) variables — root .env only¶
Location: root .env (NOT frontend/.env)
Vite loads VITE_* variables from the repo-root .env — this is configured via envDir: rootDir in frontend/vite.config.ts. A frontend/.env file is ignored at runtime and is deleted by start-all-servers-windowed.ps1 on every run, so never put variables there.
Required Variables (in root .env):
# ============================================
# Frontend Environment Variables
# ============================================
# Note: Vite requires VITE_ prefix for client-side variables
# Supabase (public keys - safe to expose)
VITE_SUPABASE_URL=https://orjmlibnlzkyuauaysye.supabase.co
VITE_SUPABASE_ANON_KEY=your_anon_key_here
# API Configuration
VITE_API_URL=http://localhost:8000
VITE_FASTAPI_URL=http://localhost:8000
VITE_API_KEY=your_api_key_here
After editing the root .env, fully restart Vite — HMR does not re-read env variables.
🔄 Variable Priority (How They're Loaded)¶
When Using Docker Compose:¶
- Root
.env→ Read by Docker Compose - Docker Compose passes variables to containers via
environment:section - Backend container receives variables as environment variables
backend/main.pycan also loadbackend/.envas fallback
When Running Backend Locally (No Docker):¶
- System environment variables (already-set vars are never overridden by
.envfiles) - Root
.env→ Loaded first bybackend/main.py(lines 34-35) backend/.env→ Loaded second as a legacy fallback (first call wins, so it cannot override root.env)
✅ Quick Setup Checklist¶
For Docker Compose Setup:¶
- Create/update root
.envwith all required variables - Set
API_KEY(generate new secure key) - Set
POSTGRES_PASSWORD(strong password) - Set
POSTGRES_USER(default:postgres) - Set
POSTGRES_DB(default:pcbstackup) - Set Supabase keys (
VITE_SUPABASE_ANON_KEY, etc.) - Set external API keys (Nexar, DigiKey, etc.)
- Verify
.envis in.gitignore✅ (already done)
For Local Development (No Docker):¶
- Put all variables (backend +
VITE_*) in the root.env— the backend loads it (main.py lines 34-35) and Vite reads it viaenvDir - Do NOT create
frontend/.env— Vite ignores it and the start script deletes it - Optionally use
backend/.envonly for legacy backend-specific overrides (root.envvalues win)
🔒 Security Best Practices¶
- Never commit
.envfiles ✅ (already in.gitignore) - Use different keys for dev/prod:
- Development: Use test keys or local values
- Production: Use real, secure keys
- Rotate exposed secrets:
- After security fixes, generate new API keys
- Change database passwords
- Use strong passwords:
- Database passwords: 20+ characters, mixed case, numbers, symbols
- API keys: Use secure random generators
📝 Example: Setting Up After Security Fix¶
After removing hardcoded secrets from docker-compose.yml, add to root .env:
# Generate new secure API key (use: openssl rand -base64 32)
API_KEY=NEW_SECURE_KEY_HERE_GENERATE_ONE
# Strong database password
POSTGRES_USER=postgres
POSTGRES_PASSWORD=StrongPassword123!@#ChangeThis
POSTGRES_DB=pcbstackup
Then test:
# Verify docker-compose can read them
docker-compose config
# Should show your values (not errors about missing vars)
🆘 Troubleshooting¶
Issue: "API_KEY not set" error¶
Solution: Add API_KEY=... to root .env
Issue: Database connection fails¶
Solution:
1. Check POSTGRES_PASSWORD is set in root .env
2. Verify password matches what's in database
3. Check DATABASE_URL is correct
Issue: Frontend can't connect to backend¶
Solution:
1. Check VITE_API_URL in the root .env (Vite does not read frontend/.env)
2. Verify backend is running on that URL
3. Check CORS settings
Issue: Variables not loading¶
Solution:
1. Verify .env file is in correct location
2. Check file has no syntax errors (no spaces around =)
3. Restart services after changing .env
4. For Docker: Rebuild containers if needed
📚 Reference: Which File for What¶
| Variable | Root .env |
backend/.env |
Notes |
|---|---|---|---|
API_KEY |
✅ | ✅ | Docker uses root, local uses backend |
POSTGRES_* |
✅ | ✅ | Docker uses root |
DATABASE_URL |
✅ | ✅ | Auto-built in docker-compose |
SUPABASE_* |
✅ | ✅ | Frontend needs VITE_ prefix |
VITE_* |
✅ | ❌ | Frontend variables — root .env only (Vite envDir); frontend/.env is ignored |
NEXAR_* |
✅ | ✅ | Backend only |
DIGIKEY_* |
✅ | ✅ | Backend only |
GEMINI_API_KEY |
✅ | ✅ | Backend only |
SMTP_* |
✅ | ✅ | Backend only |
💡 Recommendation¶
For simplicity, use root .env for everything:
- Docker Compose reads it automatically
- Backend loads it explicitly (backend/main.py lines 34-35)
- Frontend (Vite) reads it automatically (envDir: rootDir in frontend/vite.config.ts)
- Single source of truth
- Easier to manage
Only use backend/.env if:
- You need different values for local vs Docker
- You're running services separately (not with docker-compose)
- You need environment-specific overrides (note: root .env values load first and win)
Never use frontend/.env — Vite ignores it at runtime and start-all-servers-windowed.ps1 deletes it on every run.