Files
blackroad-operating-system/ENV_VARS.md
Claude 2a8f12d5cb chore: phase 1 infrastructure implementation
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)
2025-11-18 02:51:52 +00:00

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

  1. Core Application
  2. Database & Cache
  3. Authentication & Security
  4. API Integrations
  5. Infrastructure
  6. Deployment
  7. Observability
  8. Where to Set Variables
  9. Security Best Practices
  10. 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 $PORT automatically)
  • 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_URL to 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:

  1. Go to https://platform.openai.com/api-keys
  2. Create new secret key
  3. 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:

  1. Go to https://console.anthropic.com/settings/keys
  2. Create new API key
  3. 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:

  1. Go to https://github.com/settings/tokens
  2. Generate new token (classic or fine-grained)
  3. 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:

  1. Go to https://dashboard.stripe.com/apikeys
  2. Copy "Secret key" (starts with sk_test_ or sk_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:

  1. AWS Console → IAM → Users → Security Credentials
  2. Create access key
  3. 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:

  1. Cloudflare dashboard → My Profile → API Tokens
  2. Create token with "Zone.DNS" edit permissions
  3. 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:

  1. Cloudflare dashboard → Select domain
  2. 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:

  1. Railway dashboard → Service → Settings
  2. 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:

  1. Go to https://sentry.io
  2. Create new project
  3. 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: WARNING or INFO
  • Staging: INFO or DEBUG
  • Development: DEBUG

Example:

LOG_LEVEL=INFO

Where to Set Variables

Railway (Production & Staging)

  1. Go to Railway dashboard → Your project
  2. Select service (e.g., backend)
  3. Go to Variables tab
  4. Click New Variable
  5. Enter name and value
  6. 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:

  1. Variables tab → Shared Variables
  2. Add variable (e.g., SECRET_KEY)
  3. All services can access

GitHub Actions

  1. Go to repository → Settings → Secrets and variables → Actions
  2. Click New repository secret
  3. Enter name and value
  4. Click Add secret

Required GitHub Secrets:

  • RAILWAY_TOKEN - For Railway deployments
  • CF_API_TOKEN - For DNS automation
  • SENTRY_DSN - For error monitoring (optional)

How to use in workflows:

env:
  RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}

Local Development

  1. Copy environment template:

    cp backend/.env.example backend/.env
    
  2. Edit .env file with your local values:

    nano backend/.env  # or use your preferred editor
    
  3. The .env file is gitignored - safe to add real values

  4. FastAPI automatically loads .env via python-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)
  • .env files (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_KEY quarterly
  • 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=False in 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:

  1. Railway: Check service Variables tab - is variable set?
  2. Local: Is .env file in correct location (backend/.env)?
  3. Restart: Restart application after changing variables
  4. Syntax: Check for typos in variable names

Database Connection Fails

Problem: DatabaseConnectionError or similar

Solutions:

  1. Check DATABASE_URL format is correct
  2. Railway: Verify Postgres plugin is attached
  3. Local: Check Docker Compose is running (docker-compose ps)
  4. Check database credentials are correct

CORS Errors

Problem: Frontend can't call API (CORS error in browser console)

Solutions:

  1. Check ALLOWED_ORIGINS includes frontend domain
  2. Include protocol: https:// not just domain.com
  3. No trailing slash: https://domain.com not https://domain.com/
  4. 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. 🛣️