Implement Phase 1 infrastructure from master orchestration plan. This commit delivers production-ready deployment infrastructure, comprehensive documentation, and workflow automation. **Cloudflare DNS Infrastructure:** - Add records.yaml with complete DNS config for all domains - Add migrate_to_cloudflare.md with step-by-step migration guide - Add cloudflare_dns_sync.py for automated DNS synchronization - Update CLOUDFLARE_DNS_BLUEPRINT.md with implementation references **Environment Variable Documentation:** - Add ENV_VARS.md with comprehensive variable reference - Document all services: Railway, GitHub Actions, Cloudflare, local - Include security best practices and validation scripts - Add troubleshooting guides and quick-start templates **GitHub Actions Workflows:** - Add railway-deploy-template.yml for Railway deployments - Add frontend-deploy-template.yml for static site deployments - Add codeql-analysis-template.yml for security scanning - Add comprehensive-ci-template.yml for complete CI pipeline - Add .github/dependabot.yml for automated dependency updates **Frontend Infrastructure:** - Add infra/frontend/LANDING_PAGE_PLAN.md with detailed implementation plan - Include page structure, design system, content guidelines - Document deployment options (GitHub Pages, Railway, Cloudflare Pages) **Master Orchestration Updates:** - Update MASTER_ORCHESTRATION_PLAN.md with implementation file references - Add Phase 1 implementation checklist - Document immediate, short-term, and medium-term next steps **Impact:** This implementation enables: - Automated DNS management across 10+ domains - Secure, documented deployment workflows - Consistent environment configuration - Automated security scanning and dependency updates - Clear path to production for landing page **Next Steps for Operator:** 1. Migrate DNS to Cloudflare using migrate_to_cloudflare.md 2. Configure GitHub and Railway secrets 3. Deploy backend with custom domains 4. Implement landing page using LANDING_PAGE_PLAN.md Refs: #55 (Master Orchestration Prompt)
18 KiB
Environment Variables Documentation
Version: 1.0 Date: 2025-11-18 Purpose: Complete reference for all environment variables across BlackRoad OS infrastructure
Overview
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
Table of Contents
- Core Application
- Database & Cache
- Authentication & Security
- API Integrations
- Infrastructure
- Deployment
- Observability
- Where to Set Variables
- Security Best Practices
- Quick Start Templates
Core Application
ENVIRONMENT
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=production
DEBUG
Required: No
Default: False
Valid values: True, False
Description: Enable debug mode (verbose logging, stack traces)
⚠️ Security Warning: MUST be False in production!
Where to set:
- Railway:
False - Local:
True(for development)
Example:
DEBUG=False
SECRET_KEY
Required: 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))"
⚠️ Security:
- 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=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
API_BASE_URL
Required: 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.systems
FRONTEND_URL
Required: 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.systems
ALLOWED_ORIGINS
Required: 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.ai
PORT
Required: 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=8000
Database & Cache
DATABASE_URL
Required: 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_dev
How to use Railway reference: In Railway dashboard → Service → Variables:
DATABASE_URL=${{Postgres.DATABASE_URL}}
DATABASE_ASYNC_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_dev
REDIS_URL
Required: 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/0
How to use Railway reference: In Railway dashboard → Service → Variables:
REDIS_URL=${{Redis.REDIS_URL}}
Authentication & Security
ACCESS_TOKEN_EXPIRE_MINUTES
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=30
REFRESH_TOKEN_EXPIRE_DAYS
Required: No
Default: 7
Description: JWT refresh token expiration time (in days)
Recommended values:
- Production:
7-14 - Development:
30
Example:
REFRESH_TOKEN_EXPIRE_DAYS=7
WALLET_MASTER_KEY
Required: Yes (for blockchain features) Description: Master key for wallet/blockchain operations
How to generate:
openssl rand -hex 32
⚠️ Security:
- 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-here
API Integrations
OPENAI_API_KEY
Required: 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...
ANTHROPIC_API_KEY
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...
GITHUB_TOKEN
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_1234567890abcdefghijklmnopqrstuvwxyz
STRIPE_SECRET_KEY
Required: 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_)
⚠️ Use test key for development:
# Development/Staging
STRIPE_SECRET_KEY=sk_test_...
# Production
STRIPE_SECRET_KEY=sk_live_...
STRIPE_PUBLISHABLE_KEY
Required: For frontend payment UI Description: Stripe publishable key (safe to expose in frontend)
Example:
STRIPE_PUBLISHABLE_KEY=pk_test_1234567890abcdef...
AWS_ACCESS_KEY_ID
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=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY
Required: For AWS S3 storage Description: AWS IAM secret access key
Example:
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_S3_BUCKET
Required: For AWS S3 storage Description: S3 bucket name for file uploads
Example:
AWS_S3_BUCKET=blackroad-uploads-production
AWS_REGION
Required: For AWS S3 storage
Default: us-east-1
Description: AWS region for S3 bucket
Example:
AWS_REGION=us-east-1
Infrastructure
CF_API_TOKEN
Required: 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-token
CF_ZONE_ID
Required: 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=1234567890abcdef1234567890abcdef
RAILWAY_TOKEN
Required: For Railway CLI/CI deployments Description: Railway API token for deployments
How to get:
railway login
railway tokens create
Where to set:
- GitHub Actions: As secret
RAILWAY_TOKEN - Local: Export when using Railway CLI
Example:
RAILWAY_TOKEN=your-railway-api-token
RAILWAY_SERVICE_ID
Required: 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=abc123def456
Deployment
SENTRY_DSN
Required: 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/1234567
SENTRY_ENVIRONMENT
Required: No (if using SENTRY_DSN)
Default: Uses ENVIRONMENT value
Description: Sentry environment tag
Example:
SENTRY_ENVIRONMENT=production
Observability
LOG_LEVEL
Required: 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
Where to Set Variables
Railway (Production & Staging)
- 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
GitHub Actions
- 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 }}
Local Development
-
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
⚠️ Never commit .env files to git!
Security Best Practices
1. Secret Generation
- 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
2. Secret Storage
- ✅ 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
3. Secret Rotation
- Rotate
SECRET_KEYquarterly - Rotate API keys after suspected compromise
- Update credentials after team member departure
- Keep backups of old secrets (for rollback)
4. Principle of Least Privilege
- 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.)
5. Verification
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
Quick Start Templates
Production Railway (backend service)
# 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
Local Development (.env)
# 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-...
GitHub Actions Secrets
# Required
RAILWAY_TOKEN=[get-from-railway-cli]
CF_API_TOKEN=[get-from-cloudflare]
# Optional
SENTRY_DSN=[get-from-sentry]
Validation Script
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.sh
Troubleshooting
Variable Not Loading
Problem: 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
Database Connection Fails
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
CORS Errors
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. 🛣️