Skip to content

Self-host Shroud.email

Shroud.email is fully libre and open-source, and can be deployed on your own infrastructure. We provide a Docker Compose file for easy deployment.

You’ll need a server running on the public Internet, with ports 25, 80, and 443 open. In addition, you’ll need access keys for an S3-compatible object storage service.

Clone the complete Shroud.email monorepo and enter its hosting/ directory:

Terminal window
git clone https://github.com/Shroud-email/shroud.email.git
cd shroud.email/hosting

Run the remaining commands from hosting/ unless a step says otherwise. Keep the sibling caddy-permissive-file-storage/ directory: the Caddy image builds its storage module from that local source.

Shroud.email uses two domains. If your domain is e.g. example.com, then the first domain (APP_DOMAIN in .env) is where the web UI will be served (e.g. app.example.com). The second domain (EMAIL_DOMAIN) is the domain used by email aliases. For this, you can use your root domain, so that email aliases will end in @example.com.

Note that your APP_DOMAIN cannot be the same as your EMAIL_DOMAIN.

Type Name Content Notes
A app.example.com your IP
A example.com your IP Needed to get SSL certificate for example.com
MX example.com app.example.com
TXT example.com v=spf1 mx -all Don’t allow other servers to send emails from your domain

SPF (Sender Policy Framework) prevents others from forging emails from your domain.

If you added the SPF TXT record above, this should already be done. You can check your SPF configuration using free online tools like this one.

DKIM (DomainKeys Identified Mail) uses public-key cryptography to sign messages from your domain, so recipients can be sure that emails were not forged.

First, generate your keypair. From the repo you cloned, run the following:

Terminal window
# cd to the dkim directory so keys are created in the right place
$ cd haraka/haraka_config/config/dkim
$ ./dkim_key_gen.sh example.com # use your domain

Now, look in the directory ./example.com/dns. This file shows the TXT DNS record you need to add.

We’re getting there! DMARC builds on top of SPF and DKIM to tell recipients how to verify that emails really came from you.

Add the following TXT record for _dmarc.example.com. Replace dmarc@example.com with a monitored mailbox or a DMARC reporting service; we recommend Postmark.

v=DMARC1; p=none; rua=mailto:dmarc@example.com

The p=none policy requests monitoring without quarantine or rejection. The rua tag requests aggregate reports about SPF, DKIM, and DMARC results, including both passing and failing messages.

  • cp example.env .env and enter your configuration in .env.
  • Create Haraka’s hostname configuration file:
Terminal window
cp haraka/haraka_config/config/me.example haraka/haraka_config/config/me
  • Edit the newly created haraka/haraka_config/config/me with your EMAIL_DOMAIN. It should be a plaintext file with only this value, e.g.
example.com
docker compose up -d

And if you want to view logs:

docker compose logs -f

Once the logs show that Caddy has obtained the APP_DOMAIN certificate, you can continue. Public MX records must target APP_DOMAIN. The SMTP relay uses its certificate; EMAIL_DOMAIN does not need a separate TLS certificate. We need to bundle the certificate and private key in a format that the SMTP relay can understand. Run the following command:

docker compose exec cron /etc/periodic/daily/bundle_certs
docker compose restart haraka

You only need to run this manually once; going forward it will run automatically once per day.

Once legitimate mail authenticates reliably, you can consider requesting quarantine for messages that fail DMARC. Keep your aggregate reporting destination so you can monitor the effect:

v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com

Assuming you’ve already read about considerations when self-hosting, you know that it’s worth being careful when running your own mailserver.

Now, you should run some checks against your mailserver to ensure that you’re not running an open relay, that your SPF/DKIM/DMARC are configured properly, and that you’re not on any blocklists.

Here’s a non-exhaustive list of useful websites that can help check your configuration: