MailCow on Azure VM

Tom Kandula
5 min readJan 8, 2023

Your own email server

For many years I have used commercial email services like hotmail.com and gmail.com. They were great; however, at some point in time, I had to be able to automate things like setting up a new email box etc. I knew I would need my email server, where I would have complete control of all email boxes spanned across many different domains.

Thus, last year I decided to have one. Since I have some solid experience with Azure Cloud, I decided to use Azure Virtual Machine (CentOS) to host an email server.

After some research, my choice was to go with MailCow (dockerized). This article is a step-by-step procedure for setting up such an email server.

Prerequisites

Before we started, make sure you have:

  • Azure subscription.
  • Azure resource group for virtual machine.
  • Azure Virtual Machine (Linux based).
  • SendGrid account with added domain and generated API key.

I recommend to use size:Standard D4as (4 vcpus, 16 GiB memory), because we will need to have a room for quite large number of docker containers.

After creating Azure Virtual Machine; navigate to the VM and select an item called Networking. Now add the following ports:

Please note that we do not add port 25. This is because it is always blocked (unless you will make separate deal with Microsoft).

To send an email from the Azure Virtual Machine, we must use SMTP relay like SendGrid with SUBMISSION_PORT 587.

In next step go to resource group and select an item with a type Public IP address, then navigate to configuration and setup domain name, so the full address follows schema: <YOUR_NAME>.westeurope.cloudapp.azure.com.

Finally, log into the VM from a console and setup root password: sudo passwd root.

Once that is done, let’s install unnecessary ingredients.

GIT

Let’s install GIT, and execute following command:

sudo yum install git

Docker

To install docker, execute following command:

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

Docker-Compose

To install docker-compose, execute following command:

COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4)
sudo sh -c "curl -L https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-'uname -s'-'uname -m' > /usr/local/bin/docker-compose"
sudo chmod +x /usr/local/bin/docker-compose
sudo sh -c "curl -L https://raw.githubusercontent.com/docker/compose/${COMPOSE_VERSION}/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose"
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

Now we may check if everything is OK, following command will display version number:

docker-compose -v

Enabling SELinux

Before we can continue, we have to check if Security-Enhanced Linux is enabled. Run the command: sudo docker info | grep selinux. If nothing is printed on the console, then:

sudo touch /etc/docker/daemon.json
sudo nano /etc/docker/daemon.json

Paste below JSON code:

{
"selinux-enabled": true
}

To verify, just execute the first command again. You should see selinux. However, sometimes you may also see the following warnings:

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled

In such case, just edit file/etc/sysctl.conf by executing the following commandsudo nano /etc/sysctl.conf, add and save below configuration:

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1

MailCow

Now it is the time to get the MailCow. Execute the following commands:

su
umask

Here we switch to the root account and check the default user permission. We should see 0022 which translates to read/write access for files, and read/write/search for directories we own. All others have read access only to our files, and read/search access to our directories.

Then in the next step, we clone GitHub repository:

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

Execute script from mailcow-dockerized folder:

./generate_config.sh

When asked for host.domain.tld, provide with your full address: <YOUR_NAME>.westeurope.cloudapp.azure.com .

Go to postfixfolder and edit master.cf file:

nano /etc/postfix/master.cf

Disable by commenting out the follwoing line:

smtp    inet n - - - - smtpd

Save and exit. Apply below postfix configuration:

postconf -e "relayhost=172.22.1.1"
postconf -e "mynetworks=127.0.0.1/8 [::ffff:127.0.0.0]/104 [::1]/128"
postconf -e "inet_interfaces=loopback-only"
postconf -e "relay_transport=relay"
postconf -e "default_transport=smtp"

postfix stop
postfix start

Please note that the IP address 172.22.1.1 is the MailCow gateway in the Docker.

Navigate to the mailcow-dockerized folder and start docker-compose:

cd /opt/mailcow-dockerized
docker-compose pull
docker-compose up -d

After a while, we should have MailCow service up and running on our Virtual Machine.

Navigate to the VM URL in the web browser of choice:

Username: admin. Password: moohoo.

Now we should change our admin credentials, enable 2FA, add email boxes and domains.

However, this is not the final setup. We will not be able to send any email. To do that, we must configure SMTP relay. Assuming that we already have SendGrid API key for the domain:

Fill the host, the username and the password, where:

  • host value is smtp.sendgrid.net:587,
  • username value is any name of choice,
  • password value is API key from SendGrid.

Once that is done, click on the TEST. We should get similar positive verification:

Finally, we can navigate to the Configuration -> Mail Setup to edit our existing domain(s):

Now after saving our changes. We will be able to send emails.

Conclusion

The setup is fairly straightforward, mostly because it is dockerized version.

Once everything is up and running, we have access to great list of features like:

  • Very nice webmail (SOGo).
  • Aliases, Temporary Aliases & Domain Aliases.
  • Synchrontized jobs.
  • Filters and address rewriting.
  • Multiple administrative users, as well as domain-specific administrative accounts.
  • An extensive REST-API.
  • Two Factor Authentication (2FA).
  • Automatic SSL Certificate generation and renewal (it uses Let’s Encrypt free of charge).

…and much more (for some, MailCow may be too feature-rich).

Nevertheless, in my experience this is one of the best free mail server, which I always recommend.

Thank you for reading this article! Please leave a comment should you have any questions or have a different experience.

--

--

Tom Kandula

Software Engineer | NET | Azure | React | Freelancer & Contractor