Skip to content

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
└── .dockerignore

Creating the Dockerfile

Create a Dockerfile in the root of your repository:

FROM foxcpp/maddy:latest
# Copy configuration
COPY maddy.conf /etc/maddy/maddy.conf
# Create data directories
RUN mkdir -p /var/lib/maddy
# Set permissions
RUN chown -R maddy:maddy /var/lib/maddy
# Expose mail ports
EXPOSE 25
EXPOSE 465
EXPOSE 587
EXPOSE 143
EXPOSE 993
# Health check
HEALTHCHECK --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 configuration
tls file /etc/maddy/certs/fullchain.pem /etc/maddy/certs/privkey.pem
# Storage paths
state_dir /var/lib/maddy/state
runtime_dir /run/maddy
# Logging
log syslog /dev/log
# Authentication and storage
auth.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 queue
target.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
*.md
LICENSE
.gitignore
*.log
.DS_Store
.env
.env.local

Environment Variables Reference

VariableRequiredDefaultDescription
MADDY_HOSTNAMEYes-Mail server hostname
MADDY_DOMAINYes-Primary email domain

Deploying Maddy on Klutch.sh

Once your repository is prepared, follow these steps to deploy:

    Configure DNS Records

    Before deployment, set up DNS records for your domain:

    # MX record
    example.com. MX 10 mail.example.com.
    # A record for mail server
    mail.example.com. A your-server-ip
    # SPF record
    example.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:

    Terminal window
    git init
    git add Dockerfile maddy.conf .dockerignore README.md
    git commit -m "Initial Maddy mail server deployment"
    git remote add origin https://github.com/yourusername/maddy-deploy.git
    git push -u origin main

    Create 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:

    • 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)

    Note: Email ports have specific requirements. Consult Klutch.sh documentation for port configuration.

    Set Environment Variables

    In the environment variables section, add:

    VariableValue
    MADDY_HOSTNAMEmail.example.com
    MADDY_DOMAINexample.com

    Attach Persistent Volumes

    Add the following volumes:

    Mount PathRecommended SizePurpose
    /var/lib/maddy50+ GBMailboxes and databases
    /etc/maddy/certs100 MBTLS certificates

    Deploy Your Application

    Click Deploy to start the build process. Klutch.sh will:

    • Detect your Dockerfile automatically
    • Build the container image
    • Attach the persistent volumes
    • Start the Maddy mail server

    Create User Accounts

    Use maddyctl to create user accounts:

    Terminal window
    maddyctl users create user@example.com

User Management

Creating Users

Add email accounts:

Terminal window
maddyctl users create user@example.com
# Enter password when prompted

Managing Passwords

Update user passwords:

Terminal window
maddyctl users password user@example.com

Creating Aliases

Set up email aliases:

Terminal window
maddyctl aliases add alias@example.com user@example.com

Email Client Configuration

IMAP Settings

Configure email clients:

SettingValue
Servermail.example.com
Port993 (TLS) or 143 (STARTTLS)
SecurityTLS/SSL
Usernameuser@example.com

SMTP Settings

For sending mail:

SettingValue
Servermail.example.com
Port465 (TLS) or 587 (STARTTLS)
SecurityTLS/SSL
Usernameuser@example.com

Security Configuration

DKIM Setup

Generate DKIM keys:

Terminal window
maddyctl dkim generate default

Add 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:

  1. PTR Record: Set up reverse DNS for your IP
  2. Warm Up: Gradually increase sending volume
  3. Authentication: Properly configure SPF, DKIM, DMARC
  4. Reputation: Monitor blacklist status

Backup Strategy

Protect your email data:

  1. Mailbox Backups: Regularly back up /var/lib/maddy
  2. Database Backups: Back up SQLite databases
  3. Configuration: Version control maddy.conf
  4. 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

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.