| title | description |
|---|---|
Installation |
How to self-host Notifuse |
Notifuse includes an interactive Setup Wizard that makes installation easy. Many environment variables are optional and can be configured through the web interface on first launch.
- Deploy Notifuse using one of the options below
- Access your instance in a web browser
- Complete the Setup Wizard:
- Enter your root administrator email
- Configure your API endpoint
- Set up SMTP settings
- Start using Notifuse!
Deploy Notifuse instantly with these one-click deployment options:
These deployment platforms will automatically set up Notifuse with all required dependencies. After deployment, you'll be guided through the Setup Wizard to complete your configuration.
You also have the following options to deploy Notifuse:
This option includes an embedded PostgreSQL database for easy testing and development:
# Clone the repository or download compose.yaml
curl -O https://raw.githubusercontent.com/notifuse/notifuse/main/compose.yaml
# Start Notifuse with embedded PostgreSQL
docker compose up -dThis will start Notifuse on port 8080 with a PostgreSQL database.
On first launch, you'll be guided through the Setup Wizard to configure your instance. Alternatively, you can configure environment variables in a .env file or directly in the compose.yaml.
For production deployments, use the standalone Docker image with your own PostgreSQL database:
docker run -d --name notifuse -p 8080:8080 notifuse/notifuse:latestOn first launch, you'll be guided through the Setup Wizard to configure your instance. Alternatively, you can configure environment variables.
Note: You'll need to provide your own PostgreSQL database.
If using the standalone Docker option, you can use any PostgreSQL database with root credentials. Notifuse automatically creates a system database for itself.
Recommended version: PostgreSQL 17 or higher
A new database will be created for each Notifuse workspace to avoid multi-tenant issues (that's why you need root credentials).
Note: This is not required when using Docker Compose as PostgreSQL is included.
Notifuse needs an SMTP server to send system emails (e.g. password reset emails, invitation emails, etc.).
If using SES, you can create SMTP credentials in the SMTP settings section of the SES dashboard.
Notifuse needs a public API endpoint to be accessible from the web. Example: https://emails.yourcompany.com
With the Setup Wizard, many environment variables are optional and can be configured through the web interface. Environment variables always take precedence over database settings when present.
**Special Characters in .env Files**If you're using a .env file and any of your values contain the # character (common in passwords), you must wrap the value in quotes:
# ✅ CORRECT - value is quoted
DB_PASSWORD="mypass#word123"
SECRET_KEY="abc123#xyz789"
# ❌ INCORRECT - will be truncated at the # character
DB_PASSWORD=mypass#word123 # parsed as "mypass"
SECRET_KEY=abc123#xyz789 # parsed as "abc123"This limitation only applies to .env files. Environment variables set directly in your shell, Docker Compose, or container orchestration platform do not have this restriction.
| Variable | Description |
|---|---|
DB_HOST |
PostgreSQL host (e.g., localhost or db.yourcompany.com) |
DB_PORT |
PostgreSQL port (e.g., 5432) |
DB_USER |
Database username (e.g., postgres) |
DB_PASSWORD |
Database password (e.g., postgres) |
SECRET_KEY |
Secret key for encryption (generate with command below) |
Generate SECRET_KEY:
openssl rand -base64 32These variables can be configured via the Setup Wizard on first launch, or set as environment variables. Environment variables always override wizard settings.
| Variable | Description |
|---|---|
ROOT_EMAIL |
Root administrator email (e.g., admin@yourcompany.com) |
API_ENDPOINT |
Public API endpoint URL (e.g., https://emails.yourcompany.com) |
SMTP_HOST |
SMTP server host (e.g., smtp.gmail.com) |
SMTP_PORT |
SMTP server port (e.g., 587 or 465) |
SMTP_USERNAME |
SMTP username (e.g., noreply@yourcompany.com) |
SMTP_PASSWORD |
SMTP password (e.g., your_smtp_password) |
SMTP_FROM_EMAIL |
From email address (e.g., noreply@yourcompany.com) |
SMTP_FROM_NAME |
From name (e.g., Your Company Name) |
| Variable | Description | Default |
|---|---|---|
| Server Configuration | ||
SERVER_PORT |
Port for the server to listen on (e.g., 8080) |
8080 |
SERVER_HOST |
Host address to bind to (e.g., 0.0.0.0) |
0.0.0.0 |
CORS_ALLOW_ORIGIN |
CORS allowed origins (e.g., https://yourapp.com,https://admin.yourapp.com) |
* |
ENVIRONMENT |
Environment mode (e.g., production) |
production |
LOG_LEVEL |
Logging level (e.g., debug or warn) |
info |
| Database Configuration | ||
DB_PREFIX |
Database table prefix (e.g., notifuse) |
notifuse |
DB_NAME |
Database name (e.g., notifuse_system) |
${DB_PREFIX}_system |
DB_SSLMODE |
SSL mode for database (e.g., require or disable) |
require |
DB_MAX_CONNECTIONS |
Total max connections across all databases (e.g., 100) |
100 |
DB_MAX_CONNECTIONS_PER_DB |
Max connections per workspace database (e.g., 3) |
3 |
DB_CONNECTION_MAX_LIFETIME |
Maximum lifetime of a connection (e.g., 10m) |
10m |
DB_CONNECTION_MAX_IDLE_TIME |
Maximum idle time before closing connection (e.g., 5m) |
5m |
| Task Scheduler Configuration | ||
TASK_SCHEDULER_ENABLED |
Enable internal task scheduler (e.g., true or false) |
true |
TASK_SCHEDULER_INTERVAL |
Task execution interval in seconds (e.g., 30) |
30 |
TASK_SCHEDULER_MAX_TASKS |
Maximum concurrent tasks (e.g., 10) |
10 |
| Privacy Settings | ||
TELEMETRY |
Send anonymous usage statistics (e.g., true or false) |
true |
CHECK_FOR_UPDATES |
Check for new versions (e.g., true or false) |
true |
| SMTP Relay Configuration | ||
SMTP_RELAY_ENABLED |
Enable SMTP relay server for transactional emails (e.g., true or false) |
false |
SMTP_RELAY_PORT |
SMTP relay port (e.g., 587 for STARTTLS) |
587 |
SMTP_RELAY_DOMAIN |
Public domain name for SMTP relay (e.g., smtp.yourdomain.com) |
localhost |
SMTP_RELAY_TLS_CERT_BASE64 |
Base64-encoded TLS certificate for SMTP relay | - |
SMTP_RELAY_TLS_KEY_BASE64 |
Base64-encoded TLS private key for SMTP relay | - |
| Tracing Configuration | ||
TRACING_ENABLED |
Enable tracing (e.g., true) |
false |
TRACING_SERVICE_NAME |
Service name for tracing (e.g., notifuse-production) |
notifuse-api |
TRACING_SAMPLING_PROBABILITY |
Sampling probability (e.g., 0.05) |
0.1 |
TRACING_TRACE_EXPORTER |
Trace exporter: jaeger/zipkin/stackdriver/datadog/xray/none (e.g., jaeger or datadog) |
none |
TRACING_JAEGER_ENDPOINT |
Jaeger endpoint (e.g., http://jaeger:14268/api/traces) |
http://localhost:14268/api/traces |
TRACING_ZIPKIN_ENDPOINT |
Zipkin endpoint (e.g., http://zipkin:9411/api/v2/spans) |
http://localhost:9411/api/v2/spans |
TRACING_STACKDRIVER_PROJECT_ID |
Stackdriver project ID (e.g., my-gcp-project-id) |
- |
TRACING_AZURE_INSTRUMENTATION_KEY |
Azure Monitor instrumentation key (e.g., 12345678-1234-1234-1234-123456789012) |
- |
TRACING_DATADOG_AGENT_ADDRESS |
Datadog agent address (e.g., datadog-agent:8126) |
localhost:8126 |
TRACING_DATADOG_API_KEY |
Datadog API key (e.g., 1234567890abcdef1234567890abcdef) |
- |
TRACING_XRAY_REGION |
AWS X-Ray region (e.g., us-east-1) |
us-west-2 |
TRACING_AGENT_ENDPOINT |
General agent endpoint (e.g., monitoring-agent:8126) |
localhost:8126 |
TRACING_METRICS_EXPORTER |
Metrics exporter: stackdriver/prometheus/datadog/none (e.g., prometheus) |
none |
TRACING_PROMETHEUS_PORT |
Prometheus metrics port (e.g., 9464) |
9464 |
The SMTP Relay feature allows you to connect SaaS applications that only provide SMTP integration (like Supabase Auth, Firebase, Auth0, etc.) to Notifuse. This gives you full control over email designs and branding using Notifuse's MJML editor, instead of being stuck with default SaaS templates.
See SMTP Relay usage documentation for examples of how to send emails once configured.
For production deployments, use valid TLS certificates from Let's Encrypt using certbot with DNS challenges.
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install certbot
# macOS
brew install certbot
# CentOS/RHEL
sudo yum install certbotDNS challenge is recommended because it doesn't require opening port 80 or 443, and works even if your SMTP server is on a different port.
# Generate certificate using DNS challenge
sudo certbot certonly \
--manual \
--preferred-challenges dns \
--email admin@yourdomain.com \
--agree-tos \
-d smtp.yourdomain.comWhen prompted, certbot will ask you to create a DNS TXT record:
Please deploy a DNS TXT record under the name
_acme-challenge.smtp.yourdomain.com with the following value:
XyZ123AbC456...
Before continuing, verify the record is deployed by running:
dig -t txt _acme-challenge.smtp.yourdomain.com
Add the TXT record to your DNS provider:
Type: TXT
Name: _acme-challenge.smtp
Value: XyZ123AbC456... (the value provided by certbot)
TTL: 300 (5 minutes)
Wait a few minutes for DNS propagation, verify with:
dig -t txt _acme-challenge.smtp.yourdomain.com
# Or using nslookup
nslookup -type=TXT _acme-challenge.smtp.yourdomain.comPress Enter in certbot to continue once the record is verified.
After certbot successfully generates the certificates, encode them to base64:
# Certificate location (typically):
# Certificate: /etc/letsencrypt/live/smtp.yourdomain.com/fullchain.pem
# Private Key: /etc/letsencrypt/live/smtp.yourdomain.com/privkey.pem
# Encode certificate to base64 (single line)
sudo cat /etc/letsencrypt/live/smtp.yourdomain.com/fullchain.pem | base64 -w 0 > cert_base64.txt
# Encode private key to base64 (single line)
sudo cat /etc/letsencrypt/live/smtp.yourdomain.com/privkey.pem | base64 -w 0 > key_base64.txt
# On macOS, omit the -w flag:
sudo cat /etc/letsencrypt/live/smtp.yourdomain.com/fullchain.pem | base64 > cert_base64.txt
sudo cat /etc/letsencrypt/live/smtp.yourdomain.com/privkey.pem | base64 > key_base64.txtCopy the base64-encoded values to your .env file:
SMTP_RELAY_ENABLED=true
SMTP_RELAY_DOMAIN=smtp.yourdomain.com
SMTP_RELAY_PORT=587
SMTP_RELAY_TLS_CERT_BASE64="<paste-cert-base64-here>"
SMTP_RELAY_TLS_KEY_BASE64="<paste-key-base64-here>"For local development, you can use self-signed certificates:
# Using the provided script
./scripts/generate-dev-certs.sh localapi.notifuse.com
# Or manually with openssl
openssl req -x509 -newkey rsa:2048 \
-keyout dev-cert.key.pem \
-out dev-cert.cert.pem \
-days 365 -nodes \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
# Encode to base64
cat dev-cert.cert.pem | base64 > cert_base64.txt
cat dev-cert.key.pem | base64 > key_base64.txtSetup Wizard vs Environment Variables
- Setup Wizard: Ideal for quick deployments and testing. Configuration is stored securely in the database and can be managed through the web interface.
- Environment Variables: Recommended for production deployments. Provides better security for sensitive data and allows configuration management through your deployment pipeline.
- Priority: Environment variables always take precedence over database settings when both are present.
For Production Deployments: We recommend using environment variables for sensitive configuration (SMTP credentials, SECRET_KEY) and the Setup Wizard or admin interface for non-sensitive settings (API endpoint, etc.).
For CI/CD pipelines and automated deployments, the root user can authenticate programmatically using HMAC-SHA256 signature, bypassing magic link authentication.
#!/bin/bash
# Configuration
NOTIFUSE_URL="https://your-notifuse-instance.com"
SECRET_KEY="your-secret-key"
ROOT_EMAIL="admin@example.com"
TIMESTAMP=$(date +%s)
# Generate HMAC signature
MESSAGE="${ROOT_EMAIL}:${TIMESTAMP}"
SIGNATURE=$(echo -n "$MESSAGE" | openssl dgst -sha256 -hmac "$SECRET_KEY" | awk '{print $2}')
# Authenticate and get JWT token
curl -X POST "${NOTIFUSE_URL}/api/user.rootSignin" \
-H "Content-Type: application/json" \
-d "{\"email\":\"${ROOT_EMAIL}\",\"timestamp\":${TIMESTAMP},\"signature\":\"${SIGNATURE}\"}"The endpoint returns a JWT token for subsequent API requests. Timestamps must be within 60 seconds of server time, and requests are rate limited to 5 attempts per 5 minutes.

