SimpleNS LogoDocs

Self-Hosting Guide

Deploy SimpleNS to production with flexible infrastructure hosting options.


Overview

SimpleNS uses a split architecture that separates application services from infrastructure services, allowing flexible deployment across single or distributed systems.

Compose FilePurposeWhen to Use
docker-compose.yamlApplication services (API, processors, dashboard)Always required
docker-compose.infra.yamlInfrastructure (MongoDB, Kafka, Redis, Loki, Grafana)Only if self-hosting infrastructure
docker-compose.dev.yamlAll-in-one development setupLocal development only

Quick Start

Create Project Directory

mkdir my-simplens && cd my-simplens

Download Required Files

Download these files from the simplens-core repository:

  • .env.example → rename to .env
  • docker-compose.yaml
  • docker-compose.infra.yaml (if self-hosting infrastructure)

Configure Environment

# Generate secrets
openssl rand -base64 32  # Copy to NS_API_KEY
openssl rand -base64 32  # Copy to AUTH_SECRET

Edit .env with your configuration (see Configuration Reference).

Generate Plugin Configuration

# For testing
npx @simplens/config-gen generate @simplens/mock

# For production email
npx @simplens/config-gen generate @simplens/nodemailer-gmail

Start Services

# Start infrastructure (if self-hosting)
docker-compose -f docker-compose.infra.yaml up -d

# Wait for infrastructure to be healthy (~30-60 seconds)
docker-compose -f docker-compose.infra.yaml ps

# Pull latest simplens-core and simplens-dashboard image from ghcr.io
docker-compose pull

# Start application services
docker-compose up -d

Verify Installation

# API Health
curl http://localhost:3000/health

# Check all services
docker-compose ps

Deployment Scenarios

All services on one machine using self-hosted infrastructure.

.env
# Leave INFRA_HOST unset (uses host.docker.internal)
MONGO_URI=mongodb://host.docker.internal:27017/simplens?replicaSet=rs0
BROKERS=host.docker.internal:9092
REDIS_URL=redis://host.docker.internal:6379
LOKI_URL=http://host.docker.internal:3100
# Start both compose files
docker-compose -f docker-compose.infra.yaml up -d
docker-compose up -d

Infrastructure and applications on separate machines.

On Infrastructure Host (e.g., 192.168.1.100):

.env on infrastructure machine
INFRA_HOST=192.168.1.100
docker-compose -f docker-compose.infra.yaml up -d

On Application Host:

.env on application machine
MONGO_URI=mongodb://192.168.1.100:27017/simplens?replicaSet=rs0
BROKERS=192.168.1.100:9092
REDIS_URL=redis://192.168.1.100:6379
LOKI_URL=http://192.168.1.100:3100
docker-compose up -d

Ensure firewall rules allow traffic on ports 27017, 9092, 6379, and 3100 between hosts.

Use managed cloud services instead of self-hosting.

.env
# MongoDB Atlas
MONGO_URI=mongodb+srv://user:pass@cluster.mongodb.net/simplens?retryWrites=true

# Confluent Cloud Kafka
BROKERS=kafka-broker.cloud-provider.com:9092

# Redis Cloud
REDIS_URL=redis://user:pass@redis.cloud-provider.com:6379

# Grafana Cloud Loki (or skip)
LOKI_URL=http://loki.cloud-provider.com:3100
# Only start application services
docker-compose up -d

When using cloud infrastructure, you don't need docker-compose.infra.yaml at all.


Application Services

The docker-compose.yaml uses pre-built images from GitHub Container Registry:

ServiceImageDescription
apighcr.io/simplenotificationsystem/simplens-core:latestREST API for notification ingestion
workerghcr.io/simplenotificationsystem/simplens-core:latestBackground worker for outbox processing
notification_processorghcr.io/simplenotificationsystem/simplens-core:latestPlugin-based notification delivery
delayed_processorghcr.io/simplenotificationsystem/simplens-core:latestScheduled notification handling
recoveryghcr.io/simplenotificationsystem/simplens-core:latestDetects and rescues stuck notifications
dashboardghcr.io/simplenotificationsystem/simplens-dashboard:latestAdmin dashboard (Next.js)

All application services share a plugin-data volume for plugins and mount simplens.config.yaml as read-only.


Infrastructure Services

The docker-compose.infra.yaml provides self-hosted infrastructure:

ServiceImageDescription
mongomongo:7.0MongoDB with replica set
kafkaapache/kafka-nativeKafka with KRaft mode (no Zookeeper)
kafka-uikafbat/kafka-ui:mainKafka monitoring UI (optional)
redisredis:7-alpineRedis for caching and queues
lokigrafana/loki:2.9.0Log aggregation
grafanagrafana/grafana:10.2.0Log visualization

Port Reference

ServicePortDescription
API3000REST API for notification ingestion
Dashboard3002Admin web interface
MongoDB27017Database
Kafka9092Message broker
Kafka UI8080Kafka monitoring (optional)
Redis6379Cache and queues
Loki3100Log aggregation
Grafana3001Log visualization

Config Generator CLI

The @simplens/config-gen CLI generates simplens.config.yaml from plugin manifests.

Commands

# Generate config for single plugin
npx @simplens/config-gen generate @simplens/mock

# Generate config for multiple plugins
npx @simplens/config-gen gen @simplens/nodemailer-gmail @simplens/mock

# Add plugin to existing config
npx @simplens/config-gen gen @simplens/nodemailer-gmail -c simplens.config.yaml

# Custom output path
npx @simplens/config-gen gen @simplens/mock -o custom.yaml

# Print to stdout
npx @simplens/config-gen gen @simplens/mock --stdout

# List official plugins
npx @simplens/config-gen list --official

# List community plugins
npx @simplens/config-gen list --community

Security Considerations

Before Deploying to Production

Complete these security checks before going live.

  1. ✅ Generate strong NS_API_KEY and AUTH_SECRET values
  2. ✅ Set a secure ADMIN_PASSWORD
  3. ✅ Configure firewall rules to restrict infrastructure ports
  4. ✅ Set up SSL/TLS for API and dashboard
  5. ✅ Configure MongoDB authentication
  6. ✅ Set up backup strategy for MongoDB
  7. ✅ Review and limit exposed ports

Troubleshooting

Services can't connect to infrastructure

  • INFRA_HOST: Ensure it matches the infrastructure machine's accessible IP
  • Firewall: Check ports 27017, 9092, 6379, 3100 are open
  • Network: Verify machines can ping each other

MongoDB replica set issues

# Reset and reinitialize
docker-compose -f docker-compose.infra.yaml down -v
docker-compose -f docker-compose.infra.yaml up -d
# Wait 60 seconds for auto-initialization

Plugin configuration not loading

# Verify config file exists
ls -la simplens.config.yaml

# Regenerate if needed
npx @simplens/config-gen generate @simplens/mock --stdout

# Set required environment variables in .env

On this page