DEPLOYMENT ARCHITECTURE - nself-org/cli GitHub Wiki

Deployment Architecture

This guide explains how nself deploys services across different environments and the distinction between staging and production deployments.

Service Categories

nself organizes services into five distinct categories:

1. Core Services (4) - Always Deployed

These are the foundational services required for any nself deployment:

Service Purpose Subdomain
PostgreSQL Primary database Internal only
Hasura GraphQL API engine api.domain.com
Auth Authentication service (nhost-compatible) auth.domain.com
Nginx Reverse proxy & SSL termination Main entry point

2. Optional Services (7) - Based on *_ENABLED Vars

Enable these based on your application needs:

Service Enable Flag Subdomain Purpose
nself-admin NSELF_ADMIN_ENABLED=true admin.domain.com Web management UI
MinIO MINIO_ENABLED=true minio.domain.com S3-compatible storage
Redis REDIS_ENABLED=true Internal Cache & sessions
Functions FUNCTIONS_ENABLED=true functions.domain.com Serverless runtime
MLflow MLFLOW_ENABLED=true mlflow.domain.com ML experiment tracking
Mailpit MAILPIT_ENABLED=true mail.domain.com Dev email testing
Meilisearch MEILISEARCH_ENABLED=true search.domain.com Full-text search

3. Monitoring Bundle (10) - All or Nothing

When MONITORING_ENABLED=true, all 10 services are deployed:

Service Purpose
Prometheus Metrics collection
Grafana Dashboards & visualization
Loki Log aggregation
Promtail Log shipping (required for Loki)
Tempo Distributed tracing
Alertmanager Alert routing
cAdvisor Container metrics
Node Exporter System metrics
Postgres Exporter Database metrics
Redis Exporter Redis metrics

4. Custom Services (CS_N) - Your Backend Applications

Completely independent backend applications with custom business logic:

# In .env
CS_1=order-api:express-js:8001    # Order processing API
CS_2=webhooks:nestjs:8002         # Webhook handler service
CS_3=payments:fastapi-py:8003     # Payment processing
CS_4=ml-inference:fastapi-py:8004 # ML model serving

Custom services are separate applications that:

  • Have their own codebase and logic
  • May or may not connect to the database
  • Run as independent Docker containers
  • Can integrate with Hasura via Actions/Event Triggers

Examples:

  • Order processing API
  • Payment processing service
  • Email notification worker
  • ML inference endpoint
  • Third-party integration handlers (webhooks, callbacks)

5. Remote Schemas - Multi-App Hasura Endpoints

Different from Custom Services! Remote Schemas are multiple Hasura GraphQL endpoints for different apps/tenants, all accessing the same database with different exposed schemas:

Same nself instance, same PostgreSQL, different GraphQL APIs:

api.app1.com โ†’ Hasura endpoint exposing App1 tables/permissions
api.app2.com โ†’ Hasura endpoint exposing App2 tables/permissions

Use case: One nself deployment serving multiple applications:

  • www.app1.com uses api.app1.com (sees users, products, orders)
  • www.app2.com uses api.app2.com (sees different tables/fields)

Configuration in .env:

# Remote Schemas (multiple Hasura endpoints)
REMOTE_SCHEMA_1_NAME=app1
REMOTE_SCHEMA_1_DOMAIN=api.app1.com

REMOTE_SCHEMA_2_NAME=app2
REMOTE_SCHEMA_2_DOMAIN=api.app2.com

6. Frontend Apps (FRONTEND_APP_N) - External Applications

Frontend applications configured for Nginx routing:

# In .env
FRONTEND_APP_1_NAME=web
FRONTEND_APP_1_PORT=3000
FRONTEND_APP_1_ROUTE=app

FRONTEND_APP_2_NAME=admin
FRONTEND_APP_2_PORT=3001
FRONTEND_APP_2_ROUTE=dashboard

Key Point: These are NOT Docker containers - they run outside Docker and Nginx routes to them.


Deployment Flow

๐Ÿ”‘ KEY DIFFERENCE: Frontend apps are included in staging (complete testing environment) but excluded in production (deployed separately to Vercel/CDN).

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    LOCAL DEVELOPMENT                             โ”‚
โ”‚  nself init โ†’ nself build โ†’ nself start                         โ”‚
โ”‚  All services run in Docker on localhost                        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                       STAGING                                    โ”‚
โ”‚  nself deploy staging                                           โ”‚
โ”‚                                                                  โ”‚
โ”‚  โœ… Deploys: Core + Optional + Monitoring + Custom + Frontends โ”‚
โ”‚                                                                  โ”‚
โ”‚  Frontend apps served by Nginx on subdomains:                   โ”‚
โ”‚    app.staging.example.com โ†’ Frontend App 1                     โ”‚
โ”‚    dashboard.staging.example.com โ†’ Frontend App 2               โ”‚
โ”‚                                                                  โ”‚
โ”‚  Complete replica for testing everything together               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                              โ”‚
                              โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      PRODUCTION                                  โ”‚
โ”‚  nself deploy production                                        โ”‚
โ”‚                                                                  โ”‚
โ”‚  โœ… Deploys: Core + Optional + Monitoring + Custom              โ”‚
โ”‚  โŒ Frontend apps EXCLUDED by default (deploy separately)       โ”‚
โ”‚                                                                  โ”‚
โ”‚  Frontend apps deployed to specialized platforms:               โ”‚
โ”‚    โ”œโ”€โ”€ Vercel (Next.js, React) - Auto-scaling, edge cache      โ”‚
โ”‚    โ”œโ”€โ”€ Cloudflare Pages (static) - Global CDN                  โ”‚
โ”‚    โ”œโ”€โ”€ Mobile apps (App Store, Play Store)                      โ”‚
โ”‚    โ””โ”€โ”€ Any CDN/hosting platform                                 โ”‚
โ”‚                                                                  โ”‚
โ”‚  API endpoints exposed:                                          โ”‚
โ”‚    api.example.com โ†’ Hasura GraphQL                             โ”‚
โ”‚    auth.example.com โ†’ Authentication                            โ”‚
โ”‚                                                                  โ”‚
โ”‚  ๐Ÿ’ก Override: Use --include-frontends to deploy frontends       โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Staging vs Production

โš ๏ธ IMPORTANT: The key difference is frontend app deployment behavior!

Aspect Staging Production
Frontend Apps โœ… INCLUDED (Nginx serves) โŒ EXCLUDED (Vercel/CDN)
Hasura Console โœ… Enabled โŒ Disabled
Debug Mode โŒ Off โŒ Off
Log Level info warning
Mailpit โœ… Available โŒ Use real email
Monitoring โš ๏ธ Optional โœ… Required
Purpose Testing & QA Live users

Why This Distinction?

๐Ÿ’ก TL;DR: Staging = test everything together. Production = backend on VPS, frontends on specialized platforms.

Staging: You want a complete replica to test everything together - frontend, backend, APIs, integrations. Nginx serves all frontend apps on staging subdomains. This ensures your staging environment matches the full user experience.

Production: Frontend apps have different scaling needs and are typically deployed on specialized platforms:

  • Vercel/Netlify: Automatic scaling, edge caching, preview deployments, serverless functions
  • Cloudflare Pages: Global CDN with 200+ edge locations, instant cache invalidation
  • Mobile Apps: App Store / Google Play (can't run on your VPS anyway)

Why separate?

  • โœ… Better performance (global CDN vs single VPS)
  • โœ… Lower costs (frontend hosting is often free)
  • โœ… Easier deployment (Git push vs Docker rebuild)
  • โœ… Better DX (preview deployments, instant rollbacks)

Your VPS focuses on what it does best: running the backend services, APIs, and databases.


Deployment Commands

Staging (Full Stack)

# Initialize staging
nself staging init staging.example.com --email [email protected]

# Configure server
# Edit .environments/staging/server.json

# Generate secrets
nself staging secrets generate

# Deploy everything
nself staging deploy

# What gets deployed:
#   โœ“ Core Services (PostgreSQL, Hasura, Auth, Nginx)
#   โœ“ Optional Services (based on *_ENABLED)
#   โœ“ Monitoring Bundle (if enabled)
#   โœ“ Custom Services (CS_1, CS_2, ...)
#   โœ“ Frontend Apps (FRONTEND_APP_1, FRONTEND_APP_2, ...)

Production (Backend Only)

# Initialize production
nself prod init example.com --email [email protected]

# Configure server
# Edit .environments/prod/server.json

# Generate secrets
nself prod secrets generate

# Security audit
nself prod check

# Deploy backend only
nself deploy prod

# What gets deployed:
#   โœ“ Core Services (PostgreSQL, Hasura, Auth, Nginx)
#   โœ“ Optional Services (based on *_ENABLED)
#   โœ“ Monitoring Bundle (if enabled)
#   โœ“ Custom Services (CS_1, CS_2, ...)
#   โ—‹ Frontend Apps (excluded - deploy to Vercel/CDN)

Override Default Behavior

# Force include frontends in production (unusual)
nself deploy prod --include-frontends

# Exclude frontends in staging (e.g., testing backend only)
nself staging deploy --exclude-frontends

Hasura Integration

Remote Schemas (Multi-App Endpoints)

nself can serve multiple applications from one deployment using Remote Schemas - different Hasura GraphQL endpoints with different exposed schemas, all hitting the same database:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    nself Deployment                          โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ api.app1.com โ”‚    โ”‚ api.app2.com โ”‚    โ”‚  api.main    โ”‚  โ”‚
โ”‚  โ”‚  (Remote 1)  โ”‚    โ”‚  (Remote 2)  โ”‚    โ”‚  (Default)   โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚         โ”‚                   โ”‚                   โ”‚           โ”‚
โ”‚         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜           โ”‚
โ”‚                             โ–ผ                               โ”‚
โ”‚                    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                      โ”‚
โ”‚                    โ”‚    PostgreSQL   โ”‚                      โ”‚
โ”‚                    โ”‚  (Same Database)โ”‚                      โ”‚
โ”‚                    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Use case: SaaS platform serving multiple white-label apps from one backend.

Custom Services Integration

Custom Services (CS_N) are separate backend applications that can integrate with Hasura:

Hasura Actions

Your Custom Service handles business logic called from GraphQL:

# Custom service for complex operations
CS_1=order-service:nestjs:8001

In Hasura Console โ†’ Actions:

  • Handler URL: http://order-service:8001/validate-and-process
  • Expose as: processOrder mutation
  • Hasura handles auth, your service handles logic

Hasura Event Triggers

Your Custom Service reacts to database changes:

# Worker service for async processing
CS_2=notification-worker:express-js:8002

In Hasura Console โ†’ Events:

  • Webhook URL: http://notification-worker:8002/on-order-created
  • Trigger on: INSERT into orders table
  • Your service sends emails, updates analytics, etc.

Standalone APIs

Custom Services can also be completely independent:

# Telemetry API (no Hasura integration)
CS_3=telemetry:express-js:8003

# ML inference (no Hasura integration)
CS_4=ml-api:fastapi-py:8004

These run alongside nself but handle their own routing and logic.


Example Project Structure

my-project/
โ”œโ”€โ”€ .environments/
โ”‚   โ”œโ”€โ”€ staging/
โ”‚   โ”‚   โ”œโ”€โ”€ .env              # Staging config
โ”‚   โ”‚   โ”œโ”€โ”€ .env.secrets      # Staging secrets
โ”‚   โ”‚   โ””โ”€โ”€ server.json       # Staging VPS SSH config
โ”‚   โ””โ”€โ”€ prod/
โ”‚       โ”œโ”€โ”€ .env              # Production config
โ”‚       โ”œโ”€โ”€ .env.secrets      # Production secrets
โ”‚       โ””โ”€โ”€ server.json       # Production VPS SSH config
โ”œโ”€โ”€ .env.dev                   # Local development config
โ”œโ”€โ”€ docker-compose.yml         # Generated by nself build
โ”œโ”€โ”€ nginx/                     # Generated nginx configs
โ”œโ”€โ”€ services/                  # Generated custom services
โ”‚   โ”œโ”€โ”€ payment_api/          # CS_1
โ”‚   โ”œโ”€โ”€ event_worker/         # CS_2
โ”‚   โ””โ”€โ”€ ml_inference/         # CS_3
โ””โ”€โ”€ frontend/                  # Your frontend apps (not in Docker)
    โ”œโ”€โ”€ web/                   # Next.js app โ†’ Vercel in prod
    โ””โ”€โ”€ mobile/                # React Native โ†’ App stores

Best Practices

  1. Staging mirrors production config - Same services, same structure
  2. Test everything in staging - Including frontend integrations
  3. Production is backend-focused - Let specialized platforms handle frontends
  4. Use Hasura for API - Custom services extend, don't replace it
  5. Monitor everything - Enable monitoring bundle in staging and production
  6. Secure secrets - Different secrets per environment, never commit them

Related Documentation

โš ๏ธ **GitHub.com Fallback** โš ๏ธ