Deployment
Running as a systemd Service
On Linux, the simplest way to run Mailgator in production is as a systemd service. Create a service file:
# /etc/systemd/system/mailgator.service [Unit] Description=Mailgator Email Proxy After=network-online.target Wants=network-online.target [Service] Type=simple User=mailgator Group=mailgator WorkingDirectory=/opt/mailgator ExecStart=/usr/local/bin/mailgator serve -c /opt/mailgator/config.toml Restart=on-failure RestartSec=5 LimitNOFILE=65536 # Security hardening NoNewPrivileges=true ProtectSystem=strict ReadWritePaths=/opt/mailgator [Install] WantedBy=multi-user.target
Then enable and start the service:
# Create a dedicated user sudo useradd --system --no-create-home --shell /usr/sbin/nologin mailgator # Set up the directory sudo mkdir -p /opt/mailgator sudo cp mailgator-config.toml /opt/mailgator/config.toml sudo cp mailgator-config-secrets.toml /opt/mailgator/config-secrets.toml sudo chown -R mailgator:mailgator /opt/mailgator sudo chmod 600 /opt/mailgator/config-secrets.toml # Enable and start sudo systemctl daemon-reload sudo systemctl enable mailgator sudo systemctl start mailgator # Check status sudo systemctl status mailgator sudo journalctl -u mailgator -f
Docker Deployment
Mailgator works well in Docker. Note that Docker deployments require a Max license (see Licensing).
# Dockerfile FROM alpine:latest COPY mailgator /usr/local/bin/mailgator RUN chmod +x /usr/local/bin/mailgator EXPOSE 1993 1587 8080 ENTRYPOINT ["mailgator"] CMD ["serve", "-c", "/etc/mailgator/config.toml"]
Build and run:
# Build docker build -t mailgator . # Run with mounted config docker run -d \ --name mailgator \ -p 1993:1993 \ -p 1587:1587 \ -p 8080:8080 \ -v /path/to/config.toml:/etc/mailgator/config.toml:ro \ -v /path/to/config-secrets.toml:/etc/mailgator/config-secrets.toml \ -v /path/to/data:/data \ mailgator
Docker Compose
For a complete setup with Docker Compose:
# docker-compose.yml
services:
mailgator:
image: mailgator:latest
restart: unless-stopped
ports:
- "1993:1993"
- "1587:1587"
- "8080:8080"
volumes:
- ./config.toml:/etc/mailgator/config.toml:ro
- ./config-secrets.toml:/etc/mailgator/config-secrets.toml
- mailgator-data:/data
volumes:
mailgator-data:
Make sure your config file uses paths relative to the container, for example:
[database] path = "/data/mailgator.db"
Kubernetes Basics
For Kubernetes deployments, store your config in a ConfigMap and your secrets in a Secret:
# Create ConfigMap from config file kubectl create configmap mailgator-config \ --from-file=config.toml=mailgator-config.toml # Create Secret from secrets file kubectl create secret generic mailgator-secrets \ --from-file=config-secrets.toml=mailgator-config-secrets.toml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mailgator
spec:
replicas: 1
selector:
matchLabels:
app: mailgator
template:
metadata:
labels:
app: mailgator
spec:
containers:
- name: mailgator
image: mailgator:latest
args: ["serve", "-c", "/etc/mailgator/config.toml"]
ports:
- containerPort: 1993
- containerPort: 1587
- containerPort: 8080
volumeMounts:
- name: config
mountPath: /etc/mailgator/config.toml
subPath: config.toml
readOnly: true
- name: secrets
mountPath: /etc/mailgator/config-secrets.toml
subPath: config-secrets.toml
- name: data
mountPath: /data
volumes:
- name: config
configMap:
name: mailgator-config
- name: secrets
secret:
secretName: mailgator-secrets
- name: data
persistentVolumeClaim:
claimName: mailgator-data
Important: Mailgator uses a SQLite database (for ask rules), so it should run as a single replica. If you need high availability, consider running multiple instances with separate configs and a load balancer.
Config Management
Best practices for managing your Mailgator configuration:
- Version control your config. The main config file (
mailgator-config.toml) does not contain secrets and is safe to commit to Git. - Never commit the secrets file. Add
*-secrets.tomlto your.gitignore. The secrets file contains your license token and encryption key. - Use
mailgator config validatein your CI pipeline to catch config errors before deploying. - Keep a backup of the secrets file. If you use the ask flow, losing the encryption key means pending emails cannot be replayed.
# .gitignore *-secrets.toml *.db
TLS in Production
Mailgator's listener ports accept plain-text connections from your email client. In production, you will typically want to put a reverse proxy in front of Mailgator to handle TLS termination.
For the web approval UI (ask flow), use a standard HTTPS reverse proxy. Here are examples for common reverse proxies:
Caddy
# Caddyfile
mailgator.company.com {
reverse_proxy localhost:8080
}
Nginx
server {
listen 443 ssl http2;
server_name mailgator.company.com;
ssl_certificate /etc/letsencrypt/live/mailgator.company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mailgator.company.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
For IMAP and SMTP TLS (ports 993 and 465), you would need a TCP-level TLS proxy (e.g., nginx stream module or HAProxy) rather than an HTTP reverse proxy. In many cases, it is simpler to run Mailgator on a private network and let your email clients connect locally or over a VPN.
Monitoring and Logging
Mailgator logs structured output to stdout. Each proxied connection and rule evaluation is logged with relevant details (username, operation, rule name, action).
If running with systemd, logs are available through journalctl:
# Follow logs sudo journalctl -u mailgator -f # Show recent logs sudo journalctl -u mailgator --since "1 hour ago"
With Docker, use docker logs:
docker logs -f mailgator
Backup Considerations
The following files should be included in your backup strategy:
| File | Priority | Notes |
|---|---|---|
| config.toml | High | Your rules and server configuration. Should be in version control. |
| config-secrets.toml | Critical | License token and encryption key. Without it, pending emails are lost. Store securely (not in Git). |
| mailgator.db | Medium | SQLite database with pending and historical approval records. Only exists if you use ask rules. |
For SQLite backups, you can use the sqlite3 backup command or simply copy the file while Mailgator is stopped. For live backups, use the SQLite .backup command to avoid corruption.