Skip to main content

Mailcow - Docker Compose Stack, Setup a Mailcow Mailserver with SOGo Mailclient on a Hetzner Cloud Server

1103 words·
Mailcow Docker-Compose Debian Hetzner Cloud Route 53
Table of Contents

Prerequisites
#

In this tutorial I’m using:

  • A Hetzner Cloud “CAX11” cloud server with 2 (Arm64) CPU cores, 4GB RAM and 40GB disk space.

  • Debian 12 Bookworm as server OS

  • The domain “jueklu.net” that’s hosted on AWS Route 53


Hetzner Cloud
#

Firewall Ports
#

  • Open the following ports for inbound:
Service Protocol Port
Postfix SMTP TCP 25
Postfix SMTPS TCP 465
Postfix Submission TCP 587
Dovecot IMAP TCP 143
Dovecot IMAPS TCP 993
Dovecot POP3 TCP 110
Dovecot POP3S TCP 995
Dovecot ManageSieve TCP 4190
HTTP TCP 80
HTTPS TCP 443
Port Details

Port Description

SMTP (Simple Mail Transfer Protocol):

  • Port 25 (TCP) for SMTP: Receiving emails from other servers
  • Port 587 (TCP) for Submission: For secure email submission from email clients
  • Port 465 (TCP) for SMTPS: SMTP over SSL, less common but used by some clients

IMAP (Internet Message Access Protocol):

  • Port 143 (TCP) for IMAP: Accessing emails from email clients
  • Port 993 (TCP) for IMAPS: IMAP over SSL, for secure email access

POP3 (Post Office Protocol version 3):

  • Port 110 (TCP) for POP3: Downloading emails from the server
  • Port 995 (TCP) for POP3S: POP3 over SSL, for secure email downloading
  • Port 4190 (TCP) for managing sieve scripts via the ManageSieve protocol

HTTP/HTTPS (for accessing the mailcow UI and webmail):

  • Port 80 (TCP) for HTTP: Web interface
  • Port 443 (TCP) for HTTPS: Web interface secure
  • Apply the firewall to the cloud server

Reverse DNS Entry
#

# Hetzner Cloud: Projects
https://console.hetzner.cloud/projects
  • Go to Networking > Edit Reverse DNS

Port 25 and 465
#

Per default port 25 and 465 are blocked for the Hetzner cloud servers. They can be opened via the support menu (after the first bill) or after a few days if you send request per mail.


AWS Route 53: DNS Entries
#

Go to Route 53 > Hosted zones

A Record (IPv4)
#

Add an A record for the subdomain “mail” (mail.jueklu.net) that points to the IPv4 address of the mail server.

# Name                  Type        Value
mail.jueklu.net         A           135.181.97.75

CNAME Records
#

Add CNAME records for “autodiscover” and “autoconfig” that point to your “mail” subdomain “mail.jueklu.net.” These are used by email clients for automatic discovery of mail server settings.

# Name                  Type        Value
autodiscover            CNAME       mail.jueklu.net.
autoconfig              CNAME       mail.jueklu.net.

MX Record (Mail Exchange)
#

Add an MX record that is used for routing emails.

# Name                  Type        Value
(blank)                 MX       10 mail.jueklu.net.

Debian Prerequisites
#

Create Swap File
#

# Create swapfile
sudo fallocate -l 4G /swapfile

# Change permissions
sudo chmod 600 /swapfile

# Mark the file as swap space
sudo mkswap /swapfile

# Enable the Swapfile
sudo swapon /swapfile

# Add fstab entry
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Install Docker & Docker Compose
#

  • Install the Docker ARM version for Debian 12
#!/bin/bash

# REF:https://docs.docker.com/engine/install/debian/#install-using-the-repository 

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the repository to Apt sources:
echo \
  "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian \
  "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Mailcow Setup
#

Install Dependencies
#

# Update package index
sudo apt update

# Install dependencies
sudo apt install curl git -y

Docker Compose
#

  • Clone Mailcow repository
# Change directory
cd /opt

# Clone the Mailcow repository
git clone https://github.com/mailcow/mailcow-dockerized
  • Generate configuration
# Change directory
cd /opt/mailcow-dockerized

# Generate configuration file
./generate_config.sh

# Mail server hostname (FQDN) - this is not your mail domain, but your mail servers hostname:
mail.jueklu.net # Enter the FQDN

# Timezone [Europe/Vienna]:
Europe/Vienna # Enter timezone

# Available Branches:
# - master branch (stable updates) | default, recommended [1]
# - nightly branch (unstable updates, testing) | not-production ready [2]
# Choose the Branch with it´s number [1/2]
1 # Select master branch

# Detecting if your IP is listed on Spamhaus Bad ASN List...
# Check completed! Your IP is clean
# Check the configuration, optional change HTTPS & HTTPS ports
cat mailcow.conf
  • Create / start container
# Create / start Docker stack
sudo docker compose up -d

# Check
docker ps --format '{{.Names}}'

# Shell output:
mailcowdockerized-ipv6nat-mailcow-1
mailcowdockerized-watchdog-mailcow-1
mailcowdockerized-acme-mailcow-1
mailcowdockerized-rspamd-mailcow-1
mailcowdockerized-ofelia-mailcow-1
mailcowdockerized-nginx-mailcow-1
mailcowdockerized-dovecot-mailcow-1
mailcowdockerized-postfix-mailcow-1
mailcowdockerized-php-fpm-mailcow-1
mailcowdockerized-solr-mailcow-1
mailcowdockerized-redis-mailcow-1
mailcowdockerized-mysql-mailcow-1
mailcowdockerized-clamd-mailcow-1
mailcowdockerized-dockerapi-mailcow-1
mailcowdockerized-netfilter-mailcow-1
mailcowdockerized-olefy-mailcow-1
mailcowdockerized-sogo-mailcow-1
mailcowdockerized-unbound-mailcow-1
mailcowdockerized-memcached-mailcow-1

Mailcow Configuration
#

Webinterface
#

# Access the Mailcow webinterface
https://mail.jueklu.net

# Default user:
admin

# Default PW:
moohoo

Admin PW & 2FA
#

Go to System > Configuration > Access

  • Click Edit to change the admin password

  • Click “Two-factor authentication:” Please select to add 2FA


Add Mail Domain
#

Go to E-Mail > Configuration

  • Select the Domains tab

  • Click + Add domain

  • Add the domain “jueklu.net”

  • Click Add domain and restart SOGo

Remainings DNS Entrys
#

  • Click on DNS to open the DNS status for the new domain
  • This provides a overview for the missing DNS entries. Copy the text for the DKIM DNS entry:

DKIM DNS Entry
#

  • Record name: dkim._domainkey

  • Record type: TXT

  • Value: Copy from Mailcow

Note: On AWS Route 53 it was necessary to split up the DKIM value into two parts in quotation marks, separated by a space. Like “part1” “part2”

For example:

"v=DKIM1; k=rsa;p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrL1y615QbUJEdHPfOINx" "6tBw4fFJ5YizSa/en5B5JUxpOUDGiFZWSYti4Ed+I0Y3ERUUE"

Otherwise Route 53 shows the following error:

Error occurred
Bad request.
(InvalidChangeBatch 400: CharacterStringTooLong (Value is too long)

DMARC DNS Entry
#

  • Record name: _dmarc

  • Record type: TXT

# Value: If an email fails the DKIM and SPF tests, mark it as spam:
v=DMARC1; p=quarantine; adkim=s; aspf=s;

SPF DNS Entry
#

# Add the following entry
v=spf1 a mx -all

# Link
http://www.open-spf.org/SPF_Record_Syntax/

SRV DNS Entry
#

# Route 53 SRV Syntax
priority weight port target

# Example
0 0 443 mail.jueklu.net

TLSA DNS Entry
#

TLSA is not supported by AWS Route 53.

Check Mailcow DNS
#

Open and close the DNS section of the domain, it should look like this:


Create a Mailbox
#

Go to E-Mail > Configuration > Mailboxes

  • Click + Add Mailbox
  • Define the “username” (username@domain.com)

  • Define a password

  • Click Add to create the mailbox

Create Alias
#

Optional create one or more aliases for the mailbox.

Go to E-Mail > Configuration > Alisas

  • Click + Add alias

SOGO Webmail
#

# Access the SoGo webinterface
https://mail.jueklu.net/SOGo/

Test Configuration
#

https://mail-tester.com

Links #

# Hetzner Cloud: Pricing
https://www.hetzner.com/cloud/

# Hetzner Cloud: Login
https://accounts.hetzner.com/login

# Hetzner Cloud: Server Overview
https://console.hetzner.cloud/projects
# Mailcow Github
https://github.com/mailcow/mailcow-dockerized

# Mailcow Official Documentation
https://docs.mailcow.email/

# Mailcow Official Documentation: Ports
https://docs.mailcow.email/getstarted/prerequisite-system/#default-ports

# Mailcow Official Documentation: DNS
https://docs.mailcow.email/getstarted/prerequisite-dns/#references