Environment Variables
Configure per-application environment variables using domain-based files.
Configuration
[env]
dir = "~/.gordon/env" # Default location
Options
| Option | Type | Default | Description |
|---|---|---|---|
dir |
string | ~/.gordon/env |
Directory containing .env files |
How It Works
Gordon loads environment variables from files named after the domain:
~/.gordon/env/
├── app_mydomain_com.env # For app.mydomain.com
├── api_mydomain_com.env # For api.mydomain.com
└── admin_mydomain_com.env # For admin.mydomain.com
Naming convention: Replace dots with underscores, add .env extension.
| Domain | File Name |
|---|---|
app.mydomain.com |
app_mydomain_com.env |
api.company.io |
api_company_io.env |
staging.app.dev |
staging_app_dev.env |
Backend Behavior
The auth.secrets_backend setting changes where route secrets live:
Pass Backend
- Env files are not used for route secrets.
- Use
gordon secrets setto store per-domain secrets in pass. - Existing
.envfiles are migrated on startup and renamed to.env.migrated.
SOPS or Unsafe Backend
- Env files remain the source of truth.
- Use
${sops:...}syntax for encrypted values whensecrets_backend = "sops".
File Format
Standard .env file format:
# app_mydomain_com.env
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://db:5432/myapp
API_KEY=sk-1234567890
DEBUG=false
Variable Merging
Variables are merged from multiple sources (lowest to highest priority):
- Dockerfile ENV - Base defaults from image
- .env file - Overrides Dockerfile values
# Dockerfile
ENV NODE_ENV=development
ENV PORT=3000
# app_mydomain_com.env
NODE_ENV=production # Overrides Dockerfile
# PORT not set, uses 3000 from Dockerfile
Result: NODE_ENV=production, PORT=3000
Secret Provider Syntax
Reference secrets from configured backends in env files:
Pass (Unix Password Manager)
DATABASE_PASSWORD=${pass:myapp/database/password}
API_SECRET=${pass:company/api-secret}
JWT_KEY=${pass:production/jwt-signing-key}
SOPS (Encrypted Files)
DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
API_SECRET=${sops:production.yaml:api.secret}
STRIPE_KEY=${sops:secrets.yaml:stripe.api_key}
Syntax Reference
| Provider | Syntax | Example |
|---|---|---|
| pass | ${pass:<path>} |
${pass:myapp/db-password} |
| sops | ${sops:<file>:<key.path>} |
${sops:secrets.yaml:db.password} |
Examples
Basic Application
# app_mydomain_com.env
NODE_ENV=production
PORT=3000
LOG_LEVEL=info
Database Connection
# ~/.gordon/env/api_mydomain_com.env
DATABASE_HOST=postgres
DATABASE_PORT=5432
DATABASE_NAME=myapi
DATABASE_USER=apiuser
DATABASE_PASSWORD=${pass:myapi/db-password}
DATABASE_URL=postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
Full Production Setup
# ~/.gordon/env/app_company_com.env
# Application settings
NODE_ENV=production
PORT=3000
LOG_LEVEL=warn
# Database
DATABASE_URL=postgresql://postgres:5432/production
DATABASE_PASSWORD=${pass:company/db-password}
# Redis
REDIS_URL=redis://redis:6379
# External APIs
STRIPE_SECRET_KEY=${pass:company/stripe-secret}
SENDGRID_API_KEY=${pass:company/sendgrid-key}
# Auth
JWT_SECRET=${pass:company/jwt-secret}
SESSION_SECRET=${pass:company/session-secret}
# Feature flags
ENABLE_ANALYTICS=true
MAINTENANCE_MODE=false
Development Environment
# ~/.gordon/env/app_local.env
NODE_ENV=development
PORT=3000
LOG_LEVEL=debug
DATABASE_URL=postgresql://postgres:5432/dev
DEBUG=*
File Permissions
Gordon creates env files with secure permissions:
- Directory:
0700(owner only) - Files:
0600(owner only)
Create files with proper permissions:
mkdir -p ~/.gordon/env
chmod 700 ~/.gordon/env
touch ~/.gordon/env/app_mydomain_com.env
chmod 600 ~/.gordon/env/app_mydomain_com.env
Auto-Creation
Gordon creates empty env files automatically when deploying a new route. You can then edit the file to add your variables.
Viewing Effective Environment
To see what environment a container receives:
docker inspect gordon-app-mydomain-com | jq '.[0].Config.Env'