nself provides a comprehensive environment management system for managing development, staging, and production configurations. This guide explains how environments work, how to configure them, and best practices for managing configuration across your deployment pipeline.
my-project/
├── .environments/ # Environment configurations
│ ├── dev/
│ │ ├── .env # Development settings
│ │ └── .env.secrets # Development secrets (optional)
│ ├── staging/
│ │ ├── .env # Staging settings
│ │ ├── .env.secrets # Staging secrets (git-ignored)
│ │ └── server.json # SSH connection details
│ └── prod/
│ ├── .env # Production settings
│ ├── .env.secrets # Production secrets (git-ignored)
│ └── server.json # SSH connection details
├── .env # Active merged config (git-ignored)
├── .env.example # Template with all options
├── .current-env # Tracks active environment
└── docker-compose.yml # Generated (do not edit)| File | Purpose | Git Tracked |
|---|---|---|
.env | Non-sensitive configuration | Yes |
.env.secrets | Passwords, API keys, tokens | No (chmod 600) |
server.json | SSH deployment settings | Yes (no secrets) |
.env.example | Template for new developers | Yes |
# List all environments
nself env list
# Output:
# * dev (active)
# staging
# prod
# Switch to a different environment
nself env switch staging
# Check current environment status
nself env status
# Output:
# Current Environment: staging
# Base Domain: staging.example.com
# Services: 12 enabled
# Last Modified: 2026-01-24 10:30:15
# Create a new environment
nself env create qa staging # Create 'qa' from staging template
# Delete an environment
nself env delete qa# View environment details
nself env info staging
# Compare environments
nself env diff staging prod
# Output:
# Differences: staging vs prod
# ────────────────────────────────────
# ENV: staging -> prod
# DEBUG: true -> false
# NSELF_ADMIN_ENABLED: true -> false
# MONITORING_ENABLED: false -> true
# + SSL_MODE: letsencrypt (prod only)
# - MAILPIT_ENABLED: true (staging only)
# Compare with values (secrets masked)
nself env diff staging prod --values
# Validate environment configuration
nself env validate staging# .environments/dev/.env
ENV=dev
DEBUG=true
BASE_DOMAIN=local.nself.org
LOG_LEVEL=debug
# Database
POSTGRES_DB=myapp_dev
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
# Services - enable development tools
NSELF_ADMIN_ENABLED=true # Admin UI
MAILPIT_ENABLED=true # Email testing
SWAGGER_ENABLED=true # API documentation
HOT_RELOAD_ENABLED=true # Frontend hot reload
# Security relaxed for development
HASURA_GRAPHQL_ENABLE_CONSOLE=true
HASURA_GRAPHQL_DEV_MODE=true
# Monitoring disabled for faster startup
MONITORING_ENABLED=false# Start development environment
nself env switch dev
nself build
nself start
# Access services at:
# - https://api.local.nself.org (Hasura GraphQL)
# - https://auth.local.nself.org (Authentication)
# - https://admin.local.nself.org (Admin UI)
# - https://mail.local.nself.org (MailPit)
# - https://storage.local.nself.org (MinIO)
# View all URLs
nself urlsadmin.local.nself.orgmail.local.nself.orgnself db mock# .environments/staging/.env
ENV=staging
DEBUG=false
BASE_DOMAIN=staging.example.com
LOG_LEVEL=info
# Database
POSTGRES_DB=myapp_staging
# Services - production-like with some debug tools
NSELF_ADMIN_ENABLED=false # Disabled by default
MAILPIT_ENABLED=false # Use real email
MONITORING_ENABLED=true # Enable monitoring
GRAFANA_ENABLED=true
# Security - stricter than dev
HASURA_GRAPHQL_ENABLE_CONSOLE=true # Still allow console for debugging
HASURA_GRAPHQL_DEV_MODE=false
# SSL
SSL_ENABLED=true
SSL_PROVIDER=letsencrypt
LETSENCRYPT_STAGING=true # Use staging certificates# .environments/staging/.env.secrets
# Generated with: nself staging secrets generate
# File permissions: chmod 600
POSTGRES_PASSWORD=gKj8mN2pL9xQ4rW7vY1cF6bH3tZ0
HASURA_GRAPHQL_ADMIN_SECRET=aB5dE8fG1hJ4kM7nP0qS3tV6wX9yZ2
JWT_SECRET=cD6eF9gH2iJ5kL8mN1oP4qR7sT0uV3wX
MINIO_ROOT_PASSWORD=yZ2aB5cD8eF1gH4iJ7kL0mN3oP6qR9
REDIS_PASSWORD=sT6uV9wX2yZ5aB8cD1eF4gH7iJ0kL3// .environments/staging/server.json
{
"name": "staging",
"type": "staging",
"host": "staging.example.com",
"port": 22,
"user": "deploy",
"key": "~/.ssh/staging_deploy_key",
"deploy_path": "/opt/myapp"
}# Generate secrets for staging
nself staging secrets generate
# Check SSH access
nself deploy check-access
# Preview deployment
nself staging deploy --dry-run
# Deploy to staging (full stack including frontends)
nself staging deploy
# Verify deployment
nself deploy health staging# .environments/prod/.env
ENV=prod
DEBUG=false
BASE_DOMAIN=example.com
LOG_LEVEL=warning
# Database
POSTGRES_DB=myapp_production
# Services - production hardened
NSELF_ADMIN_ENABLED=false # DISABLED for security
MAILPIT_ENABLED=false # Never in production
MONITORING_ENABLED=true # Full monitoring
GRAFANA_ENABLED=true
# Security - maximum
HASURA_GRAPHQL_ENABLE_CONSOLE=false # Disabled
HASURA_GRAPHQL_DEV_MODE=false
# SSL
SSL_ENABLED=true
SSL_PROVIDER=letsencrypt
LETSENCRYPT_STAGING=false # Real certificates
# Performance
POSTGRES_SHARED_BUFFERS=2GB
POSTGRES_EFFECTIVE_CACHE_SIZE=6GB
REDIS_MAXMEMORY=1GB
# Backups
BACKUP_ENABLED=true
BACKUP_SCHEDULE="0 2 * * *"
BACKUP_RETENTION_DAYS=30# Generate production secrets (NEVER reuse from staging)
nself prod secrets generate
# Rotate specific secret
nself prod secrets rotate POSTGRES_PASSWORD
# Validate secrets are set
nself prod secrets validate# Initialize production environment
nself prod init example.com --email admin@example.com
# Run security audit
nself prod check
# Output:
# Production Security Audit
# ────────────────────────────────────
# ✓ Admin UI disabled
# ✓ Console disabled
# ✓ Debug mode disabled
# ✓ SSL enabled with valid certificate
# ✓ Strong passwords set
# ✓ Firewall configured
# ✓ Backups enabled
# ✗ Rate limiting not configured
#
# Score: 87/100
# Recommendations: 1
# Apply security hardening
nself prod harden
# Request SSL certificate
nself prod ssl request example.com# Check SSH access
nself deploy check-access
# Preview deployment
nself deploy prod --dry-run
# Deploy to production (backend only)
nself deploy prod
# Check deployment health
nself deploy health prod
# View deployment logs
nself deploy logs prod# Project identification
PROJECT_NAME=myapp # Container prefix
BASE_DOMAIN=example.com # Service URL base
ENV=dev|staging|prod # Environment type
# Logging and debugging
DEBUG=true|false # Enable debug mode
LOG_LEVEL=debug|info|warning|error# Optional services
NSELF_ADMIN_ENABLED=true|false # Admin UI (port 3021)
MINIO_ENABLED=true|false # S3 storage
REDIS_ENABLED=true|false # Cache
MEILISEARCH_ENABLED=true|false # Search
MAILPIT_ENABLED=true|false # Email testing (dev only)
MONITORING_ENABLED=true|false # Prometheus/Grafana
FUNCTIONS_ENABLED=true|false # Serverless functions
MLFLOW_ENABLED=true|false # ML experiment tracking# PostgreSQL
POSTGRES_VERSION=16-alpine
POSTGRES_DB=myapp
POSTGRES_USER=postgres
POSTGRES_PASSWORD=<secret>
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
# Performance tuning
POSTGRES_SHARED_BUFFERS=256MB # 25% of RAM
POSTGRES_EFFECTIVE_CACHE_SIZE=768MB # 75% of RAM
POSTGRES_WORK_MEM=64MB
POSTGRES_MAX_CONNECTIONS=100# Hasura
HASURA_GRAPHQL_ADMIN_SECRET=<secret>
HASURA_GRAPHQL_ENABLE_CONSOLE=true|false
HASURA_GRAPHQL_DEV_MODE=true|false
# JWT
HASURA_JWT_KEY=<32+ character secret>
HASURA_JWT_TYPE=HS256|HS384|HS512
# SSL
SSL_ENABLED=true|false
SSL_PROVIDER=mkcert|letsencrypt|custom
LETSENCRYPT_EMAIL=admin@example.com
LETSENCRYPT_STAGING=true|falseWhen nself loads configuration, it merges files in this order (later overrides earlier):
.env.dev - Base development defaults.environments/{name}/.env - Environment-specific config.env.local - Generated merged config.environments/{name}/.env.secrets - Sensitive credentials# Example cascade for staging environment:
# 1. Load base defaults from .env.dev
# DEBUG=true, LOG_LEVEL=debug, etc.
# 2. Override with .environments/staging/.env
# DEBUG=false, LOG_LEVEL=info, BASE_DOMAIN=staging.example.com
# 3. Merge to .env.local
# 4. Apply secrets from .environments/staging/.env.secrets
# POSTGRES_PASSWORD=xxx, JWT_SECRET=xxx, etc.# Generate all secrets for an environment
nself staging secrets generate
nself prod secrets generate
# What gets generated:
# - POSTGRES_PASSWORD (24+ characters)
# - HASURA_GRAPHQL_ADMIN_SECRET (32+ characters)
# - JWT_SECRET (64+ characters)
# - MINIO_ROOT_PASSWORD (24+ characters)
# - REDIS_PASSWORD (24+ characters)
# - Additional service-specific secrets# Rotate a specific secret
nself prod secrets rotate POSTGRES_PASSWORD
# This will:
# 1. Generate new secret
# 2. Update .env.secrets file
# 3. Prompt for service restart
# 4. Optionally update dependent services
# Rotate all secrets (use with caution)
nself prod secrets rotate --all# Check if all required secrets are set
nself prod secrets validate
# Output:
# Secret Validation
# ────────────────────────────────────
# ✓ POSTGRES_PASSWORD: Set (24 chars)
# ✓ HASURA_GRAPHQL_ADMIN_SECRET: Set (32 chars)
# ✓ JWT_SECRET: Set (64 chars)
# ✗ SMTP_PASSWORD: Missing
#
# Status: 3/4 secrets configured.env.secrets files to gitchmod 600 permissions# 1. Development - Local testing
nself env switch dev
nself build
nself start
# Test your changes locally
# 2. Staging - Pre-production testing
nself env switch staging
nself build
nself staging deploy --dry-run # Preview
nself staging deploy # Deploy
nself deploy health staging # Verify
# 3. Production - Live deployment
nself env switch prod
nself build
nself deploy prod --dry-run # Preview
nself deploy prod # Deploy
nself deploy health prod # Verify# Staging shortcuts
nself staging deploy # Full deploy
nself staging secrets generate # Generate secrets
nself staging logs # View logs
# Production shortcuts
nself prod init example.com # Initialize
nself prod check # Security audit
nself prod harden # Apply hardening
nself prod ssl request # SSL certificate
nself deploy prod # Deploy# Check current environment
nself env status
# Force rebuild after switch
nself env switch staging
nself clean
nself build --force
nself start# Validate secrets are configured
nself env validate staging
# Generate missing secrets
nself staging secrets generate
# Check file permissions
ls -la .environments/staging/.env.secrets
# Should show: -rw------- (chmod 600)# Check SSH access
nself deploy check-access
# Test manual connection
ssh -i ~/.ssh/staging_key deploy@staging.example.com
# Check server.json configuration
cat .environments/staging/server.json
# View deployment logs
nself deploy logs stagingnself prod check regularlynself deploy healthProper environment management is the foundation of reliable deployments. Use the .environments/ structure to maintain clean separation between development, staging, and production configurations.