Version: 1.0 Date: 2025-11-18 Purpose: Complete reference for all environment variables across BlackRoad OS infrastructure
This document provides the complete list of environment variables used across the BlackRoad OS ecosystem. It covers:
- Required variables for core functionality
- Optional variables for integrations and features
- Where to set them (Railway, GitHub Actions, local development)
- How to generate secret values safely
- Security best practices
- Core Application
- Database & Cache
- Authentication & Security
- API Integrations
- Infrastructure
- Deployment
- Observability
- Where to Set Variables
- Security Best Practices
- Quick Start Templates
Required: Yes
Default: development
Valid values: development, staging, production
Description: Runtime environment identifier
Where to set:
- Railway (production):
production - Railway (staging):
staging - Local:
development
Example:
ENVIRONMENT=productionRequired: No
Default: False
Valid values: True, False
Description: Enable debug mode (verbose logging, stack traces)
False in production!
Where to set:
- Railway:
False - Local:
True(for development)
Example:
DEBUG=FalseRequired: Yes Description: Secret key for signing sessions, JWT tokens, and encryption
How to generate:
# Option 1: Using openssl
openssl rand -hex 32
# Option 2: Using Python
python -c "import secrets; print(secrets.token_hex(32))"- MUST be unique per environment (production ≠ staging ≠ local)
- MUST be at least 32 characters
- NEVER commit to git
- Rotate quarterly or after suspected compromise
Where to set:
- Railway (production): Generate unique value
- Railway (staging): Generate different unique value
- Local: Generate local value (in
.env, gitignored)
Example:
SECRET_KEY=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6Required: Yes Description: Public URL for the backend API (used by frontend for API calls)
Where to set:
- Railway (production):
https://os.blackroad.systems - Railway (staging):
https://staging.blackroad.systems - Local:
http://localhost:8000
Example:
API_BASE_URL=https://os.blackroad.systemsRequired: Yes Description: Public URL for the frontend (used for CORS, redirects, emails)
Where to set:
- Railway (production):
https://os.blackroad.systems - Railway (staging):
https://staging.blackroad.systems - Local:
http://localhost:8000
Example:
FRONTEND_URL=https://os.blackroad.systemsRequired: Yes Description: Comma-separated list of allowed CORS origins
Where to set:
- Railway (production):
https://os.blackroad.systems,https://blackroad.ai,https://blackroad.network - Railway (staging):
https://staging.blackroad.systems - Local:
http://localhost:8000,http://localhost:3000
Example:
ALLOWED_ORIGINS=https://os.blackroad.systems,https://blackroad.aiRequired: No (Railway auto-detects)
Default: 8000
Description: HTTP port for the backend server
Where to set:
- Railway: Not needed (Railway sets
$PORTautomatically) - Local:
8000(or any available port)
Example:
PORT=8000Required: Yes Description: PostgreSQL connection string (sync driver)
Format: postgresql://user:password@host:port/database
Where to set:
- Railway: Auto-injected via
${{Postgres.DATABASE_URL}} - Local:
postgresql://user:pass@localhost:5432/blackroad_dev
Example:
DATABASE_URL=postgresql://user:password@localhost:5432/blackroad_devHow to use Railway reference: In Railway dashboard → Service → Variables:
DATABASE_URL=${{Postgres.DATABASE_URL}}
Required: Yes (for async database operations) Description: PostgreSQL connection string (async driver)
Format: postgresql+asyncpg://user:password@host:port/database
Where to set:
-
Railway: Convert
DATABASE_URLto async:DATABASE_ASYNC_URL=${{Postgres.DATABASE_URL_ASYNC}}Or manually construct:
# If Railway doesn't provide async URL, derive from sync URL # Replace 'postgresql://' with 'postgresql+asyncpg://'
-
Local:
postgresql+asyncpg://user:pass@localhost:5432/blackroad_dev
Example:
DATABASE_ASYNC_URL=postgresql+asyncpg://user:password@localhost:5432/blackroad_devRequired: Yes Description: Redis connection string for caching and sessions
Format: redis://host:port/db or redis://user:password@host:port/db
Where to set:
- Railway: Auto-injected via
${{Redis.REDIS_URL}} - Local:
redis://localhost:6379/0
Example:
REDIS_URL=redis://localhost:6379/0How to use Railway reference: In Railway dashboard → Service → Variables:
REDIS_URL=${{Redis.REDIS_URL}}
Required: No
Default: 30
Description: JWT access token expiration time (in minutes)
Recommended values:
- Production:
15-30(shorter = more secure) - Development:
60-120(longer = less login friction)
Example:
ACCESS_TOKEN_EXPIRE_MINUTES=30Required: No
Default: 7
Description: JWT refresh token expiration time (in days)
Recommended values:
- Production:
7-14 - Development:
30
Example:
REFRESH_TOKEN_EXPIRE_DAYS=7Required: Yes (for blockchain features) Description: Master key for wallet/blockchain operations
How to generate:
openssl rand -hex 32- CRITICAL: Losing this key means losing access to blockchain wallets
- Backup securely (encrypted password manager, hardware security module)
- NEVER expose in logs or error messages
Example:
WALLET_MASTER_KEY=your-generated-master-key-hereRequired: For AI features (Lucidia, agents) Description: OpenAI API key for GPT models
How to get:
- Go to https://platform.openai.com/api-keys
- Create new secret key
- Copy key (starts with
sk-)
Example:
OPENAI_API_KEY=sk-proj-1234567890abcdef...Required: For Claude integration Description: Anthropic API key for Claude models
How to get:
- Go to https://console.anthropic.com/settings/keys
- Create new API key
- Copy key
Example:
ANTHROPIC_API_KEY=sk-ant-1234567890abcdef...Required: For GitHub integrations (agents, automation) Description: GitHub Personal Access Token (PAT)
How to get:
- Go to https://github.com/settings/tokens
- Generate new token (classic or fine-grained)
- Required scopes:
repo,workflow,read:org
Example:
GITHUB_TOKEN=ghp_1234567890abcdefghijklmnopqrstuvwxyzRequired: For payment features Description: Stripe API secret key
How to get:
- Go to https://dashboard.stripe.com/apikeys
- Copy "Secret key" (starts with
sk_test_orsk_live_)
# Development/Staging
STRIPE_SECRET_KEY=sk_test_...
# Production
STRIPE_SECRET_KEY=sk_live_...Required: For frontend payment UI Description: Stripe publishable key (safe to expose in frontend)
Example:
STRIPE_PUBLISHABLE_KEY=pk_test_1234567890abcdef...Required: For AWS S3 storage Description: AWS IAM access key ID
How to get:
- AWS Console → IAM → Users → Security Credentials
- Create access key
- Download/save credentials
Example:
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLERequired: For AWS S3 storage Description: AWS IAM secret access key
Example:
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYRequired: For AWS S3 storage Description: S3 bucket name for file uploads
Example:
AWS_S3_BUCKET=blackroad-uploads-productionRequired: For AWS S3 storage
Default: us-east-1
Description: AWS region for S3 bucket
Example:
AWS_REGION=us-east-1Required: For Cloudflare automation Description: Cloudflare API token for DNS/cache management
How to get:
- Cloudflare dashboard → My Profile → API Tokens
- Create token with "Zone.DNS" edit permissions
- Copy token
Where to set:
- GitHub Actions: As secret
CF_API_TOKEN - Local: Export when running DNS scripts
Example:
CF_API_TOKEN=your-cloudflare-api-tokenRequired: For Cloudflare automation Description: Cloudflare zone ID for a specific domain
How to get:
- Cloudflare dashboard → Select domain
- Overview page → Right sidebar → Zone ID
Where to set:
- GitHub Actions: As secret
CF_ZONE_ID - records.yaml: In domain configuration
Example:
CF_ZONE_ID=1234567890abcdef1234567890abcdefRequired: For Railway CLI/CI deployments Description: Railway API token for deployments
How to get:
railway login
railway tokens createWhere to set:
- GitHub Actions: As secret
RAILWAY_TOKEN - Local: Export when using Railway CLI
Example:
RAILWAY_TOKEN=your-railway-api-tokenRequired: For specific service deployments Description: Railway service ID to deploy to
How to get:
- Railway dashboard → Service → Settings
- Copy Service ID
Where to set:
- GitHub Actions: As repository variable
Example:
RAILWAY_SERVICE_ID=abc123def456Required: For error monitoring Description: Sentry Data Source Name for error tracking
How to get:
- Go to https://sentry.io
- Create new project
- Copy DSN from project settings
Example:
SENTRY_DSN=https://1234567890abcdef@o123456.ingest.sentry.io/1234567Required: No (if using SENTRY_DSN)
Default: Uses ENVIRONMENT value
Description: Sentry environment tag
Example:
SENTRY_ENVIRONMENT=productionRequired: No
Default: INFO
Valid values: DEBUG, INFO, WARNING, ERROR, CRITICAL
Description: Application logging level
Recommended:
- Production:
WARNINGorINFO - Staging:
INFOorDEBUG - Development:
DEBUG
Example:
LOG_LEVEL=INFO- Go to Railway dashboard → Your project
- Select service (e.g.,
backend) - Go to Variables tab
- Click New Variable
- Enter name and value
- Click Add
Railway Reference Variables:
Use ${{ServiceName.VARIABLE}} to reference values from other services:
DATABASE_URL=${{Postgres.DATABASE_URL}}
REDIS_URL=${{Redis.REDIS_URL}}
Shared Variables: For variables used across services, use Shared Variables:
- Variables tab → Shared Variables
- Add variable (e.g.,
SECRET_KEY) - All services can access
- Go to repository → Settings → Secrets and variables → Actions
- Click New repository secret
- Enter name and value
- Click Add secret
Required GitHub Secrets:
RAILWAY_TOKEN- For Railway deploymentsCF_API_TOKEN- For DNS automationSENTRY_DSN- For error monitoring (optional)
How to use in workflows:
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}-
Copy environment template:
cp backend/.env.example backend/.env
-
Edit
.envfile with your local values:nano backend/.env # or use your preferred editor -
The
.envfile is gitignored - safe to add real values -
FastAPI automatically loads
.envviapython-dotenv
.env files to git!
- Always use cryptographically secure random generators
- Minimum 32 characters for secrets
- Use different secrets per environment
Good:
openssl rand -hex 32
python -c "import secrets; print(secrets.token_hex(32))"Bad:
# Don't use predictable values
SECRET_KEY=password123
SECRET_KEY=my-app-secret- ✅ Railway environment variables (encrypted at rest)
- ✅ GitHub Actions secrets (encrypted)
- ✅
.envfiles (gitignored) - ✅ Password managers (1Password, LastPass, Bitwarden)
- ❌ NEVER commit secrets to git
- ❌ NEVER hardcode in source code
- ❌ NEVER expose in logs or error messages
- Rotate
SECRET_KEYquarterly - Rotate API keys after suspected compromise
- Update credentials after team member departure
- Keep backups of old secrets (for rollback)
- Give each service only the permissions it needs
- Use separate database users for different services
- Use read-only API keys where possible
- Limit token scopes (GitHub, Stripe, etc.)
Before deploying to production:
- All required variables are set
- No placeholder values (e.g.,
REPLACE_ME) - Secrets are unique per environment
-
DEBUG=Falsein production - CORS origins match production domains
- Database backups are configured
# Core
ENVIRONMENT=production
DEBUG=False
SECRET_KEY=[generate-unique-32-char-string]
API_BASE_URL=https://os.blackroad.systems
FRONTEND_URL=https://os.blackroad.systems
ALLOWED_ORIGINS=https://os.blackroad.systems,https://blackroad.ai
# Database (auto-injected by Railway)
DATABASE_URL=${{Postgres.DATABASE_URL}}
DATABASE_ASYNC_URL=${{Postgres.DATABASE_URL_ASYNC}}
REDIS_URL=${{Redis.REDIS_URL}}
# Auth
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_DAYS=7
WALLET_MASTER_KEY=[generate-unique-32-char-string]
# AI (add when ready)
# OPENAI_API_KEY=sk-proj-...
# ANTHROPIC_API_KEY=sk-ant-...
# Observability (add when ready)
# SENTRY_DSN=https://...
# LOG_LEVEL=WARNING# Core
ENVIRONMENT=development
DEBUG=True
SECRET_KEY=local-dev-secret-key-not-for-production
API_BASE_URL=http://localhost:8000
FRONTEND_URL=http://localhost:8000
ALLOWED_ORIGINS=http://localhost:8000,http://localhost:3000
# Database (Docker Compose)
DATABASE_URL=postgresql://blackroad:blackroad@localhost:5432/blackroad_dev
DATABASE_ASYNC_URL=postgresql+asyncpg://blackroad:blackroad@localhost:5432/blackroad_dev
REDIS_URL=redis://localhost:6379/0
# Auth
ACCESS_TOKEN_EXPIRE_MINUTES=120
REFRESH_TOKEN_EXPIRE_DAYS=30
WALLET_MASTER_KEY=local-dev-wallet-key
# AI (optional - use your own keys)
# OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-ant-...# Required
RAILWAY_TOKEN=[get-from-railway-cli]
CF_API_TOKEN=[get-from-cloudflare]
# Optional
SENTRY_DSN=[get-from-sentry]Use this script to validate your environment variables:
#!/bin/bash
# File: scripts/validate_env.sh
set -e
echo "Validating environment variables..."
# Check required variables
REQUIRED_VARS=(
"ENVIRONMENT"
"SECRET_KEY"
"DATABASE_URL"
"REDIS_URL"
"API_BASE_URL"
"FRONTEND_URL"
"ALLOWED_ORIGINS"
)
MISSING_VARS=()
for VAR in "${REQUIRED_VARS[@]}"; do
if [ -z "${!VAR}" ]; then
MISSING_VARS+=("$VAR")
fi
done
if [ ${#MISSING_VARS[@]} -gt 0 ]; then
echo "❌ Missing required environment variables:"
printf ' - %s\n' "${MISSING_VARS[@]}"
exit 1
fi
# Check SECRET_KEY length
if [ ${#SECRET_KEY} -lt 32 ]; then
echo "❌ SECRET_KEY must be at least 32 characters"
exit 1
fi
# Check DEBUG in production
if [ "$ENVIRONMENT" = "production" ] && [ "$DEBUG" = "True" ]; then
echo "⚠️ WARNING: DEBUG=True in production environment!"
exit 1
fi
echo "✅ Environment variables validated successfully!"Run before deploy:
chmod +x scripts/validate_env.sh
source backend/.env && ./scripts/validate_env.shProblem: Application doesn't see environment variable
Solutions:
- Railway: Check service Variables tab - is variable set?
- Local: Is
.envfile in correct location (backend/.env)? - Restart: Restart application after changing variables
- Syntax: Check for typos in variable names
Problem: DatabaseConnectionError or similar
Solutions:
- Check
DATABASE_URLformat is correct - Railway: Verify Postgres plugin is attached
- Local: Check Docker Compose is running (
docker-compose ps) - Check database credentials are correct
Problem: Frontend can't call API (CORS error in browser console)
Solutions:
- Check
ALLOWED_ORIGINSincludes frontend domain - Include protocol:
https://not justdomain.com - No trailing slash:
https://domain.comnothttps://domain.com/ - Railway: Wait 1-2 minutes for variable updates to apply
This document is the single source of truth for environment variables. Keep it updated as new variables are added.
Where AI meets the open road. 🛣️