Deploying Maddy Mail Server
Introduction
Maddy is a modern, all-in-one mail server written in Go that replaces Postfix, Dovecot, and other components typically needed for a complete email setup. Designed with security and simplicity in mind, Maddy handles SMTP, IMAP, and all the complex parts of email delivery in a single binary.
Unlike traditional mail server stacks requiring extensive configuration across multiple services, Maddy provides everything you need in one package: sending mail, receiving mail, spam filtering, DKIM signing, and secure storage. The configuration is straightforward yet powerful, making self-hosted email accessible to more administrators.
Key highlights of Maddy:
- All-in-One: SMTP (sending), Submission (client sending), and IMAP (receiving) in one binary
- Modern Security: TLS 1.3, DKIM, SPF, DMARC, and MTA-STS support out of the box
- Simple Configuration: Single configuration file with sensible defaults
- Built-in Spam Filtering: Rspamd integration or built-in filtering
- Go Implementation: Fast, memory-efficient, and easy to deploy
- Virtual Users: Support for virtual mailboxes without system accounts
- Aliases: Email aliases and forwarding
- SQLite/PostgreSQL: Database backends for user and mailbox storage
- Metrics: Prometheus metrics for monitoring
- Active Development: Regular updates and security patches
- Open Source: GPLv3 licensed
This guide walks through deploying Maddy on Klutch.sh using Docker, configuring your mail domain, and setting up secure email delivery.
Why Deploy Maddy on Klutch.sh
Deploying Maddy on Klutch.sh provides several advantages:
Simplified Deployment: Klutch.sh handles the complexity of deploying a mail server with Docker.
Persistent Storage: Attach persistent volumes for your mailboxes and database. Your email survives restarts.
GitHub Integration: Connect your configuration repository directly from GitHub for version-controlled configurations.
Scalable Resources: Allocate CPU and memory based on email volume.
Environment Variable Management: Securely store credentials and API keys through Klutch.sh’s environment variable system.
Custom Domains: Use your own domain for email with proper DNS configuration.
Always-On Availability: Your mail server remains accessible 24/7.
Prerequisites
Before deploying Maddy on Klutch.sh, ensure you have:
- A Klutch.sh account
- A GitHub account with a repository for your Maddy configuration
- Basic familiarity with Docker and containerization concepts
- A domain name with DNS access for email configuration
- Understanding of email protocols and DNS records
Understanding Maddy Architecture
Maddy uses a modular, pipeline-based architecture:
Endpoints: Network listeners for SMTP, Submission, and IMAP protocols.
Pipelines: Message processing flows with configurable checks and modifiers.
Storage Backend: Mailbox storage using local filesystem or blob storage.
Authentication: User authentication via database or external providers.
Security Modules: DKIM signing, SPF checking, and other security features.
Preparing Your Repository
To deploy Maddy on Klutch.sh, create a GitHub repository containing your configuration.
Repository Structure
maddy-deploy/├── Dockerfile├── maddy.conf├── README.md└── .dockerignoreCreating the Dockerfile
Create a Dockerfile in the root of your repository:
FROM foxcpp/maddy:latest
# Copy configurationCOPY maddy.conf /etc/maddy/maddy.conf
# Create data directoriesRUN mkdir -p /var/lib/maddy
# Set permissionsRUN chown -R maddy:maddy /var/lib/maddy
# Expose mail portsEXPOSE 25EXPOSE 465EXPOSE 587EXPOSE 143EXPOSE 993
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ CMD maddy version || exit 1
CMD ["maddy", "-config", "/etc/maddy/maddy.conf"]Configuration File
Create a maddy.conf configuration file:
# Maddy Mail Server Configuration
# Domain and hostname$(hostname) = mail.example.com$(primary_domain) = example.com$(local_domains) = $(primary_domain)
# TLS configurationtls file /etc/maddy/certs/fullchain.pem /etc/maddy/certs/privkey.pem
# Storage pathsstate_dir /var/lib/maddy/stateruntime_dir /run/maddy
# Logginglog syslog /dev/log
# Authentication and storageauth.pass_table local_authdb { table sql_table { driver sqlite3 dsn /var/lib/maddy/credentials.db table_name passwords }}
storage.imapsql local_mailboxes { driver sqlite3 dsn /var/lib/maddy/imapsql.db}
# SMTP endpoint (receiving mail)smtp tcp://0.0.0.0:25 { limits { all rate 20 1s all concurrency 10 }
dmarc yes check { require_mx_record dkim spf }
source $(local_domains) { reject 501 5.1.8 "Use Submission for outgoing SMTP" }
default_source { destination postmaster $(local_domains) { deliver_to &local_mailboxes } default_destination { reject 550 5.1.1 "User doesn't exist" } }}
# Submission endpoint (sending mail)submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { limits { all rate 50 1s }
auth &local_authdb
source $(local_domains) { check { authorize_sender { prepare_email &local_authdb user_to_email identity } }
modify { dkim $(primary_domain) $(local_domains) default }
deliver_to &remote_queue }
default_source { reject 501 5.1.8 "Non-local sender domain" }}
# IMAP endpoint (reading mail)imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { auth &local_authdb storage &local_mailboxes}
# Outgoing mail queuetarget.queue remote_queue { target &outbound_delivery}
target.remote outbound_delivery { limits { destination rate 20 1s destination concurrency 5 } mx_auth { dane mtasts { cache fs fs_dir /var/lib/maddy/mtasts_cache } local_policy { min_tls_level encrypted min_mx_level none } }}Creating the .dockerignore File
Create a .dockerignore file:
.git.github*.mdLICENSE.gitignore*.log.DS_Store.env.env.localEnvironment Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
MADDY_HOSTNAME | Yes | - | Mail server hostname |
MADDY_DOMAIN | Yes | - | Primary email domain |
Deploying Maddy on Klutch.sh
Once your repository is prepared, follow these steps to deploy:
- Port 25 for SMTP (receiving mail)
- Port 465 for Submission (TLS)
- Port 587 for Submission (STARTTLS)
- Port 143 for IMAP
- Port 993 for IMAP (TLS)
- Detect your Dockerfile automatically
- Build the container image
- Attach the persistent volumes
- Start the Maddy mail server
Configure DNS Records
Before deployment, set up DNS records for your domain:
# MX recordexample.com. MX 10 mail.example.com.
# A record for mail servermail.example.com. A your-server-ip
# SPF recordexample.com. TXT "v=spf1 mx -all"
# DKIM record (generate after server setup)default._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=..."
# DMARC record_dmarc.example.com. TXT "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.com"Push Your Repository to GitHub
Initialize your repository and push to GitHub:
git initgit add Dockerfile maddy.conf .dockerignore README.mdgit commit -m "Initial Maddy mail server deployment"git remote add origin https://github.com/yourusername/maddy-deploy.gitgit push -u origin mainCreate a New Project on Klutch.sh
Navigate to the Klutch.sh dashboard and create a new project. Give it a descriptive name like “maddy” or “mail-server”.
Create a New App
Within your project, create a new app. Connect your GitHub account if you haven’t already, then select the repository containing your Maddy Dockerfile.
Configure Traffic
Maddy requires multiple ports:
Note: Email ports have specific requirements. Consult Klutch.sh documentation for port configuration.
Set Environment Variables
In the environment variables section, add:
| Variable | Value |
|---|---|
MADDY_HOSTNAME | mail.example.com |
MADDY_DOMAIN | example.com |
Attach Persistent Volumes
Add the following volumes:
| Mount Path | Recommended Size | Purpose |
|---|---|---|
/var/lib/maddy | 50+ GB | Mailboxes and databases |
/etc/maddy/certs | 100 MB | TLS certificates |
Deploy Your Application
Click Deploy to start the build process. Klutch.sh will:
Create User Accounts
Use maddyctl to create user accounts:
maddyctl users create user@example.comUser Management
Creating Users
Add email accounts:
maddyctl users create user@example.com# Enter password when promptedManaging Passwords
Update user passwords:
maddyctl users password user@example.comCreating Aliases
Set up email aliases:
maddyctl aliases add alias@example.com user@example.comEmail Client Configuration
IMAP Settings
Configure email clients:
| Setting | Value |
|---|---|
| Server | mail.example.com |
| Port | 993 (TLS) or 143 (STARTTLS) |
| Security | TLS/SSL |
| Username | user@example.com |
SMTP Settings
For sending mail:
| Setting | Value |
|---|---|
| Server | mail.example.com |
| Port | 465 (TLS) or 587 (STARTTLS) |
| Security | TLS/SSL |
| Username | user@example.com |
Security Configuration
DKIM Setup
Generate DKIM keys:
maddyctl dkim generate defaultAdd the public key to your DNS as a TXT record.
SPF Configuration
Configure SPF in DNS:
example.com. TXT "v=spf1 mx -all"DMARC Policy
Set DMARC policy:
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:postmaster@example.com"Production Best Practices
Security Recommendations
- TLS Certificates: Use valid certificates from Let’s Encrypt
- Strong Passwords: Enforce strong passwords for all accounts
- Regular Updates: Keep Maddy updated for security patches
- Firewall Rules: Restrict access to mail ports
- Monitoring: Monitor for abuse and unauthorized access
Deliverability
Ensure your emails reach inboxes:
- PTR Record: Set up reverse DNS for your IP
- Warm Up: Gradually increase sending volume
- Authentication: Properly configure SPF, DKIM, DMARC
- Reputation: Monitor blacklist status
Backup Strategy
Protect your email data:
- Mailbox Backups: Regularly back up
/var/lib/maddy - Database Backups: Back up SQLite databases
- Configuration: Version control maddy.conf
- Keys: Securely back up DKIM private keys
Troubleshooting Common Issues
Mail Not Delivering
Symptoms: Emails not reaching recipients.
Solutions:
- Check DNS records (MX, SPF, DKIM)
- Verify PTR record
- Review outbound logs
- Check IP reputation
Authentication Failures
Symptoms: Users cannot log in.
Solutions:
- Verify credentials database
- Check authentication configuration
- Review auth logs
- Test with known-good credentials
TLS Certificate Issues
Symptoms: Certificate warnings or connection failures.
Solutions:
- Verify certificate validity
- Check certificate chain
- Ensure hostname matches certificate
- Renew expired certificates
Additional Resources
- Maddy Official Website
- Maddy Configuration Reference
- Maddy GitHub Repository
- Klutch.sh Persistent Volumes
- Klutch.sh Deployments
Conclusion
Deploying Maddy on Klutch.sh gives you a complete, modern mail server in a single application. The combination of Maddy’s all-in-one approach and Klutch.sh’s deployment simplicity means you can focus on managing your email rather than juggling multiple mail server components.
With built-in security features, simple configuration, and efficient Go implementation, Maddy handles the complexities of email delivery while remaining accessible to administrators. Whether you’re setting up personal email or small business communications, Maddy on Klutch.sh provides a reliable, self-hosted email solution.