One morning, I woke up to an email notifying me that someone had logged into my account from another country. At first, I assumed it was just a routine IP error and didn’t give it much thought.
But over the next few days, new emails kept coming in sporadically, each time from a different IP. This became a problem. If I didn’t take action soon, my mailbox might really be hijacked for mass emailing. So, I quickly deleted the MX, SPF, and DMARC records of the domain and sought a new solution.
I originally just wanted to change the password, but the entry point for changing the password in Tencent Enterprise Mail is incredibly well-hidden. I couldn’t find it anywhere. Forget it, I’ll migrate. No need to put up with this.
Pull Configuration Files
Docker-mailserver requires two configuration files, compose.yaml
and mailserver.env
. Pull the configuration files as follows:
|
|
You can modify the configurations as needed. Here are the parts I modified:
|
|
Using Caddy to Maintain TLS Certificates1
Since I was already using Caddy, I decided to use it to automatically maintain the certificates. According to the project’s official documentation, I just needed to add a subdomain in the Caddyfile, and Caddy would automatically maintain the certificates for me.
|
|
After updating the DNS records, I found that my situation was a bit special: my server didn’t use Caddy’s automatic certificate requesting feature but instead used a 15-year wildcard Cloudflare Origin Certificate. Even if I didn’t specify a certificate file for this subdomain, Caddy would load the wildcard certificate and think there’s no need to request a new one. This was quite awkward. With Caddy, it was either the Cloudflare Origin Certificate or the mail server. I had to install dns.providers.cloudflare
, so everything would be automated, out of sight, out of mind.
Global configuration after installing dns.providers.cloudflare
:
|
|
Finally, map Caddy’s certificate storage location to the Caddy container.
|
|
If Caddy runs as the root user, the certificate location should be /root/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourdomain.tld/
. Make the corresponding changes.
Then, as mentioned before, I mapped the certificate storage location to the /certs/
directory in the container, so the configuration is:
|
|
Firewall Configuration
My firewall is a bit special, using ufw
and the configuration mentioned in To Fix The Docker and UFW Security Flaw Without Disabling Iptables. So when I want to expose Docker container ports to the outside, I need to make additional configurations.
|
|
First Time Starting the Container
The first time you start the container, you need to create a new Postmaster account immediately (within 120 seconds).
|
|
Then you can stop the container and continue configuring.
|
|
DNS Records
- An A record, with any name (assume
mail
), pointing to the server IP (Cloudflare requires “DNS only”). - An MX record, Apex domain (@), pointing to
mail.yourdomain.tld
. - A TXT record (SPF), Apex domain (@), which can be generated here (optional).
- A TXT record (DMARC), name
_dmarc
, which can be generated here (optional). - A TXT record (DKIM), name
mail._domainkey
, specific configuration provided later in the text (optional).
DKIM, SPF, and DMARC2
What are DKIM, SPF, and DMARC? Simply put, DKIM is a digital signature mechanism; SPF is similar to an “employee list,” recording all legitimate sending servers; and DMARC is used to instruct the recipient’s server on how to handle emails that fail DKIM and SPF checks. 3
First, set up DKIM by generating a public/private key pair on the server.
|
|
The generated key pair can be found in the mapped container directory ./docker-data/dms/config/opendkim/keys/
.
Download the mail.txt
(or copy all its contents and paste into a local file), and import it into the Cloudflare Dashboard to complete the DKIM setup. Note that after configuring DKIM, you need to restart the container for the changes to take effect. 4
|
|
As mentioned earlier, SPF is like an “employee list.” Since I only have one legitimate sending server, the DNS should be configured as follows:
|
|
Lastly, for DMARC, you can use the template mentioned earlier, so I won’t be repeated here.
If your domain provider has its own setup wizard (such as Cloudflare), you can also use it to simplify the setup process.
Client Configuration
Client configuration is relatively simple. Both the IMAP and SMTP servers are mail.yourdomain.ltd
. After enabling SSL, the ports are 465 and 993, respectively. Just log in.
TODO-List
- Add an WebUI
Reference: https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl/#caddy ↩︎
Reference: https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/ ↩︎
More detailed introduction: https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/ ↩︎
This is mentioned in the official documentation. ↩︎