Files
docs/Servers/Email/Mailcow.md
Nicole Rappe 94050b639e
All checks were successful
GitOps Automatic Deployment / GitOps Automatic Deployment (push) Successful in 5s
Update Servers/Email/Mailcow.md
2025-07-17 17:01:26 -06:00

227 lines
6.8 KiB
Markdown

## 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.