(The original tutorial was written by ntimo in 2019 and was updated to the current state and new topics)
Introduction
In this tutorial you will setup your own mail server running on an Ubuntu Server in the Hetzner Cloud. With Mailcow you can host your own mail server with your custom domain. Mailcow also provides a way to sync your Contacts and Calendar.
Official documentation: https://docs.mailcow.email/
Project Website: https://mailcow.email
GitHub: https://github.com/mailcow/mailcow-dockerized
Community forum: https://community.mailcow.email
Prerequisites
- You need a domain name
- A bit of knowledge of how Docker works
- Hetzner Cloud servers by default block port 25 and 465 to protect from spammers. You can request to get the ports unblocked after your first invoice was paid. This basically acts as a simple verification, that you are not a spammer.
Step 1 - Create a new Cloud server
- Sign-in to the Cloud Console
- Create a new project and name it whatever you want
- Choose a server location and type depending on your needs. See below for tips if you are unsure.
- Click
Add Server
and select your server image. This tutorial is based aroundUbuntu 22.04
but can easily be adapted toDebian 11
, which is more stable and lighter. - Choose the resources you need from Type
- Click on the field
Cloud config
enter this:#include https://get.docker.com
(this will install docker) - Select your SSH key
- You can read this article to learn how to generate an SSH key
- Write your server hostname in
name
input (mail.example.com) - Click
Create & Buy Now
How to choose the correct server location and type
Choose a server location which is geographically closest to you or your user base.
In regard to the correct server type, keep in mind that Mailcow requires at least 7GB RAM to function properly.
Mailcow is a fully-featured groupware solution.
Having that said, the lowest server type available would be a CX31* or CPX31.
*Availability of the CX line depends on your chosen location. As of the time of writing CX servers are not available in US locations.
Step 2 - Setup DNS
Basically, you want to create a new DNS record called mail.example.com and add your server IPv4 (A record) and IPv6 (AAAA record) to it.
Then, you can set up your domains MX record to point to your mail.example.com
subdomain that you just created.
You also need to set up an autodiscover.example.com
and autoconfig.example.com
subdomain. Both should be of the type CNAME and point to mail.example.com
.
Your DNS configuration should look similar to this:
# Name Type Value
mail IN A 10.0.0.1
mail IN AAAA 2001:db8:1234::1
autodiscover IN CNAME mail
autoconfig IN CNAME mail
@ IN MX 10 mail
For a more advanced setup, there are more DNS records you should watch out for in the Mailcow documentation.
Step 3 - Install updates and Docker Compose on the server
Wait a few seconds for the server to startup and then connect to it using SSH and your private key. Now you should install available updates on your server by running:
apt update && apt upgrade -y
This is a good time to reboot the server after all upgrades are finished, especially if there are kernel updates.
Step 4 - Clone the Mailcow Repository
Now we are going to clone the Mailcow GitHub repository, so first you need to cd
to /opt
with:
cd /opt
Once you are in /opt
, you can run:
git clone https://github.com/mailcow/mailcow-dockerized
Step 5 - Create the config, pull the Docker containers, and start Mailcow
When you run
./generate_config.sh
, you need the latest version of docker compose v2. You can usedocker compose version
to get your version and check if you need to upgrade to version 2.
To create the config, change your working directory to /opt/mailcow-dockerized
with cd /opt/mailcow-dockerized
and run ./generate_config.sh
this will generate the config. Now you have to enter your domain name (something like mail.example.com).
We are nearly done. Now, you have to run docker compose pull
to pull the docker images.
In order to start Mailcow, run docker compose up -d
Step 6 - Set up the reverse DNS entries
To set up your reverse DNS entries, do the following steps:
- Go to the Hetzner Cloud console and click on your project
- Select the server you just created and go to the
NETWORKING
tab - Click the three dots near your IPv4 address, select
Edit Reverse DNS
, enter your domain (mail.example.com), and confirm the change. - Click the three dots near your IPv6 subnet, select
Edit Reverse DNS
, and type::1
into the field where the IP is below your domain name (mail.example.com).
Step 7 - First login to your Mailcow instance
Visit your Mailcow instance at https://mail.example.org
and log in with the default credentials:
- Username:
admin
- Password:
moohoo
Important: Change your password as soon as possible, as leaving it as is opens your server up for breaches.
Step 8 - Add domain(s) to Mailcow
Now, you can add your domain to Mailcow. Simply go to Configuration
-> Mail setup
. Add your domain under the tab "Domain".
Step 9 - Setup DKIM
Now, when you go back to Configuration
-> Configuration & Details
you can set up DKIM. In the Configuration
tap, select DKIM in the sidebar. It should be at the top. Scroll down till you see the mask where you can enter your domain. Simply click Select domains with missing keys
shortcut to have your domain name filled in. Now, select a 2048
key and click on Add
. Once the key is added, you can copy the public key and create a DNS TXT entry called dkim._domainkey
with the content you just copied.
Step 10 - Create a mailbox
When you go back to Configuration
-> Mail setup
, you can create a mailbox and log into SOGo by accessing it at https://mail.example.com/SOGo.
Step 11 - Creating backups
Backups are essential for most server setups. Your mail server is no different. Mailcow provides a very simple way to create backups of your mail data.
Create a manual backup
- Connect to your server using your SSH key.
- Go to the Mailcow directory which contains the backup script
/opt/mailcow-dockerized/helper-scripts
- Run the backup script
./backup_and_restore.sh backup all --delete-days 7
- The script will ask you for your backup location.
--delete-days 7
will remove any backup in the chosen directory which is older than 7 days. Alter the value or remove it entirely depending on your needs.
The process can take some minutes to a few hours depending on your mails size and server type.
Create automated backups
- Connect to your server using your SSH key.
- Run
crontab -e
to enter your cron task list.- If it is the first time you run this command, you will be asked to choose an editor. Choose
(1) /bin/nano
as it is the easiest for new users.
- If it is the first time you run this command, you will be asked to choose an editor. Choose
- Paste the following into your crontab and update the details depending on your setup (see below):
0 5 * * * MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups /opt/mailcow-dockerized/helper-scripts/backup_and_restore.sh backup all --delete-days 7
MAILCOW_BACKUP_LOCATION
is the folder the backups will be written to. If you have a big mail database, consider adding a Volume to your server to expand its storage.
--delete-days 7
will remove any backup in the chosen directory which is older than 7 days. Alter the value or remove it entirely depending on your needs.
General recommendations
Consider the general rules of storing backups when creating a Mailcow instance. This includes having a copy of your backup in another location than your servers' disk (for example a Hetzner Storagebox).
Step 12 - Updating your Mailcow instance
Updates for Mailcow are generally released once per month by the authors. If there are urgent security patches or bugs, more updates are released. It is wise to keep an eye on the releases page of Mailcow for information about changes.
Before executing updates, it is recommended to check if you have current backups of your data. In the Hetzner Cloud Console, you can also create a Snapshot of your server to quickly revert back to a working state if something goes wrong.
If you don't want to use Hetzner Snapshots, Mailcow also has a built-in way to roll back from updates.
- Connect to your server using your SSH key.
- Go to the Mailcow directory
/opt/mailcow-dockerized
- Run
./update.sh
- The script will first check if there is a new
update.sh
file available and will update it. If this is the case, you have to re-run the script. - Then, all other updates will be pulled and prepared to be updated. You have to confirm the update.
- The script will first check if there is a new
- At the end, Mailcow will ask if you want to delete the now unused components. Select no and optionally delete them manually later on to be prepared if something went wrong.
- After the update is done, Mailcow will start up all services and run internal upgrades. Do not shut down your server or the docker containers to prevent data corruption.