Docs / Email Servers / Maddy: Lightweight All-in-One Email Server

Maddy: Lightweight All-in-One Email Server

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 330 views · 4 min read

Maddy is a modern, lightweight email server written in Go that combines SMTP (MTA), IMAP, and security features in a single binary. Unlike traditional setups requiring separate Postfix, Dovecot, and OpenDKIM installations, Maddy provides everything in one compact package with a simple configuration file. This guide covers deployment and configuration for production email hosting.

Why Maddy?

  • Single binary — no complex multi-service setup; one process handles SMTP + IMAP
  • Modern defaults — TLS, DKIM, SPF, DMARC, and MTA-STS enabled by default
  • Low resources — runs comfortably on 512MB RAM VPS
  • Simple config — one configuration file instead of multiple service configs
  • Written in Go — static binary, no dependencies, fast startup

Prerequisites

  • VPS with public IPv4 and ports 25, 143, 465, 587, 993 open
  • Domain with DNS control
  • Reverse DNS (PTR) set to your mail hostname

Installation

# Download latest release
MADDY_VERSION=0.7.1
wget https://github.com/foxcpp/maddy/releases/download/v${MADDY_VERSION}/maddy-${MADDY_VERSION}-x86_64-linux-musl.tar.zst
tar --zstd -xf maddy-${MADDY_VERSION}-x86_64-linux-musl.tar.zst
sudo cp maddy-${MADDY_VERSION}-x86_64-linux-musl/maddy /usr/local/bin/
sudo cp maddy-${MADDY_VERSION}-x86_64-linux-musl/maddyctl /usr/local/bin/

# Create system user
sudo useradd -r -s /usr/sbin/nologin -d /var/lib/maddy maddy
sudo mkdir -p /etc/maddy /var/lib/maddy /run/maddy
sudo chown maddy:maddy /var/lib/maddy /run/maddy

Configuration

# /etc/maddy/maddy.conf

# Primary domain and hostname
$(hostname) = mail.example.com
$(primary_domain) = example.com
$(local_domains) = $(primary_domain)

# TLS certificates (use certbot or acme.sh)
tls file /etc/letsencrypt/live/mail.example.com/fullchain.pem /etc/letsencrypt/live/mail.example.com/privkey.pem

# SMTP listener (receiving mail from other servers)
smtp tcp://0.0.0.0:25 {
    hostname $(hostname)
    
    # Security checks
    check {
        require_mx_record
        dkim
        spf
        dmarc
    }
    
    # Deliver to local mailboxes or reject
    deliver_to &local_mailboxes
}

# Submission listener (sending mail from clients)
submission tls://0.0.0.0:465 tcp://0.0.0.0:587 {
    hostname $(hostname)
    
    auth &local_authdb
    
    # Sign outgoing mail with DKIM
    modify {
        dkim {
            domain $(primary_domain)
            selector default
            key_path /var/lib/maddy/dkim_keys/$(primary_domain)_default.key
        }
    }
    
    deliver_to &remote_queue
}

# IMAP listener
imap tls://0.0.0.0:993 tcp://0.0.0.0:143 {
    auth &local_authdb
    storage &local_mailboxes
}

# Local authentication database
auth.pass_table local_authdb {
    table sql_table {
        driver sqlite3
        dsn /var/lib/maddy/credentials.db
        table_name passwords
    }
}

# Local mailbox storage
storage.imapsql local_mailboxes {
    driver sqlite3
    dsn /var/lib/maddy/imapsql.db
}

# Remote delivery queue
target.queue remote_queue {
    target &remote_smtp
}

target.smtp remote_smtp {
    hostname $(hostname)
    # DKIM signing is handled in submission block
}

Generate DKIM Keys

sudo mkdir -p /var/lib/maddy/dkim_keys
sudo maddy certs dkim generate /var/lib/maddy/dkim_keys/example.com_default.key
sudo chown -R maddy:maddy /var/lib/maddy/dkim_keys

# Get the DNS record value
sudo maddy certs dkim dns /var/lib/maddy/dkim_keys/example.com_default.key
# Output: default._domainkey    TXT    "v=DKIM1; k=ed25519; p=..."

Create User Accounts

# Create a user
sudo maddyctl creds create user@example.com
# Enter password when prompted

# Create IMAP storage for the user
sudo maddyctl imap-acct create user@example.com

# List users
sudo maddyctl creds list

DNS Records

# MX record
example.com.    MX    10    mail.example.com.

# A record
mail.example.com.    A    your-server-ip

# SPF
example.com.    TXT    "v=spf1 mx -all"

# DKIM (from certs dkim dns output)
default._domainkey.example.com.    TXT    "v=DKIM1; k=ed25519; p=..."

# DMARC
_dmarc.example.com.    TXT    "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.com"

# MTA-STS
_mta-sts.example.com.    TXT    "v=STSv1; id=20250115"

Systemd Service

# /etc/systemd/system/maddy.service
[Unit]
Description=Maddy Mail Server
After=network.target

[Service]
Type=notify
User=maddy
Group=maddy
ExecStart=/usr/local/bin/maddy -config /etc/maddy/maddy.conf
Restart=on-failure
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now maddy

Testing

# Test SMTP
swaks --to test@example.com --from sender@external.com --server mail.example.com

# Test sending
swaks --to external@gmail.com --from user@example.com --server mail.example.com:587 --auth LOGIN --auth-user user@example.com --tls

# Check deliverability
# Send to check@mail-tester.com and review score

Best Practices

  • Use SQLite for small deployments (under 50 users); switch to PostgreSQL for larger ones
  • Set up log rotation for /var/log/maddy/
  • Monitor mail queue: maddyctl queue list
  • Keep Maddy updated — it is actively developed with security fixes
  • Use fail2ban or Maddy's built-in rate limiting for brute-force protection
  • Back up /var/lib/maddy/ regularly (contains credentials, mail, and DKIM keys)

Was this article helpful?