Self-Hosting Guide
Deploy SimpleNS to production with flexible infrastructure hosting options.
Initial installation and setup
Refer the Getting Started Guide guide for initial installation and setup.
Overview
SimpleNS uses a split architecture that separates application services from infrastructure services, allowing flexible deployment across single or distributed systems.
| Compose File | Purpose | When to Use |
|---|---|---|
docker-compose.yaml | Application services (API, processors, dashboard) | Always required |
docker-compose.infra.yaml | Infrastructure (MongoDB, Kafka, Redis, Loki, Grafana) | Only if self-hosting infrastructure |
Customizing Infrastructure
The onboarding scripts let you choose which infrastructure services to deploy with Docker. This gives you flexibility to use managed cloud services for some components while self-hosting others.
Selective Infrastructure Services
During onboarding, you can select which services to deploy:
| Service | Description | Default |
|---|---|---|
| MongoDB | Primary database | Yes |
| Kafka | Message queue for notifications | Yes |
| Kafka UI | Web dashboard for Kafka monitoring | Yes |
| Redis | Caching and delay queue | Yes |
| Loki | Log aggregation | No |
| Grafana | Observability dashboard | No |
Using Managed/External Services
For any service you choose not to deploy via Docker, you'll be prompted to provide connection URLs:
| Environment Variable | Description | Example |
|---|---|---|
MONGO_URI | MongoDB connection string | mongodb+srv://user:pass@cluster.mongodb.net/simplens |
BROKERS | Kafka broker addresses | kafka-broker.cloud-provider.com:9092 |
REDIS_URL | Redis connection URL | redis://user:pass@redis.cloud-provider.com:6379 |
LOKI_URL | Loki endpoint (optional) | http://loki.cloud-provider.com:3100 |
Use managed services like MongoDB Atlas, Confluent Cloud, or Redis Cloud for production deployments to reduce operational overhead.
Plugin Configuration
The simplens.config.yaml file controls which notification providers are available and how they behave.
You can easily add a plugin in the simplens.config.yaml using the @simplens/config-gen cli tool. Refer the Plugin Installation Guide
Adding Providers
Each provider connects to an external notification service:
providers:
- package: "@simplens/nodemailer-gmail"
id: email-primary
credentials:
EMAIL_USER: ${EMAIL_USER}
EMAIL_PASS: ${EMAIL_PASS}
options:
priority: 2 # Higher = preferred
rateLimit:
maxTokens: 500
refillRate: 500
refillInterval: day
- package: "@simplens/resend"
id: email-backup
credentials:
RESEND_API_KEY: ${RESEND_API_KEY}
FROM_EMAIL: ${FROM_EMAIL}
options:
priority: 1 # Lower priority, used as fallback
rateLimit:
maxTokens: 1000
refillRate: 100
refillInterval: hour
channels:
email:
default: email-primaryProvider Options
| Option | Description |
|---|---|
priority | Higher value = preferred provider. Used for automatic failover. |
rateLimit.maxTokens | Token bucket capacity (max burst size) |
rateLimit.refillRate | Number of tokens added per interval |
rateLimit.refillInterval | Refill period: second, minute, hour, or day |
Channel Configuration
Map channels to their default providers:
channels:
email:
default: email-primary
sms:
default: twilio-main
push:
default: firebase-prodScaling with Kafka Partitions
SimpleNS uses Kafka topic partitions to enable horizontal scaling of workers. The partition count is set at initial startup via environment variables.
Partition Environment Variables
| Variable | Related Service | Description |
|---|---|---|
NOTIFICATION_STATUS_PARTITION | worker | Partitions for status update processing |
<CHANNEL>_PARTITION | notification_processor | Partitions per channel (e.g., EMAIL_PARTITION, SMS_PARTITION) |
DELAYED_PARTITION | delayed_processor | Partitions for scheduled notifications |
The recovery service doesn't depend on Kafka partitions and can be scaled independently.
Scaling Workers
To scale a worker, increase its corresponding partition count before first startup, then deploy multiple instances:
# Scale notification processor for email channel
EMAIL_PARTITION=4
# Scale worker for status updates
NOTIFICATION_STATUS_PARTITION=3
# Scale delayed processor
DELAYED_PARTITION=2# Deploy multiple instances
docker-compose up -d --scale notification_processor=4
docker-compose up -d --scale worker=3
docker-compose up -d --scale delayed_processor=2Partition counts cannot be decreased after Kafka topics are created. Plan your scaling needs before initial deployment.
For detailed configuration of all environment variables, see the Configuration Reference.
Deployment Scenarios
All services on one machine using self-hosted infrastructure.
# 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 -dUse managed cloud services instead of self-hosting.
# 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 -dWhen 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:
| Service | Image | Description |
|---|---|---|
api | ghcr.io/simplenotificationsystem/simplens-core:latest | REST API for notification ingestion |
worker | ghcr.io/simplenotificationsystem/simplens-core:latest | Background worker for outbox processing |
notification_processor | ghcr.io/simplenotificationsystem/simplens-core:latest | Plugin-based notification delivery |
delayed_processor | ghcr.io/simplenotificationsystem/simplens-core:latest | Scheduled notification handling |
recovery | ghcr.io/simplenotificationsystem/simplens-core:latest | Detects and rescues stuck notifications |
dashboard | ghcr.io/simplenotificationsystem/simplens-dashboard:latest | Admin 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:
| Service | Image | Description |
|---|---|---|
mongo | mongo:7.0 | MongoDB with replica set |
kafka | apache/kafka-native | Kafka with KRaft mode (no Zookeeper) |
kafka-ui | kafbat/kafka-ui:main | Kafka monitoring UI (optional) |
redis | redis:7-alpine | Redis for caching and queues |
loki | grafana/loki:2.9.0 | Log aggregation |
grafana | grafana/grafana:10.2.0 | Log visualization |
Port Reference
| Service | Port | Description |
|---|---|---|
| API | 3000 | REST API for notification ingestion |
| Dashboard | 3002 | Admin web interface |
| MongoDB | 27017 | Database |
| Kafka | 9092 | Message broker |
| Kafka UI | 8080 | Kafka monitoring (optional) |
| Redis | 6379 | Cache and queues |
| Loki | 3100 | Log aggregation |
| Grafana | 3001 | Log 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 --communitySecurity Considerations
Before Deploying to Production
Complete these security checks before going live.
- ✅ Generate strong
NS_API_KEYandAUTH_SECRETvalues - ✅ Set a secure
ADMIN_PASSWORD - ✅ Configure firewall rules to restrict infrastructure ports
- ✅ Set up SSL/TLS for API and dashboard
- ✅ Configure MongoDB authentication
- ✅ Set up backup strategy for MongoDB
- ✅ 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-initializationPlugin 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 .envGetting Started
Get SimpleNS up and running in under a minute. This guide will walk you through setting up a local instance and sending your first notification.
Local Development
Set up a complete SimpleNS development environment using VS Code Dev Containers. This guide covers the pre-configured devcontainer setup for streamlined local development.
Docs