Environment Guide


v0.4.8Updated for nself v0.4.8

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.

Environment System Overview

  • Development (dev): Local development with debug tools and admin UI
  • Staging: Production-like environment for testing
  • Production (prod): Live deployment with security hardening

Environment Structure

Directory Layout

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 Purposes

FilePurposeGit Tracked
.envNon-sensitive configurationYes
.env.secretsPasswords, API keys, tokensNo (chmod 600)
server.jsonSSH deployment settingsYes (no secrets)
.env.exampleTemplate for new developersYes

Environment Commands

Managing Environments

# 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

Environment Information

# 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

Development Environment

Configuration

# .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

Development Workflow

# 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 urls

Development Features

  • Admin UI: Full access at admin.local.nself.org
  • MailPit: Capture all emails at mail.local.nself.org
  • Debug Logging: Verbose logging for troubleshooting
  • Hot Reload: Automatic service restart on code changes
  • Mock Data: Generate test data with nself db mock

Staging Environment

Configuration

# .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

Staging Secrets

# .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

Server Configuration

// .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"
}

Staging Deployment

# 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

Production Environment

Configuration

# .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

Production Secrets

# 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

Production Initialization

# 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

Production Deployment

# 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

Environment Variables Reference

Core Settings

# 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

Service Toggles

# 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

Database Configuration

# 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

Security Settings

# 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|false

Environment Cascade

When nself loads configuration, it merges files in this order (later overrides earlier):

  1. .env.dev - Base development defaults
  2. .environments/{name}/.env - Environment-specific config
  3. .env.local - Generated merged config
  4. .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.

Secrets Management

Generating Secrets

# 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

Secret Rotation

# 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

Secret Validation

# 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

Security Best Practices

  • Never commit .env.secrets files to git
  • Use different secrets for each environment
  • Rotate secrets regularly (quarterly recommended)
  • Secrets files should have chmod 600 permissions

Deployment Workflow

Complete Deployment Process

# 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

Quick Deployment Commands

# 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

Troubleshooting

Environment Not Switching

# Check current environment
nself env status

# Force rebuild after switch
nself env switch staging
nself clean
nself build --force
nself start

Missing Secrets

# 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)

Deployment Failures

# 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 staging

Best Practices

Configuration Management

  • Keep environments similar - Minimize differences between staging and production
  • Use templates - Start from standard templates for consistency
  • Document custom settings - Add comments explaining non-obvious values
  • Version control .env files - Commit non-secret configuration

Security

  • Separate secrets - Never share secrets between environments
  • Least privilege - Disable features not needed in production
  • Regular audits - Run nself prod check regularly
  • Rotate secrets - Update secrets on a regular schedule

Deployment

  • Always test in staging - Never deploy untested changes to production
  • Use dry-run - Preview deployments before executing
  • Health checks - Verify deployment with nself deploy health
  • Have a rollback plan - Know how to revert if issues occur

Next Steps

Proper environment management is the foundation of reliable deployments. Use the .environments/ structure to maintain clean separation between development, staging, and production configurations.