Reverse proxy & SSL

SubsiMail can serve HTTPS on its own, or sit behind Nginx or Apache the way most self-hosted apps do. This page covers both, plus Certbot for the reverse-proxy paths, and how to change the port SubsiMail listens on either way.

Do you need one?

  • Fresh server, just SubsiMail, one domain — use built-in HTTPS. Nothing else to install or patch.
  • You already run other sites/services on this box, or already manage certificates for everything with Nginx/Apache + Certbot — put SubsiMail behind that same setup so it slots into what you have.

Don't run both at once. SubsiMail's built-in Let's Encrypt support and a reverse proxy both want ports 80 and 443 for themselves — pick one path per server.

Built-in HTTPS (no reverse proxy)

SubsiMail can provision and renew its own certificate via Let's Encrypt (using rustls-acme, built into the binary — no Certbot needed for this path). It's the same three environment variables on every install method, covered in detail on the Docker install page:

ACME_DOMAIN=mail.yourdomain.com
ACME_EMAIL=you@yourdomain.com
ACME_PRODUCTION=true
  • Point the domain's A record at your server first, and open ports 80 (for the Let's Encrypt HTTP-01 challenge) and 443 in your firewall — both are needed, not just 443.
  • Leave ACME_PRODUCTION unset (or false) while you're first getting the domain/DNS/firewall right — that uses Let's Encrypt's staging environment, which issues browser-untrusted test certs but has no rate limits. Flip it to true once a staging cert comes through cleanly, to get a real, browser-trusted one.
  • The trade-off: this claims ports 80/443 on the host for SubsiMail alone. If you want to host anything else on the same IP later, you'd need to move SubsiMail behind a reverse proxy at that point anyway.

Nginx + Certbot

Assumes SubsiMail is already running in plain-HTTP mode on port 3000 (leave ACME_DOMAIN/ACME_EMAIL/ACME_PRODUCTION unset) and Nginx is installed on the same host:

sudo apt update && sudo apt install nginx

Create /etc/nginx/sites-available/subsimail:

server {
    listen 80;
    server_name mail.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

Enable the site and reload:

sudo ln -s /etc/nginx/sites-available/subsimail /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

http://mail.yourdomain.com should now reach SubsiMail. Next, get a certificate with Certbot's Nginx plugin, which edits this same config file for you — adding the ssl_certificate lines and an HTTP→HTTPS redirect:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d mail.yourdomain.com

Certbot's Debian/Ubuntu package installs a systemd timer that renews automatically before the 90-day certificate expires — nothing to schedule yourself. Confirm it's there and that a renewal would succeed:

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Set TRUSTED_PROXY=true in SubsiMail's own environment once it's behind Nginx (or Apache, below). Without it, every request looks like it came from 127.0.0.1 — with it, SubsiMail reads the real visitor IP from the X-Forwarded-For header the config above sends, which is what shows up in login history and the audit trail.

Apache + Certbot

Same idea, Apache's module system instead of Nginx's config blocks:

sudo apt update && sudo apt install apache2
sudo a2enmod proxy proxy_http ssl headers

Create /etc/apache2/sites-available/subsimail.conf:

<VirtualHost *:80>
    ServerName mail.yourdomain.com

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/

    RequestHeader set X-Forwarded-Proto "http"
</VirtualHost>

Enable the site and reload:

sudo a2ensite subsimail
sudo apache2ctl configtest
sudo systemctl reload apache2

Then Certbot's Apache plugin, which edits this vhost the same way the Nginx plugin does — SSL directives and an HTTPS redirect added automatically:

sudo apt install certbot python3-certbot-apache
sudo certbot --apache -d mail.yourdomain.com

Renewal works the same way as the Nginx path above — a systemd timer installed alongside Certbot, verifiable with sudo certbot renew --dry-run. And the same TRUSTED_PROXY=true setting applies here too, so SubsiMail sees real client IPs instead of Apache's own address.

Changing the default port

Yes — it's the PORT environment variable, same name on every install method (already covered per-platform on the Linux and Windows install pages). It defaults to 3000.

  • Docker: simplest is to leave PORT alone and just change the host side of the port mapping in docker-compose.yml, e.g. "8080:3000" to expose it on 8080 instead. Only set the PORT env var too if you specifically need the container's internal port to differ — in that case both sides of the mapping need to match it, e.g. PORT: "8080" with "8080:8080".
  • Linux binary: PORT=8080 ./subsimail
  • Windows: $env:PORT = "8080" before running .\subsimail.exe

If you're using a reverse proxy from this page, just point it at the new port — change proxy_pass http://127.0.0.1:3000 (Nginx) or ProxyPass / http://127.0.0.1:3000/ (Apache) to match. Nothing else changes.

Which should I use?

ApproachBest whenTrade-off
Built-in HTTPSSingle-purpose server, just SubsiMailOwns ports 80/443 outright; nothing else can share them
Nginx + CertbotYou already run Nginx, or want the most common self-hosted stackOne more service to keep patched and configured
Apache + CertbotYou already standardized on ApacheSame as Nginx, slightly more verbose config syntax

Nginx and Apache are functionally equivalent here — both just forward requests to SubsiMail's port and let Certbot handle the certificate. Use whichever one you already run elsewhere rather than introducing a second proxy to maintain.