Configuration

Updated for nself v0.4.8

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.

Environment Directory Structure

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)

Environment Workflow (v0.4.7+)

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

Environment File Loading Priority

When an environment is active, configuration is loaded in this order (later values override earlier):

  1. .env.dev - Base development config (always loaded first)
  2. .environments/<name>/.env - Environment-specific config
  3. .env.local - Generated merged config
  4. .environments/<name>/.env.secrets - Sensitive credentials

Core Configuration

Project Settings

# 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

Database Configuration

# 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 GraphQL Engine

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

Service Configuration

Required Services (Always Enabled)

These four services form the core of every nself deployment:

ServicePortDescription
PostgreSQL5432Database
Hasura8080GraphQL Engine
Auth4000nHost Authentication
Nginx80/443Reverse proxy and SSL

Optional Services

# 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=mlflow

Monitoring Bundle

When 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 ENV

Custom Services (CS_N)

Define 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-ts

Frontend Applications

Route 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=cloud

Environment-Specific Configuration

Development (.environments/dev/.env)

ENV=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=true

Staging (.environments/staging/.env)

ENV=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

Staging Secrets (.environments/staging/.env.secrets)

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

Production (.environments/prod/.env)

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 * * *

Server Configuration (server.json)

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

Plugin Configuration (v0.4.8)

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/TLS Configuration

# 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

Configuration Commands

# 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

Best Practices

Security

  • Never commit secrets: Add .environments/*/.env.secrets to .gitignore
  • Use strong passwords: Use nself prod secrets generate for secure credentials
  • File permissions: Secrets files should have chmod 600
  • Environment separation: Use different secrets for each environment

Organization

  • Use environment templates: Start from local, staging, or prod templates
  • Validate before deploy: Run nself env validate
  • Document custom settings: Add comments for non-obvious configuration
  • Version control templates: Keep .env.example in version control

Computed Variables

These 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

Troubleshooting

Common Issues

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

Next Steps

Proper configuration is essential for a successful nself deployment. Use the environment directory structure to maintain separate configurations for development, staging, and production.