-
-
Notifications
You must be signed in to change notification settings - Fork 2
CASCADING OVERRIDES
Understand how nself's environment variable system works and how to manage configuration across development, staging, and production.
nself uses a cascading override system where configuration files layer on top of each other. Each file overrides the previous one, allowing for:
- Shared defaults (committed to git)
- Local customization (on your machine only)
- Environment-specific overrides (staging vs production)
- Secrets management (never in git)
Configuration is loaded in this exact order. Later files override earlier files:
.env.dev (1. Base - Committed to git)
↓
.env.local (2. Local - On your machine only)
↓
.env.staging (3. Staging - On staging server only)
↓
.env.prod (4. Production - On prod server only)
↓
.env.secrets (5. Secrets - Ultra-sensitive, server only)
↓
.env.computed (6. Computed - Auto-generated, never edit)
Purpose: Base configuration used by all developers.
Properties:
- Committed to git
- Shared by entire team
- Contains safe default values
- No secrets or sensitive data
Example:
PROJECT_NAME=my-app
ENV=dev
BASE_DOMAIN=localhost
POSTGRES_DB=myapp_dev
HASURA_GRAPHQL_ENABLE_CONSOLE=truePurpose: Your personal machine customizations.
Properties:
- Gitignored (never committed)
- Only on your machine
- Overrides .env.dev
- Can contain personal secrets
Example:
# You want to use a different Postgres password
POSTGRES_PASSWORD=my-super-secret-local-password
# You want to enable Redis locally
REDIS_ENABLED=trueResult: Your machine uses your password, all other values from .env.dev.
Purpose: Configuration specific to the staging environment.
Properties:
- On staging server only (not on developer machines)
- Overrides .env.dev and .env.local
- Staging-specific values (staging database, staging API keys)
Example:
# Staging database with more data
POSTGRES_PASSWORD=staging-db-password
# Staging Hasura admin secret
HASURA_GRAPHQL_ADMIN_SECRET=staging-secret-123
# Enable monitoring on staging
MONITORING_ENABLED=trueAccess: Senior developers via SSH to staging server.
Purpose: Production-specific configuration.
Properties:
- On production server only
- Overrides everything above
- Production URLs, API keys, feature flags
Example:
# Production database
POSTGRES_PASSWORD=prod-database-password
# Production domain
BASE_DOMAIN=myapp.com
# Production Hasura secret
HASURA_GRAPHQL_ADMIN_SECRET=prod-secret-xyzAccess: Lead developers only via SSH to production.
Purpose: Ultra-sensitive credentials, generated on server.
Properties:
- Generated on server at setup time
- Never in git (ever)
- Only on production server
- Encrypted if stored at rest
Example:
# Master encryption key
ENCRYPTION_KEY=long-random-string-from-server
# Database root password
POSTGRES_ROOT_PASSWORD=ultra-secret-generated-key
# JWT signing key
JWT_SECRET=another-generated-secretAccess: Lead developers only, synced via secure SSH.
Purpose: Computed values generated during nself build.
Properties:
- Auto-generated by nself (never edit)
- Contains derived values
- Based on other environment variables
Example:
# Generated from POSTGRES credentials
DATABASE_URL=postgresql://postgres:password@postgres:5432/myapp_db
# Generated from PROJECT_NAME
DOCKER_NETWORK=my-app_network
# Generated service hosts
POSTGRES_HOST=postgres
HASURA_HOST=hasuraWhen nself starts, it loads variables in order:
#!/bin/bash
# Load .env.dev first (shared defaults)
if [ -f .env.dev ]; then
source .env.dev
fi
# Load .env.local second (your overrides)
if [ -f .env.local ]; then
source .env.local
fi
# Load environment-specific (staging, prod, etc)
if [ -f .env.${ENV} ]; then
source .env.${ENV}
fi
# Load production secrets last (if they exist)
if [ -f .env.secrets ]; then
source .env.secrets
fi
# Auto-generate computed values
source .env.computedStarting configuration:
File: .env.dev (committed to git)
PROJECT_NAME=my-app
ENV=dev
BASE_DOMAIN=localhost
POSTGRES_DB=myapp_db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=change-me
HASURA_GRAPHQL_ADMIN_SECRET=change-me
REDIS_ENABLED=false
MONITORING_ENABLED=falseFile: .env.local (on developer's machine, gitignored)
# Developer wants local Redis for caching
REDIS_ENABLED=true
# Developer uses different password
POSTGRES_PASSWORD=my-local-password-456
HASURA_GRAPHQL_ADMIN_SECRET=my-local-secret-789When you run nself start on your local machine:
| Variable | Source | Value |
|---|---|---|
PROJECT_NAME |
.env.dev | my-app |
ENV |
.env.dev | dev |
BASE_DOMAIN |
.env.dev | localhost |
POSTGRES_DB |
.env.dev | myapp_db |
POSTGRES_USER |
.env.dev | postgres |
POSTGRES_PASSWORD |
.env.local (override) | my-local-password-456 |
HASURA_GRAPHQL_ADMIN_SECRET |
.env.local (override) | my-local-secret-789 |
REDIS_ENABLED |
.env.local (override) | true |
MONITORING_ENABLED |
.env.dev | false |
The staging server doesn't have .env.local. It loads:
File: .env.dev (from git)
PROJECT_NAME=my-app
POSTGRES_PASSWORD=change-me
# ...File: .env.staging (only on staging server)
POSTGRES_PASSWORD=staging-db-password-xyz
BASE_DOMAIN=staging.myapp.com
MONITORING_ENABLED=trueResult on staging:
| Variable | Source | Value |
|---|---|---|
POSTGRES_PASSWORD |
.env.staging | staging-db-password-xyz |
BASE_DOMAIN |
.env.staging | staging.myapp.com |
MONITORING_ENABLED |
.env.staging | true |
| Other vars | .env.dev | (defaults) |
nself supports role-based environment access:
Access: .env.dev + .env.local only
Can develop locally but cannot see staging/production secrets.
nself env switch local # Works (they have .env.local)
nself sync pull staging # Fails (no SSH access to staging)Access: .env.dev, .env.local, + .env.staging
Can test on staging server without accessing production.
nself env switch local # Works
nself sync pull staging # Works (SSH access to staging)
nself sync pull prod # Fails (no SSH access to prod)Access: All files including .env.secrets
Full access to production for emergencies and critical tasks.
nself env switch local # Works
nself sync pull staging # Works
nself sync pull prod # Works (SSH access to prod)
nself sync pull secrets # Works (access to .env.secrets)Senior developers can pull staging configuration to their local machine:
# Pull .env.staging from staging server via SSH
nself sync pull staging
# This creates .env.staging locally (gitignored)
# Now you can test staging config locallyLead developers only:
# Pull .env.prod from production server
nself sync pull prod
# Pull .env.secrets (master credentials)
nself sync pull secretsUpdate configuration on remote:
# Sync your .env changes to staging
nself sync push staging
# Sync to production (Lead Dev only)
nself sync push prodYour .gitignore should include:
# Local overrides
.env.local
# Environment-specific (don't commit staging/prod)
.env.staging
.env.prod
# Secrets (NEVER commit)
.env.secrets
# Computed values (auto-generated)
.env.computedOnly .env.dev should be committed to git.
# Good - only base config in git
git add .env.dev
git commit -m "feat: update base configuration"
# BAD - never do this
git add .env.secrets # ❌ NEVER!
git add .env.prod # ❌ NEVER!# Edit .env.dev for shared changes
vim .env.dev
git add .env.dev
git commit -m "update base config"
git push
# Edit .env.local for personal changes
vim .env.local # Not committed
# No git commands needed# Pull staging config
nself sync pull staging
# Switch to staging config for testing
nself env switch staging
# Run tests
nself build
nself start
# Switch back to local
nself env switch local# Lead dev only
nself sync pull prod
# Make emergency change
vim .env.prod
# Apply immediately
nself build
nself restart
# Push change to remote
nself sync push prodAs a developer:
# Add to .env.dev (shared)
echo "NEW_VAR=value" >> .env.dev
git add .env.dev
git commit -m "add NEW_VAR to configuration"
git push
# Tell Sr Dev and Lead Dev they need to add to their environment filesAs Sr Dev:
# Add staging value
echo "NEW_VAR=staging-value" >> .env.staging
nself sync push stagingAs Lead Dev:
# Add production value
echo "NEW_VAR=prod-value" >> .env.prod
nself sync push prodProblem: You set a value in .env.local but it's not being used.
Solution: Check the cascade order. Later files override earlier ones.
# Check which file has the value
grep "POSTGRES_PASSWORD" .env.dev
grep "POSTGRES_PASSWORD" .env.local
# The .env.local value should be usedProblem: Changed .env.staging on staging server but not seeing changes locally.
Solution: Pull the latest config:
nself sync pull stagingProblem: .env.secrets doesn't exist on production server.
Solution: Generate it:
# On production server
nself config generate-secrets
# This creates .env.secrets with generated valuesProblem: Local dev uses port 8080, but staging also tries to use 8080.
Solution: Use different ports in each environment:
# .env.dev
NGINX_PORT=8080
# .env.staging
NGINX_PORT=8081
# .env.prod
NGINX_PORT=443 # HTTPS only- Keep .env.dev minimal - Only shared defaults
- Never commit .env.local - Add to .gitignore
- Never commit secrets - Use .env.secrets on servers
-
Use meaningful defaults -
change-mefor passwords - Document required variables - List in README
- Rotate secrets regularly - Especially in production
-
Audit changes - Use
nself audit logs config
- Build Configuration - How build uses env files
- Secrets Management - Secure secret handling
- Deployment Guide - Deploying across environments
Key Takeaway: The cascading environment system lets you have one source of truth (git) while allowing safe local development and secure production secrets. Understand the order and you'll never have configuration issues.
ɳSelf CLI v1.0.9. MIT licensed. Docs CC BY 4.0.
GitHub · Issues · Discussions · nself.org · nself.org/docs
Getting Started
Commands
- Commands, Overview
- Lifecycle: cmd-init · cmd-build · cmd-start · cmd-stop · cmd-restart · cmd-dev
- Monitoring: cmd-status · cmd-logs · cmd-health · cmd-urls · cmd-doctor · cmd-monitor · cmd-alerts · cmd-sentry · cmd-watchdog
- Data: cmd-db · cmd-backup · cmd-dr · cmd-queue · cmd-webhooks
- Config: cmd-config · cmd-service · cmd-env · cmd-promote
- Networking: cmd-ssl · cmd-trust · cmd-dns-setup
- Security: cmd-access · cmd-security · cmd-secrets
- Tenancy: cmd-tenant · cmd-billing
- Plugins: cmd-plugin · cmd-license · cmd-dogfood (extracted, CLI-R11) · cmd-k8s (extracted, CLI-R11) · cmd-encryption (extracted, CLI-R11) · cmd-waf (extracted, CLI-R11) · cmd-federation (extracted, CLI-R11) · cmd-mail (extracted, CLI-R11) · cmd-dlq (extracted, CLI-R11)
- AI: cmd-ai · cmd-claw · cmd-model
- Templates: cmd-template
- Utilities: cmd-exec · cmd-clean · cmd-reset · cmd-update · cmd-upgrade · cmd-version · cmd-admin · cmd-migrate · cmd-migrate-firebase · cmd-migrate-supabase · cmd-completion
Features
- Features, Overview
- Feature-Auth
- Feature-Storage
- Feature-Search
- Feature-Functions
- Feature-Email
- Feature-Monitoring
- Feature-Plugins
- Feature-nClaw, AI Assistant
- Feature-nChat, Messaging
- Feature-nTV, Media Player
- Feature-nFamily, Family Social
- Feature-nCloud, Managed Hosting
- Feature-Memory-Rooms, Knowledge Organization
- Feature-Agent-Dashboard, Agent Metrics
- Feature-Image-Generation, AI Image Generation
Configuration
- Configuration, Overview
- Config-Env-Vars
- Config-Postgres
- Config-Hasura
- Config-Auth
- Config-Nginx
- Config-Optional-Services
- Config-Custom-Services
- Config-System
Plugins (87 + 10 monitoring)
Free (25)
- plugin-backup
- plugin-content-acquisition
- plugin-content-progress
- plugin-cron
- plugin-donorbox
- plugin-feature-flags
- plugin-github
- plugin-github-runner
- plugin-invitations
- plugin-jobs
- plugin-link-preview
- plugin-mdns
- plugin-mlflow
- plugin-monitoring
- plugin-notifications
- plugin-notify
- plugin-paypal
- plugin-search
- plugin-shopify
- plugin-stripe
- plugin-subtitle-manager
- plugin-tokens
- plugin-torrent-manager
- plugin-vpn
- plugin-webhooks
Pro (62)
- plugin-access-controls
- plugin-activity-feed
- plugin-admin-api
- plugin-nself-ai-gateway
- plugin-nself-ai-mcp
- plugin-nself-ai-mcp
- plugin-analytics
- plugin-auth
- plugin-backup-pro
- plugin-bots
- plugin-browser
- plugin-calendar
- plugin-cdn
- plugin-chat
- plugin-claw
- plugin-claw-budget
- plugin-claw-news
- plugin-claw-web
- plugin-cloudflare
- plugin-cms
- plugin-compliance
- plugin-cron-pro
- plugin-ddns
- plugin-devices
- plugin-documents
- plugin-donorbox-pro
- plugin-entitlements
- plugin-epg
- plugin-file-processing
- plugin-game-metadata
- plugin-geocoding
- plugin-geolocation
- plugin-google
- plugin-home
- plugin-idme
- plugin-knowledge-base
- plugin-linkedin
- plugin-livekit
- plugin-media-processing
- plugin-meetings
- plugin-moderation
- plugin-mux
- plugin-notify-pro
- plugin-object-storage
- plugin-observability
- plugin-paypal-pro
- plugin-photos
- plugin-podcast
- plugin-post
- plugin-realtime
- plugin-recording
- plugin-retro-gaming
- plugin-rom-discovery
- plugin-shopify-pro
- plugin-social
- plugin-sports
- plugin-stream-gateway
- plugin-streaming
- plugin-stripe-pro
- plugin-support
- plugin-tmdb
- plugin-voice
- plugin-web3
- plugin-workflows
Planned (26)
plugin-auditplugin-blogplugin-checkoutplugin-commerceplugin-drmplugin-exportplugin-flowplugin-importplugin-ldapplugin-mailgunplugin-mediaplugin-oauth-providersplugin-pagesplugin-postmarkplugin-rate-limitplugin-reportsplugin-samlplugin-schedulerplugin-sendgridplugin-ssoplugin-subscriptionplugin-thumbplugin-transcoderplugin-twilioplugin-wafplugin-watermark
Guides
- Guide-Production-Deployment
- Guide-SSL-Setup
- Guide-Multi-Tenancy
- Guide-Security-Hardening
- Guide-Monitoring-Setup
- Guide-Backup-Restore
- Guide-Custom-Services
- Guide-Migration-from-v1
Architecture
Reference
- API-Reference
- error-codes, Error Codes
Licensing
Security
Brand
Operations
- operations/release-cascade, Release Cascade
- operations/self-healing, Self-Healing Schema
- operations/redis-tuning, Redis Pool Tuning
- operations/meilisearch-warmup, MeiliSearch Warm-Up
- operations/jwt-rotation, JWT Key Rotation
- operations/windows-wsl2-setup, Windows / WSL2 Setup
- operations/gemini-oauth-reauth, Gemini OAuth Reauth
Contributing
Admin
- USER-ACTION-QUEUE, Pending Admin Actions
All commands (52)
- A: cmd-access · cmd-account · cmd-admin
- B: cmd-backup · cmd-build · cmd-bundle
- C: cmd-ci · cmd-clean · cmd-completion · cmd-config
- D: cmd-db · cmd-deploy · cmd-dev · cmd-doctor
- E: cmd-env · cmd-exec
- F: cmd-functions
- G: cmd-generate
- H: cmd-health · cmd-help-topics
- I: cmd-init · cmd-install
- L: cmd-license · cmd-login · cmd-logout · cmd-logs
- M: cmd-man · cmd-mcp · cmd-migrate
- O: cmd-oauth · cmd-ops
- P: cmd-plugin · cmd-promote
- R: cmd-remove · cmd-reset · cmd-restart · cmd-runner
- S: cmd-secrets · cmd-security · cmd-self-heal · cmd-server · cmd-service · cmd-start · cmd-status · cmd-stop
- T: cmd-telemetry · cmd-template · cmd-trust
- U: cmd-update · cmd-urls
- V: cmd-verify-sbom · cmd-version