## Purpose The purpose of this document is to illustrate how to deploy Mailcow in a dockerized format. !!! note "Assumptions" It is assumed that you are deploying Mailcow into an existing Ubuntu Server environment. If you are using a different operating system, refer to the [official documentation](https://docs.mailcow.email/getstarted/install/). ### Setting Up Docker Go ahead and set up docker and docker-compose with the following commands: ```bash sudo su # (1) curl -sSL https://get.docker.com/ | CHANNEL=stable sh # (2) apt install docker-compose-plugin # (3) systemctl enable --now docker # (4) ``` 1. Make yourself root. 2. Install `Docker` 3. Install `Docker-Compose` 4. Make docker run automatically when the server is booted. ### Download and Deploy Mailcow Run the following commands to pull down the mailcow deployment files and install them with docker. Go get a cup of coffee as the `docker compose pull` command may take a while to run. !!! note "Potential `Docker Compose` Issues" If you run the `docker-compose pull` command and it fails for some reason, change the command to `docker compose pull` instead. This is just the difference between the plugin version of compose versus the standalone version. Both will have the same result. ```bash cd /opt git clone https://github.com/mailcow/mailcow-dockerized cd mailcow-dockerized ./generate_config.sh # (1) docker-compose pull # (2) docker-compose up -d ``` 1. Generate a configuration file. Use a FQDN (`host.domain.tld`) as hostname when asked. 2. If you get an error about the ports of the `nginx-mailcow` service in the `docker-compose.yml` stack, change the ports for that service as follows: ```yaml ports: - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" ``` ### Reverse-Proxy Configuration For the purposes of this document, it will be assumed that you are deploying Mailcow behind Traefik. You can use the following dynamic configuration file to achieve this: ```yaml title="/srv/containers/traefik/config/dynamic/mail.bunny-lab.io.yml" # ======================== # Mailcow / Traefik Config # ======================== # ---------------------------------------------------- # HTTP Section - Handles Mailcow web UI via Traefik # ---------------------------------------------------- http: routers: mailcow-server: entryPoints: - websecure tls: certResolver: letsencrypt service: mailcow-http rule: Host(`mail.bunny-lab.io`) services: mailcow-http: loadBalancer: servers: - url: http://192.168.3.61:80 passHostHeader: true # ---------------------------------------------------- # TCP Section - Handles all mail protocols # ---------------------------------------------------- tcp: routers: # ----------- # SMTP Router (Port 25, non-TLS, all mail deliveries) # ----------- mailcow-smtp: entryPoints: - smtp rule: "" # Empty rule = accept ALL connections on port 25 (plain SMTP) service: mailcow-smtp # ----------- # SMTPS Router (Port 465, implicit TLS) # ----------- mailcow-smtps: entryPoints: - smtps rule: "HostSNI(`*`)" # Match any SNI (required for TLS) service: mailcow-smtps tls: passthrough: true # ----------- # Submission Router (Port 587, implicit TLS or STARTTLS) # ----------- mailcow-submission: entryPoints: - submission rule: "HostSNI(`*`)" # Match any SNI (required for TLS) service: mailcow-submission tls: passthrough: true # ----------- # IMAPS Router (Port 993, implicit TLS) # ----------- mailcow-imaps: entryPoints: - imaps rule: "HostSNI(`*`)" # Match any SNI (required for TLS) service: mailcow-imaps tls: passthrough: true # ----------- # IMAP Router (Port 143, can be STARTTLS) # ----------- mailcow-imap: entryPoints: - imap rule: "HostSNI(`*`)" # Match any SNI (for TLS connections) service: mailcow-imap tls: passthrough: true # ----------- # POP3S Router (Port 995, implicit TLS) # ----------- mailcow-pop3s: entryPoints: - pop3s rule: "HostSNI(`*`)" # Match any SNI (required for TLS) service: mailcow-pop3s tls: passthrough: true # ----------- # Dovecot Managesieve (Port 4190, implicit TLS) # ----------- mailcow-dovecot-managesieve: entryPoints: - pop3s rule: "HostSNI(`*`)" # Match any SNI (required for TLS) service: dovecot-managesieve tls: passthrough: true services: # SMTP (Port 25, plain) mailcow-smtp: loadBalancer: servers: - address: "192.168.3.61:25" # SMTPS (Port 465, implicit TLS) mailcow-smtps: loadBalancer: servers: - address: "192.168.3.61:465" # Submission (Port 587, implicit TLS or STARTTLS) mailcow-submission: loadBalancer: servers: - address: "192.168.3.61:587" # IMAPS (Port 993, implicit TLS) mailcow-imaps: loadBalancer: servers: - address: "192.168.3.61:993" # IMAP (Port 143, plain/STARTTLS) mailcow-imap: loadBalancer: servers: - address: "192.168.3.61:143" # POP3S (Port 995, implicit TLS) mailcow-pop3s: loadBalancer: servers: - address: "192.168.3.61:995" # Dovecot Managesieve (Port 4190, implicit TLS) dovecot-managesieve: loadBalancer: servers: - address: "192.168.3.61:4190" ``` ### Traefik-Specific Configuration You will need to add some extra entrypoints and ports to Traefik itself so it can listen for this new traffic. ```yaml #Entrypoints - "--entrypoints.smtp.address=:25" - "--entrypoints.smtps.address=:465" - "--entrypoints.submission.address=:587" - "--entrypoints.imap.address=:143" - "--entrypoints.imaps.address=:993" - "--entrypoints.pop3.address=:110" - "--entrypoints.pop3s.address=:995" - "--entrypoints.dovecot-managesieve.address=:4190" #Ports - "25:25" - "110:110" - "143:143" - "465:465" - "587:587" - "993:993" - "995:995" - "4190:4190" ``` ### Login to Mailcow At this point, the Mailcow server has been deployed so you can log into it. - **Administrators**: `https://${MAILCOW_HOSTNAME}/admin` (Username: `admin` | Password: `moohoo`) - **Regular Mailbox Users**: `https://${MAILCOW_HOSTNAME}` (*FQDN only*) ### Mail-Client Considerations You need to ensure that you generate an app password if you have MFA enabled within Mailcow. (MFA is non-functional in Roundcube/SoGo, you set it up via Mailcow itself). You can access it via the Mailcow configuration page: https://mail.bunny-lab.io/user, then look for the "**App Passwords**" tab.