๐ŸŒ Domain & TLS Setup

Step 1: Configure DNS Records

First, set up the following DNS records in your domain management panel:

# A record โ€” point domain to server IP
chat.example.org. A 203.0.113.50
Note: After setting up records, it may take 5 minutes to 24 hours to propagate. To check immediately: dig +short chat.example.org A

Step 2: Choose TLS Mode

Madmail supports four TLS modes. The table below shows the differences:

Mode Challenge DNS API Port 80 Use Case
autocert HTTP-01 No Required Production server
acme DNS-01 Yes No Server behind firewall
file โ€” โ€” โ€” Existing certificate
self_signed โ€” โ€” โ€” Testing & development

๐Ÿ† autocert mode Recommended

Install (Maddy Install)
sudo maddy install \
  --domain chat.example.org \
  --tls-mode autocert \
  --acme-email admin@example.org \
  --enable-chatmail \
  --non-interactive

How it works:

  1. Madmail starts an HTTP server on port 80 for the ACME challenge
  2. Let's Encrypt sends a request to port 80 to verify domain ownership
  3. A certificate is issued (valid for 90 days, auto-renewed)
  4. Certificates are stored in /var/lib/maddy/autocert/

In the configuration file (maddy.conf):

maddy.conf
tls {
    loader autocert {
        hostname chat.example.org
        email admin@example.org
        cache_dir /var/lib/maddy/autocert
        agreed
    }
}

๐Ÿ” acme mode (DNS-01) Advanced

Install (Maddy Install)
sudo maddy install \
  --domain chat.example.org \
  --tls-mode acme \
  --acme-email admin@example.org \
  --acme-dns-provider cloudflare \
  --acme-dns-token "YOUR_CLOUDFLARE_TOKEN" \
  --enable-chatmail \
  --non-interactive

Supported DNS providers: cloudflare, gandi, digitalocean, vultr, hetzner, route53

๐Ÿ“„ file mode (Existing certificate)

Install (Maddy Install)
sudo maddy install \
  --domain chat.example.org \
  --tls-mode file \
  --cert-path /etc/letsencrypt/live/chat.example.org/fullchain.pem \
  --key-path /etc/letsencrypt/live/chat.example.org/privkey.pem \
  --enable-chatmail

Configuration file format:

tls file /path/to/fullchain.pem /path/to/privkey.pem
Renewal: Set up a certbot hook to restart maddy after renewal:
systemctl restart maddy

๐Ÿงช self_signed mode (Testing)

Install (Maddy Install)
sudo maddy install \
  --simple --ip YOUR_SERVER_IP \
  --tls-mode self_signed \
  --turn-off-tls

Certificates are stored in /var/lib/maddy/certs/ and reused on subsequent restarts.

Step 3: Verify Certificate

After setup, verify your certificate with this command:

echo | openssl s_client -connect chat.example.org:443 \ -servername chat.example.org 2>&1 | \ openssl x509 -noout -subject -issuer -dates

Expected output:

subject=CN=chat.example.org issuer=C=US, O=Let's Encrypt, CN=E7 notBefore=Feb 21 15:41:47 2026 GMT notAfter=May 22 15:41:46 2026 GMT

Switching TLS Mode

From self_signed to autocert

Remove old certificates
sudo rm /var/lib/maddy/certs/fullchain.pem /var/lib/maddy/certs/privkey.pem
Reinstall with autocert
sudo maddy install \
  --domain chat.example.org \
  --tls-mode autocert \
  --acme-email admin@example.org \
  --enable-chatmail \
  --non-interactive
Final restart
sudo systemctl restart maddy

Troubleshooting

๐Ÿ”‘ file: Permission denied error?

Run the following commands to fix file ownership and permissions:

Fix Permissions
sudo chown root:maddy /path/to/cert.pem /path/to/key.pem
sudo chmod 640 /path/to/cert.pem /path/to/key.pem
๐Ÿ›ก๏ธ Security Notes: