Skip to content

Install mailcow

It's the same

The installation is exactly the same on x86 and ARM64 platforms!

Docker and Docker Compose Installation

You need Docker (a version >= 20.10.2 is required) and Docker Compose (a version >= 2.0 is required).

Learn how to install Docker and Docker Compose.

Quick installation for most operation systems:

Docker

curl -sSL https://get.docker.com/ | CHANNEL=stable sh
# After the installation process is finished, you may need to enable the service and make sure it is started (e.g. CentOS 7)
systemctl enable --now docker

docker compose

Danger

mailcow requires the latest version of docker compose v2.
If Docker was installed using the script above, the Docker Compose plugin is already automatically installed in a version >=2.0.
Is your mailcow installation older or Docker was installed in a different way, the Compose plugin or the standalone version of Docker must be installed manually.

Installation via Paketmanager (plugin)

Info

This approach with the package sources is only possible if the Docker repository has been included. This can happen either through the instructions above (see Docker) or through a manually integration.

On Debian/Ubuntu systems:

apt update
apt install docker-compose-plugin

On Centos 7 systems:

yum update
yum install docker-compose-plugin

Danger

The Docker Compose command syntax is docker compose for the plugin variant of Docker Compose!!!

Installation via Script (standalone)

Info

This installation is the old familiar way. It installs Docker Compose as a standalone program and does not rely on the Docker installation way.

LATEST=$(curl -Ls -w %{url_effective} -o /dev/null https://github.com/docker/compose/releases/latest) && LATEST=${LATEST##*/} && curl -L https://github.com/docker/compose/releases/download/$LATEST/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

Danger

The Docker Compose command syntax is docker-compose for the standalone variant of Docker Compose!!!

Please use the latest Docker engine available and do not use the engine that ships with your distros repository.

Check SELinux specifics

On SELinux enabled systems, e.g. CentOS 7:

  • Check if "container-selinux" package is present on your system:
rpm -qa | grep container-selinux

If the above command returns an empty or no output, you should install it via your package manager.

  • Check if docker has SELinux support enabled:
docker info | grep selinux

If the above command returns an empty or no output, create or edit /etc/docker/daemon.json and add "selinux-enabled": true. Example file content:

{
  "selinux-enabled": true
}

Restart the docker daemon and verify SELinux is now enabled.

This step is required to make sure mailcows volumes are properly labeled as declared in the compose file. If you are interested in how this works, you can check out the readme of https://github.com/containers/container-selinux which links to a lot of useful information on that topic.

Install mailcow

Clone the master branch of the repository, make sure your umask equals 0022. Please clone the repository as root user and also control the stack as root. We will modify attributes - if necessary - while bootstrapping the containers automatically and make sure everything is secured. The update.sh script must therefore also be run as root. It might be necessary to change ownership and other attributes of files you will otherwise not have access to. We drop permissions for every exposed application and will not run an exposed service as root! Controlling the Docker daemon as non-root user does not give you additional security. The unprivileged user will spawn the containers as root likewise. The behaviour of the stack is identical.

$ su
# umask
0022 # <- Verify it is 0022
# cd /opt
# git clone https://github.com/mailcow/mailcow-dockerized
# cd mailcow-dockerized

Initialize mailcow

Generate a configuration file. Use a FQDN (host.domain.tld) as hostname when asked.

./generate_config.sh

Change configuration if you want or need to.

nano mailcow.conf
If you plan to use a reverse proxy, you can, for example, bind HTTPS to 127.0.0.1 on port 8443 and HTTP to 127.0.0.1 on port 8080.

You may need to stop an existing pre-installed MTA which blocks port 25/tcp. See this chapter to learn how to reconfigure Postfix to run besides mailcow after a successful installation.

Some updates modify mailcow.conf and add new parameters. It is hard to keep track of them in the documentation. Please check their description and, if unsure, ask at the known channels for advise.

Troubleshooting

Users with a MTU not equal to 1500 (e.g. OpenStack)

Whenever you run into trouble and strange phenomena, please check your MTU.

Edit docker-compose.yml and change the network settings according to your MTU. Add the new driver_opts parameter like this:

networks:
  mailcow-network:
    ...
    driver_opts:
      com.docker.network.driver.mtu: 1450
    ...

Users without an IPv6 enabled network on their host system

Please don't turn off IPv6, even if you don't like it. IPv6 is the future and should not be ignored.

If you do not have an IPv6 enabled network on your host and you don't care for a better internet (thehe), it is recommended to disable IPv6 for the mailcow network to prevent unforeseen issues.

Start mailcow

Pull the images and run the compose file. The parameter -d will start mailcow: dockerized detached:

docker compose pull
docker compose up -d
docker-compose pull
docker-compose up -d

Done!

You can now access https://${MAILCOW_HOSTNAME} with the default credentials admin + password moohoo.

Info

If you are not using mailcow behind a reverse proxy, you should redirect all HTTP requests to HTTPS.

The database will be initialized right after a connection to MySQL can be established.

Your data will persist in multiple Docker volumes, that are not deleted when you recreate or delete containers. Run docker volume ls to see a list of all volumes. You can safely run docker compose down without removing persistent data.