Overview
This guide walks you through installing SelfMX on TrueNAS SCALE using Docker Compose. SelfMX is a Resend-compatible email sending API (sending only) powered by AWS SES. It connects to an existing SQL Server instance running on your TrueNAS.
Prerequisites
Before starting, ensure you have:
- TrueNAS SCALE 24.10 or later (earlier versions used Kubernetes)
- Apps pool configured - a storage pool designated for application data
- SQL Server - already running as a container on TrueNAS (install from the app catalog if needed)
- AWS credentials - Access Key ID, Secret Access Key, and Region for SES (setup guide)
- A domain name pointing to your TrueNAS server (for HTTPS)
Gather Required Information
You will need these values during installation:
| Setting | Description |
|---|---|
AWS_ACCESS_KEY_ID | Your AWS access key for SES |
AWS_SECRET_ACCESS_KEY | Your AWS secret key |
AWS_REGION | AWS region where SES is configured (e.g., us-east-1) |
| Admin password | For browser login (min 12 characters) |
| Cloudflare credentials | Optional, for automatic DNS record creation |
Create Dataset and Directories
Before starting the installation, create a dataset for persistent storage.
- Navigate to Datasets in TrueNAS
- Create a dataset:
apps/selfmx(or similar, under your apps pool) - Create subdirectories inside the dataset using the TrueNAS Shell or SSH:
mkdir -p /mnt/YOUR_POOL/apps/selfmx/logs
Step 1: Create Database and User
See External SQL Server Setup for complete instructions on creating the SelfMX database and user.
Quick reference:
CREATE DATABASE SelfMX;
GO
CREATE LOGIN selfmx WITH PASSWORD = 'YourSelfMXPassword123!';
GO
USE SelfMX;
GO
CREATE USER selfmx FOR LOGIN selfmx;
GO
ALTER ROLE db_owner ADD MEMBER selfmx;
GO
Step 2: Generate Admin Password Hash
SelfMX stores admin passwords as SHA-512 crypt hashes. Generate one:
openssl passwd -6 "YourSecurePassword"
Save the hash (starts with $6$...) for the Docker Compose configuration.
Important: The hash contains $ characters which Docker Compose interprets as variables. You must either:
- Wrap the value in single quotes:
'$6$salt$hash...' - Or escape each
$as$$:$$6$$salt$$hash...
Step 3: Open the YAML Installation Wizard
- Navigate to Apps > Discover Apps
- Click the three-dot menu in the top right
- Select Install via YAML
Step 4: Configure the Application
Application Name
Enter: selfmx
Docker Compose Configuration
Paste the following YAML, replacing the placeholder values:
services:
selfmx:
image: ghcr.io/aduggleby/selfmx:latest
ports:
- "8080:17400"
environment:
- ASPNETCORE_ENVIRONMENT=Production
- App__Fqdn=YOUR_DOMAIN
- 'App__AdminPasswordHash=$6$YOUR_SALT$YOUR_HASH' # Single quotes prevent $ interpolation
- ConnectionStrings__DefaultConnection=Server=YOUR_TRUENAS_IP,1433;Database=SelfMX;User Id=selfmx;Password=YOUR_SELFMX_PASSWORD;TrustServerCertificate=true;Encrypt=True
- Aws__Region=YOUR_AWS_REGION
- Aws__AccessKeyId=YOUR_AWS_ACCESS_KEY_ID
- Aws__SecretAccessKey=YOUR_AWS_SECRET_ACCESS_KEY
volumes:
- /mnt/YOUR_POOL/apps/selfmx/logs:/app/logs
restart: unless-stopped
Values to Replace
| Placeholder | Replace With |
|---|---|
YOUR_DOMAIN | Your SelfMX domain (e.g., mail.example.com) |
$6$YOUR_SALT$YOUR_HASH | The SHA-512 hash from Step 2 (keep the single quotes!) |
YOUR_TRUENAS_IP | Your TrueNAS host IP address (e.g., 192.168.1.100) |
YOUR_SELFMX_PASSWORD | The password you set for the selfmx login in Step 1 |
YOUR_POOL | Your TrueNAS pool name (e.g., tank, data) |
YOUR_AWS_REGION | AWS region (e.g., us-east-1) |
YOUR_AWS_ACCESS_KEY_ID | Your AWS access key |
YOUR_AWS_SECRET_ACCESS_KEY | Your AWS secret key |
Optional Settings
These environment variables have sensible defaults but can be customized:
| Variable | Default | Description |
|---|---|---|
App__SessionExpirationDays | 30 | Admin session duration in days |
App__MaxLoginAttemptsPerMinute | 5 | Login rate limit |
App__MaxApiRequestsPerMinute | 100 | API rate limit per key |
App__VerificationTimeout | 72:00:00 | Domain verification timeout |
App__VerificationPollInterval | 00:05:00 | Verification check interval |
Cloudflare__ApiToken | For automatic DNS record creation | |
Cloudflare__ZoneId | Cloudflare zone ID |
Step 5: Install
Click Install to deploy the container. TrueNAS will pull the Docker image and start SelfMX.
Step 6: Configure Reverse Proxy
For HTTPS access, configure a reverse proxy.
Option A: TrueNAS Built-in or Traefik
If your TrueNAS has a public IP:
- Install Traefik from the TrueNAS app catalog
- Configure it to proxy
your-domain.com>localhost:8080
Option B: External Reverse Proxy
If using Caddy, nginx, or another external proxy:
# Example Caddy configuration
your-domain.com {
reverse_proxy YOUR_TRUENAS_IP:8080
}
Verification
- Access the SelfMX dashboard at
http://YOUR_TRUENAS_IP:8080(or your HTTPS domain) - Log in with your admin password
- Create an API key
- Add a domain for email sending
Updating SelfMX
To update to a new version:
- Navigate to Apps > Installed Applications
- Click on
selfmx - Click Edit > update the image tag or use
latest> Save
The container will restart with the new version.
Backups
For backup and restore procedures, see Database Backups.
Troubleshooting
View Logs
- Navigate to Apps > Installed Applications
- Click on
selfmx - Click Logs to view the container output
Container Won’t Start
Check that:
- All dataset paths exist and are accessible
- Environment variables are correctly formatted (no extra spaces)
- The SHA-512 hash doesn’t have special characters that need escaping
Database Connection Failed
- Verify the TrueNAS IP and port are correct
- Test the connection:
nc -zv YOUR_TRUENAS_IP 1433 - Verify the
selfmxlogin was created correctly - Check the password matches what you set in Step 1
Permission Denied on Mounted Volumes
TrueNAS may need ACL configuration:
- Navigate to the dataset in Datasets
- Click Edit Permissions
- Add an ACL entry for UID 0 (root) with full access