nself v0.4.8 provides flexible configuration through the .environments/ directory structure. This guide covers all configuration options for customizing your backend infrastructure across local development, staging, and production environments.
Starting with v0.4.7, nself uses a structured approach to environment management:
my-project/
├── .environments/ # Environment configurations
│ ├── dev/
│ │ └── .env # Development config
│ ├── staging/
│ │ ├── .env # Staging config
│ │ ├── .env.secrets # Staging secrets (git-ignored, chmod 600)
│ │ └── server.json # SSH connection details
│ └── prod/
│ ├── .env # Production config
│ ├── .env.secrets # Production secrets (git-ignored, chmod 600)
│ └── server.json # SSH connection details
├── .env # Active merged config (git-ignored)
├── .env.example # Template with all options
├── .current-env # Tracks current active environment
└── docker-compose.yml # Generated from config (do not edit)# Create environments
nself env create dev local
nself env create staging staging
nself env create prod prod
# Switch between environments
nself env switch dev
nself env switch staging
nself env switch prod
# Check current environment
nself env status
# Compare environments
nself env diff staging prodWhen an environment is active, configuration is loaded in this order (later values override earlier):
.env.dev - Base development config (always loaded first).environments/<name>/.env - Environment-specific config.env.local - Generated merged config.environments/<name>/.env.secrets - Sensitive credentials# Project identification
PROJECT_NAME=my-backend
# Default: my-backend
# Used for: Container names, database names, Docker network
# Base domain for all services
BASE_DOMAIN=local.nself.org
# Default: local.nself.org
# Used for: Service URLs (api.BASE_DOMAIN, auth.BASE_DOMAIN, etc.)
# Environment type
ENV=dev
# Default: dev
# Options: dev, staging, prod
# Affects: Console access, dev mode, security settings
# Database seeding
DB_ENV_SEEDS=true
# Default: true
# Enables environment-specific database initialization# PostgreSQL settings
POSTGRES_VERSION=16-alpine
# Options: 14-alpine, 15-alpine, 16-alpine
POSTGRES_DB=nhost
# Default: nhost
POSTGRES_USER=postgres
# Default: postgres
POSTGRES_PASSWORD=postgres-dev-password
# IMPORTANT: Change in production! Use secrets file.
POSTGRES_HOST=postgres
# Internal Docker hostname
POSTGRES_PORT=5432
# Default: 5432
POSTGRES_EXTENSIONS=uuid-ossp
# Comma-separated: uuid-ossp, pgcrypto, citext, pg_trgm, unaccent, hstore# Hasura version
HASURA_VERSION=v2.44.0
# Admin secret
HASURA_GRAPHQL_ADMIN_SECRET=hasura-admin-secret-dev
# CRITICAL: Change in production!
# JWT Configuration (Simple format - recommended)
HASURA_JWT_KEY=development-secret-key-minimum-32-characters-long
# Must be at least 32 characters
HASURA_JWT_TYPE=HS256
# Options: HS256, HS384, HS512, RS256, RS384, RS512
# Console and dev mode
HASURA_GRAPHQL_ENABLE_CONSOLE=true
# Default: true (dev), false (prod)
HASURA_GRAPHQL_DEV_MODE=true
# Default: true (dev), false (prod)
# Routing
HASURA_ROUTE=api
# Results in api.{BASE_DOMAIN}These four services form the core of every nself deployment:
| Service | Port | Description |
|---|---|---|
| PostgreSQL | 5432 | Database |
| Hasura | 8080 | GraphQL Engine |
| Auth | 4000 | nHost Authentication |
| Nginx | 80/443 | Reverse proxy and SSL |
# nself Admin UI (v0.0.8)
NSELF_ADMIN_ENABLED=true
NSELF_ADMIN_ROUTE=admin
# Access at admin.{BASE_DOMAIN}
# Port: 3021
# MinIO S3-compatible storage
MINIO_ENABLED=true
MINIO_ROUTE=storage
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
# CRITICAL: Change in production!
# Redis cache and sessions
REDIS_ENABLED=true
REDIS_PORT=6379
REDIS_PASSWORD=
# Empty for dev, set for production
# Serverless Functions
FUNCTIONS_ENABLED=false
FUNCTIONS_PORT=4300
FUNCTIONS_ROUTE=functions
# MeiliSearch full-text search
MEILISEARCH_ENABLED=true
MEILISEARCH_ROUTE=search
MEILISEARCH_MASTER_KEY=development-master-key
# Mailpit email testing (dev only)
MAILPIT_ENABLED=true
MAILPIT_ROUTE=mail
# Access UI at mail.{BASE_DOMAIN}
# MLflow ML experiment tracking
MLFLOW_ENABLED=false
MLFLOW_ROUTE=mlflowWhen MONITORING_ENABLED=true, all 10 monitoring services are enabled:
MONITORING_ENABLED=true
# Included services:
# - Prometheus (metrics collection)
# - Grafana (dashboards)
# - Loki (log aggregation)
# - Promtail (log shipping)
# - Tempo (distributed tracing)
# - Alertmanager (alerting)
# - cAdvisor (container metrics)
# - Node Exporter (host metrics)
# - Postgres Exporter (database metrics)
# - Redis Exporter (cache metrics)
# Memory profiles
nself metrics enable minimal # ~500MB
nself metrics enable standard # ~1GB (default)
nself metrics enable full # ~2GB
nself metrics enable auto # Auto-detect based on ENVDefine custom services using the CS_N pattern:
# Format: CS_N=name:framework[:port]
# N = 1-99
# Examples
CS_1=ping_api:express-ts:8001
CS_1_ROUTE=ping
CS_1_PUBLIC=true
CS_2=worker:fastapi:8002
CS_2_ROUTE=worker
CS_2_REPLICAS=2
# Advanced configuration per service
CS_1_MEMORY=512M # Memory limit
CS_1_CPU=1.0 # CPU cores
CS_1_REPLICAS=2 # Number of instances
CS_1_PUBLIC=true # Expose via nginx
CS_1_HEALTHCHECK=/health # Health endpoint
CS_1_RATE_LIMIT=100 # Requests per minute
# Available frameworks
# express, express-ts, fastapi, flask, django,
# nestjs, golang, rust-actix, rust-axum, node-tsRoute external frontend apps through nginx:
# Frontend app routing
FRONTEND_APP_1_NAME=org
FRONTEND_APP_1_PORT=3010
FRONTEND_APP_1_ROUTE=org
# Access at org.{BASE_DOMAIN}
FRONTEND_APP_2_NAME=docs
FRONTEND_APP_2_PORT=3011
FRONTEND_APP_2_ROUTE=docs
FRONTEND_APP_3_NAME=cloud
FRONTEND_APP_3_PORT=3013
FRONTEND_APP_3_ROUTE=cloudENV=dev
BASE_DOMAIN=local.nself.org
DEBUG=true
LOG_LEVEL=debug
# Full console access
HASURA_GRAPHQL_ENABLE_CONSOLE=true
HASURA_GRAPHQL_DEV_MODE=true
# Development services
MAILPIT_ENABLED=true
NSELF_ADMIN_ENABLED=true
# Monitoring disabled for faster startup
MONITORING_ENABLED=false
# Hot reloading for frontends
HOT_RELOAD_ENABLED=trueENV=staging
BASE_DOMAIN=staging.example.com
DEBUG=false
LOG_LEVEL=info
# Console enabled for debugging
HASURA_GRAPHQL_ENABLE_CONSOLE=true
HASURA_GRAPHQL_DEV_MODE=false
# SSL via Let's Encrypt (staging)
SSL_ENABLED=true
SSL_PROVIDER=letsencrypt
LETSENCRYPT_STAGING=true
# Monitoring enabled
MONITORING_ENABLED=true# Sensitive credentials - chmod 600, git-ignored
POSTGRES_PASSWORD=<strong-password>
HASURA_GRAPHQL_ADMIN_SECRET=<strong-secret>
JWT_SECRET=<32+-character-secret>
MINIO_ROOT_PASSWORD=<strong-password>
REDIS_PASSWORD=<strong-password>ENV=prod
BASE_DOMAIN=example.com
DEBUG=false
LOG_LEVEL=warning
# Security: Disable consoles
HASURA_GRAPHQL_ENABLE_CONSOLE=false
HASURA_GRAPHQL_DEV_MODE=false
NSELF_ADMIN_ENABLED=false
# SSL via Let's Encrypt (production)
SSL_ENABLED=true
SSL_PROVIDER=letsencrypt
LETSENCRYPT_STAGING=false
# Monitoring and backups
MONITORING_ENABLED=true
BACKUP_ENABLED=true
BACKUP_SCHEDULE=0 2 * * *Each environment with remote deployment needs a server.json file:
{
"name": "staging",
"type": "staging",
"host": "staging.example.com",
"port": 22,
"user": "deploy",
"key": "~/.ssh/staging_deploy_key",
"deploy_path": "/opt/myapp"
}Configure plugins by adding their required environment variables:
# Stripe Plugin
STRIPE_API_KEY=sk_test_xxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
# GitHub Plugin
GITHUB_TOKEN=ghp_xxxxx
GITHUB_WEBHOOK_SECRET=xxxxx
GITHUB_ORG=myorganization
# Shopify Plugin
SHOPIFY_STORE=your-store
SHOPIFY_ACCESS_TOKEN=shpat_xxxxx
SHOPIFY_WEBHOOK_SECRET=xxxxx# SSL Mode
SSL_ENABLED=true
SSL_PROVIDER=mkcert
# Options: mkcert (local), letsencrypt (production), custom
# Let's Encrypt
LETSENCRYPT_EMAIL=admin@example.com
LETSENCRYPT_STAGING=false
# Use staging=true for testing
# Custom certificates
SSL_CERT_PATH=/etc/ssl/certs/server.crt
SSL_KEY_PATH=/etc/ssl/private/server.key# Environment management
nself env list # List environments
nself env create staging staging # Create from template
nself env switch staging # Switch environment
nself env status # Show current status
nself env diff staging prod # Compare environments
nself env validate staging # Validate config
# Secrets management
nself staging secrets generate # Generate staging secrets
nself prod secrets generate # Generate production secrets
nself prod secrets rotate POSTGRES_PASSWORD # Rotate secret
# Build and apply
nself build # Generate docker-compose.yml
nself build --validate # Validate before building
# Production hardening
nself prod init example.com # Initialize production
nself prod check # Security audit
nself prod harden # Apply hardening.environments/*/.env.secrets to .gitignorenself prod secrets generate for secure credentialschmod 600local, staging, or prod templatesnself env validate.env.example in version controlThese are automatically computed from other variables:
# Routes (computed from BASE_DOMAIN)
HASURA_ROUTE=api.{BASE_DOMAIN}
AUTH_ROUTE=auth.{BASE_DOMAIN}
STORAGE_ROUTE=storage.{BASE_DOMAIN}
MAILPIT_ROUTE=mail.{BASE_DOMAIN}
# Database URL
HASURA_GRAPHQL_DATABASE_URL=postgres://{USER}:{PASS}@{HOST}:{PORT}/{DB}
# JWT Secret (from simple format)
HASURA_GRAPHQL_JWT_SECRET={"type":"{TYPE}","key":"{KEY}"}
# Docker network
DOCKER_NETWORK={PROJECT_NAME}_network# Validate configuration
nself env validate
# Check current environment
nself env status
# Regenerate SSL certificates
rm -rf ssl/certificates
nself build
nself trust
# Force rebuild
nself clean
nself build --force
# Debug mode
DEBUG=true nself startProper configuration is essential for a successful nself deployment. Use the environment directory structure to maintain separate configurations for development, staging, and production.