Environment Variables Management Guide¶
๐ฏ TL;DR - How It Works¶
You only need ONE .env file for local development.
Railway automatically provides environment variables based on which environment is deployed. You don't need separate .env files for prod/dev on Railway.
๐ File Structure¶
archety/
โโโ .env # โ
For LOCAL development only
โโโ .env.example # โ
Template (committed to git)
โโโ .gitignore # โ
Blocks .env from being committed
โโโ app/
โโโ config.py # โ
Loads from Railway OR .env
Important:
- .env = Only for local development (NEVER commit!)
- .env.example = Template for other developers (safe to commit)
- Railway = Provides variables automatically based on environment
๐ How Environment Variables Work¶
1. Local Development (Your Machine)¶
Uses: .env file
What happens:
- app/config.py reads .env file
- You get local development variables
- ENVIRONMENT=development (from your .env)
- DATABASE_URL=postgresql://localhost... (local database)
2. Railway Development Environment¶
Uses: Railway dashboard variables
What happens:
- GitHub Actions deploys to Railway dev environment
- Railway injects variables from development environment
- app/config.py reads from environment (NOT .env)
- ENVIRONMENT=development (from Railway)
- DATABASE_URL=
3. Railway Production Environment¶
Uses: Railway dashboard variables
What happens:
- GitHub Actions deploys to Railway production environment
- Railway injects variables from production environment
- ENVIRONMENT=production (from Railway)
- DATABASE_URL=
๐ง Configuration Code (How It Works)¶
app/config.py automatically handles this:
class Settings(BaseSettings):
model_config = ConfigDict(
# Only load .env in development, Railway provides env vars directly
env_file=".env" if os.path.exists(".env") else None,
env_file_encoding="utf-8",
case_sensitive=False,
extra="ignore",
)
Priority order:
1. Railway environment variables (if on Railway)
2. .env file (if running locally and file exists)
3. Defaults in config.py
๐ Example .env (Local Development)¶
This is an example .env for local development. Do not paste real keys into documentation or commit them to git.
Use .env.example as the canonical template.
# Local development settings
ENVIRONMENT=development
LOG_LEVEL=INFO
BASE_URL=http://localhost:8000
# Database (local)
DATABASE_URL=<your_postgres_connection_string>
# API Keys (shared across environments usually)
SUPERMEMORY_API_KEY=<supermemory_api_key> # Primary memory service (optional if using mem0)
MEM0_API_KEY=<mem0_api_key> # Legacy fallback (optional if using supermemory)
OPENAI_API_KEY=<openai_api_key>
PERPLEXITY_API_KEY=<perplexity_api_key>
# OAuth (for local testing)
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
OAUTH_REDIRECT_URI=http://localhost:8000/auth/callback
# Security (local development keys)
SECRET_KEY=<generate_with_openssl_rand_hex_32>
FERNET_KEY=<generate_with_fernet>
EDGE_SECRET=<generate_with_openssl_rand_hex_32>
๐ซ What NOT to Do¶
โ Don't create .env.prod or .env.dev¶
Why not? - Railway handles prod/dev separation automatically - Risk of accidentally committing production secrets - Unnecessary complexity - Railway injects the correct variables based on environment
โ Don't commit .env to git¶
Already protected by .gitignore:
โ What TO Do¶
1. Keep ONE .env for Local Development¶
Your current .env file is perfect for local dev:
ENVIRONMENT=development
LOG_LEVEL=INFO
BASE_URL=http://localhost:8000
DATABASE_URL=<your_postgres_connection_string>
# ... other local variables
2. Use Railway Dashboard for Prod/Dev Variables¶
Set variables via Railway CLI or dashboard:
# Production environment
railway link --environment production --service <your-prod-service>
railway variables set ENVIRONMENT=production
railway variables set BASE_URL=https://api.ikiro.ai
# Development environment
railway link --environment development --service <your-dev-service>
railway variables set ENVIRONMENT=development
railway variables set BASE_URL=<dev_base_url>
3. Use .env.example for Team Sharing¶
Already exists - keep it updated:
# .env.example (committed to git, no secrets)
ENVIRONMENT=development
LOG_LEVEL=INFO
BASE_URL=http://localhost:8000
# Memory Service Configuration
SUPERMEMORY_API_KEY=your_supermemory_api_key # Primary (get from supermemory.ai)
MEM0_API_KEY=your_mem0_api_key # Legacy fallback (optional)
# LLM Providers
OPENAI_API_KEY=your_openai_api_key
PERPLEXITY_API_KEY=your_perplexity_api_key
# OAuth
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
OAUTH_REDIRECT_URI=http://localhost:8000/auth/callback
# Security (generate your own!)
SECRET_KEY=generate_with_openssl_rand_hex_32
FERNET_KEY=generate_with_fernet
EDGE_SECRET=generate_with_openssl_rand_hex_32
๐ Typical Workflow¶
Local Development¶
# 1. Copy .env.example to .env (first time only)
cp .env.example .env
# 2. Fill in your API keys in .env
# Edit .env with your actual keys
# 3. Run locally
./run.sh
# The app reads from .env automatically
Deploy to Development¶
# 1. Make changes on dev branch
git checkout dev
# ... make changes ...
# 2. Commit and push
git add .
git commit -m "feat: new feature"
git push origin dev
# 3. GitHub Actions auto-deploys to Railway dev
# Railway injects development environment variables
# No .env file needed - Railway provides everything!
Deploy to Production¶
# 1. Merge dev to master
git checkout master
git merge dev
git push origin master
# 2. Manually trigger production deploy
# Go to: GitHub Actions โ Deploy to Production
# Type "DEPLOY TO PRODUCTION" to confirm
# 3. GitHub Actions deploys to Railway prod
# Railway injects production environment variables
# No .env file needed!
๐งช Testing Different Environments Locally¶
Scenario: You want to test against dev or prod database locally
Option 1: Temporarily change .env
# In .env, temporarily change:
DATABASE_URL=<copy from Railway dev or prod>
BASE_URL=<dev_base_url>
# Run locally
./run.sh
# REMEMBER to change back when done!
Option 2: Use environment variables directly
# Override specific variables for one run
ENVIRONMENT=development \
BASE_URL=<dev_base_url> \
DATABASE_URL=<railway dev database> \
python -m uvicorn app.main:app --reload
Option 3: Use Railway run (connects to Railway environment)
# Run locally but with Railway dev variables
railway link --environment development --service <your-dev-service>
railway run python -m uvicorn app.main:app --reload
# Or prod
railway link --environment production --service <your-prod-service>
railway run python -m uvicorn app.main:app --reload
๐ Security Best Practices¶
Local .env File¶
โ Do: - Keep .env for local development - Use weak/test keys in local .env (not production keys!) - Never commit .env - Share .env.example (without secrets)
โ Don't: - Put production secrets in local .env - Commit .env to git - Share .env file directly (use .env.example)
Railway Variables¶
โ Do: - Use Railway dashboard or CLI to set variables - Use different SECRET_KEY/FERNET_KEY/EDGE_SECRET per environment - Review variables before deploying
โ Don't: - Hardcode secrets in code - Share production secrets in Slack/email - Use same security keys across environments
๐ Variable Comparison¶
| Variable | Local (.env) | Railway Dev | Railway Prod |
|---|---|---|---|
| ENVIRONMENT | development | development | production |
| BASE_URL | http://localhost:8000 | https://api.ikiro.ai | |
| DATABASE_URL | localhost postgres | Railway dev postgres | Railway prod postgres |
| SECRET_KEY | Local test key | Unique dev key | Unique prod key |
| API Keys | Your personal keys | Shared/separate | Production keys |
๐ Troubleshooting¶
"Config loading wrong values"¶
Check which config is loading:
# Add to app/main.py temporarily
from app.config import settings
logger.info(f"ENVIRONMENT: {settings.environment}")
logger.info(f"BASE_URL: {settings.base_url}")
logger.info(f"Loading from .env: {os.path.exists('.env')}")
"Railway using .env file"¶
Railway should NOT use .env: - Railway doesn't have access to your .env file - Railway injects variables directly - If it's using .env, you might be running locally
"Variables not updating"¶
After changing Railway variables: 1. Trigger a new deploy (Railway doesn't auto-reload) 2. Check Railway logs to see what values are loaded 3. Verify you're in the correct environment
โ Summary¶
How to manage environment variables:
- Local development: Use
.envfile โ - Railway dev: Set variables in Railway dashboard (development environment) โ
- Railway prod: Set variables in Railway dashboard (production environment) โ
- Team sharing: Use
.env.example(committed to git) โ
You do NOT need:
- โ .env.prod file
- โ .env.dev file
- โ Multiple .env files
Railway handles everything automatically based on which environment is deployed!
๐ฏ Quick Reference Commands¶
# View local config
cat .env
# View Railway dev config
railway link --environment development --service <your-dev-service>
railway variables
# View Railway prod config
railway link --environment production --service <your-prod-service>
railway variables
# Set Railway dev variable
railway link --environment development --service <your-dev-service>
railway variables set KEY=value
# Set Railway prod variable
railway link --environment production --service <your-prod-service>
railway variables set KEY=value
# Run locally with .env
./run.sh
# Run locally with Railway dev variables
railway link --environment development --service <your-dev-service>
railway run ./run.sh
๐ง Email Configuration (Resend)¶
Overview¶
Archety uses Resend for transactional emails (welcome, billing notifications, account alerts). The email service is optional - if not configured, emails are logged but not sent.
Environment Variables¶
| Variable | Description | Example |
|---|---|---|
EMAIL_API_KEY |
Resend API key (required for sending) | re_XXXXX... |
EMAIL_PROVIDER |
Email provider name | resend |
EMAIL_FROM_ADDRESS |
Sender address with display name | Sage <sage@archety.ai> |
EMAIL_REPLY_TO |
Reply-to address | support@archety.ai |
EMAIL_ENABLED |
Master toggle | true or false |
Setup¶
1. Get API Key: - Sign up at https://resend.com - Create an API key in the dashboard - Verify your sending domain (sage@archety.ai)
2. Configure Environment Variable:
# Local development (.env)
EMAIL_API_KEY=re_test_...
EMAIL_ENABLED=true
# Railway Development
railway variables set EMAIL_API_KEY=re_live_...
railway variables set EMAIL_PROVIDER=resend
railway variables set EMAIL_FROM_ADDRESS="Sage <sage@archety.ai>"
railway variables set EMAIL_ENABLED=true
# Railway Production (same keys or separate)
railway variables set EMAIL_API_KEY=re_live_...
Fallback Behavior¶
The system works WITHOUT email configured:
- If EMAIL_API_KEY is not set โ emails are logged only
- If EMAIL_ENABLED=false โ emails are disabled
- Email failures never block the main operation
Testing¶
# Test email locally
python -c "
from app.email.service import get_email_service
svc = get_email_service()
print(f'Available: {svc.is_available()}')
"
Documentation¶
For detailed email system guide, see: docs/implementation/EMAIL_NOTIFICATION_SYSTEM.md
๐ฉ LaunchDarkly Feature Flags¶
Overview¶
LaunchDarkly provides runtime configuration and feature flags without requiring deployments. The integration is optional - if not configured, the system uses default values.
Setup¶
1. Get SDK Key: - Log into LaunchDarkly dashboard - Navigate to: Account Settings โ Projects โ archety - Copy SDK key for your environment
2. Configure Environment Variable:
# Local development (.env)
LAUNCHDARKLY_SDK_KEY=sdk-your-local-key
# Railway Development
railway variables set LAUNCHDARKLY_SDK_KEY=sdk-dev-key
# Railway Production
railway variables set LAUNCHDARKLY_SDK_KEY=sdk-prod-key
3. Verify:
# Check feature flags status
curl http://localhost:8000/admin/feature-flags/status
# Expected response:
{
"initialized": true,
"is_connected": true,
"circuit_breaker_open": false
}
Fallback Behavior (Important!)¶
The system works WITHOUT LaunchDarkly:
- If LAUNCHDARKLY_SDK_KEY is not set โ uses default values
- If LaunchDarkly is unavailable โ automatic fallback to defaults
- Circuit breaker protects against failures (falls back after 3 errors)
This ensures the application always runs, even if LaunchDarkly is down.
Common Use Cases¶
- Token Limit Control:
- Adjust LLM token limits without deployment
-
Emergency cost reduction via
llm.force_basic_mode -
Feature Rollouts:
- Gradual rollout of new features (0% โ 10% โ 50% โ 100%)
-
Instant rollback if issues detected
-
Cache Configuration:
- Tune cache TTLs based on load
- Enable/disable caching dynamically
Monitoring¶
# Check if LaunchDarkly is connected
curl http://localhost:8000/admin/feature-flags/status
# List all available flags
curl http://localhost:8000/admin/feature-flags/list
Documentation¶
For detailed operations guide, see: docs/operations/feature_flags.md