mserv provides a secure out of the box production quality mail server, utilizing postfix, dovecot and opendkim.
WARNING: mserv assumes that you are intending to run a bare domain mail server, meaning that you have your MX record set to the domain itself e.g.:
example.com. 300 IN MX 10 example.com.
- sasl auth is allowed only on submission{,s} ports, auth on smtp is rejected.
- dovecot only serves imap4, and does so only on tcp port 993.
- ingress messages are checked for dkim, egress is signed with.
- user spoofing is mitigated with postfix sender restictions and envelope sender mappings.
| component | version |
|---|---|
| docker base image | alpine:3.22.1 |
| postfix | 3.10.3 |
| dovecot | 2.4.1-4 (7d8c0e5759) |
| opendkim | v2.11.0 |
git clone --depth=1 https://github.com/gottaeat/mserv
cd mserv/_MYDOMAIN="example.com"
_MYPUBIP="1.1.1.1"mserv expects valid certs for $_MYDOMAIN to be present under
/etc/letsencrypt.
mkdir -pv ./data/config/{postfix,dovecot/keys,opendkim}echo "${_MYDOMAIN} 20080428" > data/config/postfix/virtual_mailbox_domainscreate as many users as necessary. admin is used here so we can alias
postmaster to it, can be arbitrary, just ensure that you alias postmaster to
it.
cat << EOF > data/config/postfix/virtual_mailbox_maps
admin@${_MYDOMAIN} ${_MYDOMAIN}/admin/
EOFcat << EOF > data/config/postfix/controlled_envelope_senders
admin@${_MYDOMAIN} admin@${_MYDOMAIN}
EOFthe postmaster alias is necessary.
cat << EOF > data/config/postfix/virtual_alias_maps
postmaster@${_MYDOMAIN} admin@${_MYDOMAIN}
EOFget the hashed password via docker compose run --rm -it mserv doveadm pw -s SHA512-CRYPT, edit the data/config/dovecot/userdb manually to avoid having
to escape the $ characters. the end result should look similar to:
admin@${_MYDOMAIN}:<hash_here>set the output as the DKIM record for your domain.
mkdir -pv data/config/opendkim/keys/"${_MYDOMAIN}"
docker compose run --rm -it mserv ash -c "
cd /opendkim/keys/${_MYDOMAIN}
opendkim-genkey -s mail -d ${_MYDOMAIN}
cat mail.txt"cat << EOF > data/config/opendkim/KeyTable
mail._domainkey.${_MYDOMAIN} ${_MYDOMAIN}:mail:/opendkim/keys/${_MYDOMAIN}/mail.private
EOF
cat << EOF > data/config/opendkim/SigningTable
*@${_MYDOMAIN} mail._domainkey.${_MYDOMAIN}
EOF
cat << EOF > data/config/opendkim/TrustedHosts
127.0.0.1
localhost
${_MYDOMAIN}
${_MYPUBIP}
EOFadd the following records to your DNS:
_dmarc.${_MYDOMAIN}. 300 IN TXT "v=DMARC1; p=reject; rua=mailto:postmaster@${_MYDOMAIN}; ruf=mailto:postmaster@${_MYDOMAIN}; sp=reject; aspf=s; adkim=s; fo=1;"
${_MYDOMAIN}. 300 IN TXT "v=spf1 a mx ip4:${_MYPUBIP} ra=postmaster -all"edit docker-compose.yml and set the hostname: key to the value of
$_MYDOMAIN, then fire up the mail server with:
docker compose up -dyou can follow the steps for postfix and dovecot for adding and removing users
and aliases without bringing the container down. once the files are to your
liking, pop into the container via docker exec -it mserv ash and do:
for i in \
virtual_mailbox_domains \
controlled_envelope_senders \
virtual_mailbox_maps \
virtual_alias_maps; do
postmap "/postfix/${i}"
done
postfix reload
dovecot reload