Deployment guide

Maddy

Overview

Maddy is a composable, all-in-one mail server. It replaces the traditional stack of separate SMTP, submission, IMAP and authentication daemons with a single self-contained Go binary. In one process, it is a Mail Transfer Agent, a Mail Submission Agent, an IMAP server and a local authentication and DKIM engine. You configure it entirely from one plain-text file.

This image installs Maddy 0.9.5 from the official prebuilt release tarball. It runs under systemd as an unprivileged maddy user with only the CAP_NET_BIND_SERVICE capability, so it can bind the standard privileged mail ports.

Maddy accepts inbound mail as an MX on port 25. It offers authenticated message submission over implicit TLS on port 465 and STARTTLS on port 587. It serves mailboxes over IMAP with implicit TLS on port 993 and STARTTLS on port 143. There is no web interface. The configuration (/etc/maddy/maddy.conf) and the maddy command line are the whole management surface. Mail and hashed credentials are stored in an embedded database on a dedicated data disk.

Secure by default, with no shared credentials. The image ships with no mailbox and no password of any kind. On the first boot of every VM, a one-shot service generates a fresh per-instance self-signed TLS certificate and sets the server hostname and primary domain to this instance. It also creates a single administrator mailbox with a strong random password, written to a root-only file. Submission and IMAP both require authentication, and the server rejects an unauthenticated submission. The server is configured as an MX for your own domains, not as an open relay.

What you get:

  • Maddy 0.9.5 from the official prebuilt release binary, run under systemd as the unprivileged maddy user (maddy.service)
  • An SMTP MTA on port 25, authenticated submission on ports 465 (implicit TLS) and 587 (STARTTLS), and IMAP on ports 993 (implicit TLS) and 143 (STARTTLS)
  • A single administrator mailbox and a strong random password generated on first boot and stored in /root/maddy-credentials.txt (mode 0600), so no credential ships in the image
  • A per-instance self-signed TLS certificate generated on first boot, ready to be replaced with a certificate for your real domain
  • Mail and hashed credentials stored in an embedded SQLite database on a dedicated data disk at /var/lib/maddy, cleanly separated from the operating system disk
  • The whole configuration in one readable file, /etc/maddy/maddy.conf, and mailbox management with the simple maddy command line

Prerequisites

  • An active Azure subscription, an SSH public key, and a virtual network and subnet in your target region.
  • A subscription to the Maddy Mail Server listing on Azure Marketplace.
  • Network security group (NSG) rules that allow TCP 22 (admin), TCP 25 (inbound mail, if you receive mail for your domain), and TCP 465, 587, 993 and 143 (submission and IMAP for your mail clients).
  • For a production mail server, a domain you control, with the ability to publish MX, SPF, DKIM, DMARC and reverse DNS records.

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) is ample for a small mailbox server. Increase the size for higher mailbox counts or message throughput.

1

Deploy from the Azure Portal

Search the Marketplace for Maddy Mail Server, select the SecureAnyCloud publisher, and choose Create.

Configure the network security group to allow TCP 22 for administration, and TCP 465, 587, 993 and 143 for submission and IMAP from your mail clients. Also allow TCP 25 if this server will receive mail for your domain. Give the VM a public IP if it needs to send or receive mail from the internet.

2

Deploy from the Azure CLI

Create the resource group and the VM from the image with the Azure CLI.

RG="mail-prod"; LOCATION="eastus"; VM_NAME="maddy1" IMAGE_URN="sac1647283583153:maddy-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:maddy-ubuntu-24-04:default:latest
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$IMAGE_URN" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 465 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 993 --priority 1002
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1003

If your clients or senders need them, open ports 587, 143 and 25 as well.

3

First boot and the admin mailbox

On first boot, the image sets the server hostname and primary domain to this VM's hostname and generates a per-instance self-signed TLS certificate. It creates the administrator mailbox admin@<hostname> with a strong random password, writes the credentials to /root/maddy-credentials.txt and starts maddy. This completes within seconds.

Connect over SSH as azureuser and read the credentials.

sudo cat /root/maddy-credentials.txt

The file is 0600 root:root. It holds the admin mailbox address, the per-instance password, the primary domain, and the submission and IMAP endpoints. This is the only place the password exists, so store it somewhere safe.

4

Confirm the service is running

Check that maddy.service is active, that maddy version reports 0.9.5, and that ss shows Maddy listening on the mail ports. Port 25 is for SMTP, 465 and 587 are for submission, and 993 and 143 are for IMAP.

systemctl is-active maddy.service maddy version
sudo ss -tlnp | grep -E ':25 |:465 |:587 |:993 |:143 '
5

Send and receive a test message

You can prove the mail path end to end without any external DNS. Submit a message as the admin mailbox and retrieve it over IMAP.

The image ships a small helper that does this for you. It authenticates to the submission port over TLS, sends a message to the admin mailbox, then retrieves it over IMAP and checks the body. It also confirms that the server rejects an unauthenticated submission and a wrong IMAP password.

sudo python3 /opt/maddy/roundtrip-check.py

A successful run prints a single OK line. It confirms that the authenticated submission was delivered and retrieved over IMAP, and that unauthenticated access was refused.

To connect a real mail client, use the admin mailbox address as the username and the per-instance password. Use your server address with port 465 (implicit TLS) or 587 (STARTTLS) for sending, and port 993 (implicit TLS) or 143 (STARTTLS) for IMAP. The shipped certificate is self-signed, so either install your own certificate (Step 7) or allow the self-signed certificate in your client for testing.

6

Review the configuration and authentication model

Everything Maddy does is configured in one file, /etc/maddy/maddy.conf. The submission and IMAP endpoints both reference the local authentication database, so both require credentials. Credentials are hashed in an embedded database and managed with the maddy creds command. There is no shared or default account.

sudo grep -E 'auth |submission |imap |storage.imapsql|auth.pass_table' /etc/maddy/maddy.conf
sudo -u maddy maddy creds list
7

Set your real domain and TLS certificate

For production, change the hostname and primary domain in the configuration to a domain you own, then install a real TLS certificate. The example below uses <your-domain> and <mx-hostname>. Replace both with your own values.

# 1) edit /etc/maddy/maddy.conf and set:
# $(hostname) = <mx-hostname> e.g. mx1.example.org
# $(primary_domain) = <your-domain> e.g. example.org
# 2) install a certificate for <mx-hostname> at:
# /etc/maddy/certs/<mx-hostname>/fullchain.pem
# /etc/maddy/certs/<mx-hostname>/privkey.pem
# (for example with certbot, then copy or symlink the files and make them
# readable by the maddy user), then apply the change:
sudo systemctl restart maddy

Maddy reloads TLS certificates from disk automatically, so it picks up certificate renewals without downtime. Point your registrar and DNS at this instance as described in Step 9.

8

Add mailboxes

Each mailbox needs a credential and a matching IMAP storage account. Usernames are full email addresses. Create both for every mailbox you add.

# create a credential (you will be prompted for a password), then the IMAP account:
sudo -u maddy maddy creds create you@<your-domain>
sudo -u maddy maddy imap-acct create you@<your-domain>

Remove a mailbox with maddy creds remove and maddy imap-acct remove. Run maddy creds --help and maddy imap-acct --help to see all subcommands.

9

Publish DNS records for delivery

A public mail server needs correct DNS to send and receive reliably. For the domain you set in Step 7, publish these records:

  • An MX record for <your-domain> pointing at <mx-hostname>, and an A record for <mx-hostname> pointing at this VM's public IP.
  • An SPF record that authorises this server to send for your domain.
  • A DKIM record. Maddy generates a DKIM key for your domain on first outbound signing, so publish the public key it produces.
  • A DMARC record for your policy.
  • A reverse DNS (PTR) record for the VM's public IP, matching <mx-hostname>. Most receivers require it for delivery.

Set reverse DNS for an Azure public IP on the IP resource, not in your own DNS zone.

10

Security recommendations

Restrict the NSG to your use case. Allow submission (465, 587) and IMAP (993, 143) only from the networks your clients use. Open port 25 only if this server receives mail for your domain.

Replace the self-signed certificate. The shipped certificate is per-instance and self-signed, for immediate testing. Install a certificate for your real hostname (Step 7) so clients and other mail servers trust the connection.

Keep authentication required. Submission and IMAP require credentials by default. Do not disable authentication, and use strong per-mailbox passwords.

Protect the credentials file. /root/maddy-credentials.txt is 0600 root:root. Keep it restricted, and rotate the admin password with maddy creds password if it is ever exposed.

Keep the OS patched. Unattended security upgrades remain enabled on the running VM.

11

Support and Licensing

Maddy Mail Server is an open-source project distributed under the GNU General Public License v3.0. This image bundles the unmodified official Maddy release binary.

SecureAnyCloud provides the packaging, the systemd hardening and the secure-by-default configuration. It also provides the per-instance first-boot provisioning of the domain, certificate and admin mailbox, this deployment guide, and 24/7 support with a guaranteed 24-hour response SLA.

SecureAnyCloud is not affiliated with or endorsed by the Maddy project. Maddy is a mark of its respective owner and is used here only to identify the software.

Deploy on Azure

Find Maddy Mail Server on Ubuntu 24.04 LTS on the Azure Marketplace, published by SecureAnyCloud. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email sales@secureanycloud.com for deployment help, configuration questions or licensing enquiries.

Deploy on Azure

Launch Maddy Mail Server 0.9.5 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure