When it’s time to talk about regaining control of personal data, e-mail are on the top of my list.
I have never trusted Google to deal with my data (my photos, my e-mail, or my documents). Even if I admit Gmail offer a very convenient service and a wonderful anti-spam (thanks to all the data shared by 1.5 billion active users and their 10 millions of spam and malicious emails received every minute).
This guide will help you to recover control of your e-mail.
When your business relies on digital exchanges, your e-mail provider must be very reliable. A chance that the Simple Mail Transfer Protocol is robust, allowing your precious e-mail to be retransmitted in case of outage of a gateway. In fact, a gateway could be off-line during days before the e-mail would be returned to its sender.
By the time, in addition to SMTP, other protocols and standards has been added to provide a complete e-mail service:
- IMAP (used by your client to retrieve e-mail from the server)
- TLS/SSL (for security and privacy)
- SPF, DKIM and DMARC (to authenticate senders and fight against phishing and spam)
- Sieve (to define filtering rules)
For fun or if your needs are a bit specific, you can also do it yourself.
In my all life, I have built 3 times a complete e-mailing system for my personal use. Obsolescence of the underlying Debian system, and therefore security, was the main driver. This last time, I defined these requirements:
- Operating System abstraction (ie I can easily upgrade/change the OS without risking a major impact on the e-mail application stack)
- Sustainable Open-Source community supporting the entire stack
- Hardware abstraction
Looking for a stateless e-mail stack, I have rapidly identified docker-mailserver as a good candidate. Anti-spam is based on SpamAssassin (a personal choice based on my experience) and configuration is very simple (no web interface, no additional dabatase, KISS)).
If docker-mailserver does not fit you, have a look at those alternatives: mailcow or Mailu.
This (almost) stateless approach enables to easily upgrade or downgrade the VM (vertical scaling).
2 GB RAM + Swap (or 3 GB if you don’t want to use swap)
8 GB Storage for System and Container (don’t forget to add the Swap size if you need it)
+ Storage for e-mail accounts
ClamAV is memory consuming (more than 800MB for the virus signature database). If you don’t run ClamAV (for example if you use another ant-virus or gateway), you should be able to run with 512MB of RAM.
For e-mail accounts storage, my first thought was to use Object Storage but I was not able to find any Open-Source IMAP server. Then I have decided to go with a scalalable Block Storage solution (like Ceph-based OVH Block Storage).
For SMTP output, IP reputation is very important. Default VM’s IP does not seem to be a convenient choice. My preference goes to ‘Static’ IP (like an OVH Fail-Over IP). Another advantage is I could decide to replace the VM while keeping the same IP.
I assume a new Public Cloud Project has been created, and you have downloaded the OpenRC environment file.
First, load the environment:
If needed, push your SSH public key to OpenStack region
openstack keypair create --public-key ~/.ssh/id_rsa.pub mykey
We can not purchase any IP without a running instance. So we will instanciate the VM without any OS:
# Download cloudinit script that will help later to setup our VM
Using Customer Interface:
And assign it to the VM named
There are two types of block storage: classic and high-speed (
openstack volume type list). Performances of classic storage seems acceptable for an entry level mail gateway.
Create a 10GB volume and attache the volume to the instance:
# Create the volume
Pass the Static IP as meta-data (replace
22.214.171.124 with your own IP) and build the VM:
openstack server rebuild --property static_ip=126.96.36.199 --image "Ubuntu 18.04" email
Connect to the VM:
# LVM setup
Many Anti-spam blacklist systems rely on DNS, some of those blacklists rate-limit can be exceeded when using mutualized DNS resolver (your provider or global anycast like Quad9). Using your own local resolver with your Static IP would solve this issue.
Configure unbound to allow local resolution and use the Static IP for external request (replace
188.8.131.52 with your own IP):
Configure Systemd to start Unbound after Docker service:
sudo systemctl edit unbound.service:
sudo systemctl reload unbound.
To test your local DNS resolver, you can use a DNS reflector (like DNS Paranoia) and check it answers your Static IP:
dig +noall +answer reflect.dnsp.co
To generate certificate, run:
sudo docker run --rm -ti -v $PWD/log/:/var/log/letsencrypt/ -v $PWD/etc/:/etc/letsencrypt/ -p 80:80 certbot/certbot certonly --standalone -d mail.mydomain.com
Review the rules, then copy and apply:
sudo curl -o /etc/iptables/rules.v4 https://raw.githubusercontent.com/gmasse/emailgw/master/etc/iptables/rules.v4
Do not restart the service
iptables-persistentbecause it will overwrite the Docker default rules and prevent from accessing the container.
Download the configuration files:
sudo mkdir /mnt/mail/docker-mailserver
env-mailserver according to your setup (
By default, docker-mailserver uses
Maildirformat for mailboxes. This is a very common format where each e-mail is stored in one file. For better performances and/or to use Alternate storage, you can rely on Dovecot
mdbox(supported since the merge of my pull request).
Update and save
Create at least one e-mail account:
sudo ./setup.sh email add <user@domain> [<password>]
Then launch the container:
sudo docker-compose up -d mail
Let’s encrypt SSL auto-renew
Coudinit: add storage and dns configuration
Tiered storage, using Dovecot Alternate storage feature: recent emails on high-speed block storage, archives on normal speed
Volume (auto?) resize
E-mail configuration auto-discover