Self-hosted Email with Docker and Mailcow

Whenever someone suggests self-hosting their emails there’s always a wave of people saying it’s too difficult or too much hassle, I took this information and decided to give it a go.

In this article I am using a DigitalOceon droplet, the reason for this is my homelab is on hardware that isn’t on all the time and on internal-only access which isn’t much use when you expect emails to arrive 24/7. You can host this in your home but you would need to set up port forwarding, firewall rules and if you’re in the UK like me probably DDNS.

Requirements

For this guide we will be using:

Create VM

Let’s start with our Droplet. We are using Ubuntu 18.04 LTS and when creating our droplet we want to make sure that the Reverse DNS name for our IP is the URL for our mail server. In my case, this will be mail.example.com and our IP address will be 123.456.78.910 (Further referred to as YOUR_IP)

Set DNS records

We’re going to set up our basic records now and then come back once complete to setup SPF, DMARC and DKIM. The basic DNS requirements for mailcow are as below

# Name              Type       Value
mail                IN A       YOUR_IP
autodiscover        IN CNAME   mail.example.com
autoconfig          IN CNAME   mail.example.com
@                   IN MX 10   mail.example.com

In CloudFlare it would look like this

Create User and grant Sudo rights

SSH into the machine using root and the password that has been emailed to you. Use the below command to add a new user with the name “mailcow”

adduser mailcow

Set and confirm the new user’s password at prompt. When asking for user information you can just leave it all blank and confirm with Y.

Changing the user information for username
Enter the new value, or press ENTER for the default
    Full Name []:
    Room Number []:
    Work Phone []:
    Home Phone []:
    Other []:
Is the information correct? [Y/n]

Use the usermod command to add the new account sudo rights

usermod -aG sudo mailcow

Now lets switch to our mailcow user and then disable root access

su - mailcow

Test you have sudo access by using whoami

sudo -u mailcow whoami

This should return your username “mailcow”. If that worked we will now go ahead and disable the root user.

sudo passwd -l root

Install Docker & Docker-compose

If you need a detailed guide on installing these two then I suggest you visit the docker and compose install guides here, otherwise, just run the commands below and it’ll be fine. If you get permission denied messages then try running the command with sudo in front.

Install Docker with the below command, this may take a minute so don’t be impatient.

curl -sSL https://get.docker.com/ | CHANNEL=stable sh

Enable the service and start docker

systemctl enable docker.service
systemctl start docker.service

Now install compose with the following commands. This will take a few minutes to complete.

curl -L https://github.com/docker/compose/releases/download/$(curl -Ls https://www.servercow.de/docker-compose/latest.php)/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Install Mailcow

Clone the repo and check the umask equals 0022.

umask
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized

Now we’re going to generate the configuration file, run the below command and when prompted for a hostname use mail.example.com

Depending on the specifications of your VPS you may be prompted to disable ClamAV.
ClamAV is a linux antivirus tool that will scan incoming mail, if you’re setting this up for multiple users I would suggest enabling this. If it’s just for you then leave it disabled as it is a RAM hog. With 2GB ram this was using 90% memory until I disabled it.

./generate_config.sh

Once generated let’s go-ahead and reduce the WOWorkersCount, this is the number of processes are generated for the webmail (SOgo) client. A good rule of thumb is 1 count for 10 users.

sudo nano data/conf/sogo/sogo.conf 

The default was set to 20 for me so go ahead and reduce the WOWorkersCount to 2/3. Use Ctrl + O to write out, Press Enter to Confirm and then Ctrl + X to Exit.

Lets go ahead and pull the images and then start the containers. Mailcow is a big set of containers so depending on your VPS it may take a few minutes to get set up and configured.

docker-compose pull

Once complete we will then run Docker-compose in detached mode. Give it 2 or 3 minutes to complete.

docker-compose up -d

Now we can visit mail.example.com and login with the default credentials of admin + moohoo.

Redirect HTTP to HTTPS

We’re going to edit our nginx configuration now so that all http requests are directed to https automatically. To do this we need to create a new file data/conf/nginx/redirect.conf

sudo nano data/conf/nginx/redirect.conf

Paste the below code and then Ctrl + O and then Enter to save, then Control + X to exit.

Lets now refresh our containers with the new changes

sudo docker-compose start nginx-mailcow

Configure MailCow

Once logged in make sure you change the default admin password, then from the dropdown menu at the top select Configuration and then Mail setup.

Let’s go ahead and select the green icon for “Add Domain”

Domain: example.com
Description: Self-Hosted Email

The other options you can either leave as is or modify depending on your preferences. At the bottom select “Add Domain Only” as we will make some other changes first and then restart SOgo.

Create Mailbox

Let’s go ahead and create our first mailbox, select Mailboxes from the tabs and select “Add Mailbox”, populate this box with your mailboxes desired information and select “Add”

Setup DKIM, DMARC and SPF

Head back to Configuration and details and then go to the Configuration tab, from there select your domain and leave dkim as the selector and select 2048 as the key length, then select Add. Copy the key that it generates as we will need it to set up our DKIM, DMARC and SPF later.

In Cloudflare, we’re going to add 3 more DNS entries.

SPF

Add a new SPF or Text record. Replace YOUR_IP with your actual IP and submit it. These values tell the mail servers that your IP is the only one allowed to send email as your domain name.

# Name              Type       Value
@               IN TXT       v=spf1 ip4:YOUR_IP ~all

For more complicated records or to customize it please check out the information here

DMARC

Create another TXT entry and use the below entry, you can add more to it depending on your preference, see DMARC Record Assistant for more info

# Name              Type       Value
_dmarc              IN TXT     v=DMARC1; p=quarantine

DKIM

Finally, we will implement DKIM. Create a new record with the below information and make sure you have the DKIM key we created earlier. Paste the copied key into the value section and save.

# Name              Type       Value
dkim._domainkey     IN TXT     v=dkim1; xxxxxxxxxxx

Check our mail score

We’re going to use a few tools now to make sure everything is setup correctly.

Head to mxtoolbox and enter your domain name, if everything is good you should see lots of green ticks.

Next, select the DMARC option at the top and enter your domain name. Again this should come back with all good.

Finally head to Mail Tester this will give you an email address to send to, let’s login to our mailbox using the SOgo client with the mailbox you created earlier.

Once logged in create a new email and send it to the email address shown on the mail tester website. Make sure to include a subject and also include a random paragraph in the body of the email.

Use the below as the body of the email if you can’t think of anything.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer odio nisl, rhoncus non odio et, porta facilisis neque. Pellentesque est augue, sagittis viverra ante vitae, feugiat sodales urna. Vestibulum pretium enim vitae nibh feugiat eleifend. Cras fringilla tortor quis tristique sagittis. Mauris tempus, justo vulputate luctus vestibulum, ante nibh tempor sapien, quis fringilla eros ipsum ac nisl. Nam sapien turpis, vestibulum eget nisi sit amet, bibendum feugiat lacus. Phasellus at vestibulum diam. Aenean vel mi sed nisl tempor ornare. Nunc dui turpis, egestas in mollis sit amet, maximus vel nulla. Curabitur a ipsum facilisis nulla elementum rutrum non sed urna. Nam congue massa ac est aliquet faucibus. Sed luctus, diam ac egestas pellentesque, dui ipsum efficitur enim, et iaculis ligula purus vel purus.

If we now check our results you should get a good score.

That’s it, hopefully, you can see how easy it is to set up your own email address.

Leave a Reply