diff --git a/maddy/Makefile b/maddy/Makefile new file mode 100644 index 0000000..8fa6a21 --- /dev/null +++ b/maddy/Makefile @@ -0,0 +1,62 @@ +.PHONY: control + +VERSION=0.6.2 +BASENAME=maddy + +help: + @echo + @echo "make all # to attempt to download, extract and build the .deb package using dpkg" + @echo + +all: download clean extract DEBIAN build + +# uses 'ar' to make a .deb file +raw: download clean extract DEBIAN tar-ar + +clean: + rm -rf ../files + rm -f ../*.deb + rm -f ../*.tar.xz data.tar.xz + rm -rf DEBIAN + +download: + @echo + @echo This uses the binary /usr/local/bin/maddy + @echo + +extract: + cp -a files ../ + mkdir -p ../files/usr/bin + cp /usr/local/bin/maddy ../files/usr/bin + +# makes the DEBIAN/ directory +DEBIAN: + mkdir -p DEBIAN + + # make the md5sum file + cd ../files/ && find -type f -exec md5sum '{}' \; |sort -k2 >../md5sums + mv ../md5sums DEBIAN/ + + # make the control there + mkdir -p DEBIAN + cp control DEBIAN/ + # echo Version: ${VERSION} >>DEBIAN/control + + cp postinst DEBIAN + +build: + mv DEBIAN ../files/ + cd .. && dpkg-deb --build files ${BASENAME}_${VERSION}_amd64.deb + cd .. && dpkg-deb --info ${BASENAME}_${VERSION}_amd64.deb + +# how to make a debian package "raw" just using tar and ar +# +# READ THIS AGAIN: +# +# A .deb file is just output from 'ar rcs' +# +tar-ar: control + cd DEBIAN && tar --ignore-failed-read -cvJf ../control.tar.xz . + cd files && tar -cvJf ../data.tar.xz . + ar rcs ${BASENAME}_${VERSION}_amd64.deb debian-binary control.tar.xz data.tar.xz + dpkg-deb --info ${BASENAME}_${VERSION}_amd64.deb diff --git a/maddy/compat b/maddy/compat new file mode 100644 index 0000000..f599e28 --- /dev/null +++ b/maddy/compat @@ -0,0 +1 @@ +10 diff --git a/maddy/control b/maddy/control new file mode 100644 index 0000000..2b44b02 --- /dev/null +++ b/maddy/control @@ -0,0 +1,16 @@ +Source: maddy +Build-Depends: golang +Package: maddy +Version: 0.6.2 +Maintainer: Jeff Carr +Architecture: any +Depends: +Description: A modern mail server written in GO + Maddy Mail Server implements all functionality required to run a e-mail server. + It can send messages via SMTP (works as MTA), accept messages via SMTP (works as MX) + and store messages while providing access to them via IMAP. In addition to + that it implements auxiliary protocols that are mandatory to keep email reasonably + secure (DKIM, SPF, DMARC, DANE, MTA-STS). + . + It replaces Postfix, Dovecot, OpenDKIM, OpenSPF, OpenDMARC and more + with one daemon with uniform configuration and minimal maintenance cost. diff --git a/maddy/files/etc/maddy/maddy.conf b/maddy/files/etc/maddy/maddy.conf new file mode 100644 index 0000000..3e285a3 --- /dev/null +++ b/maddy/files/etc/maddy/maddy.conf @@ -0,0 +1,181 @@ +## Maddy Mail Server - default configuration file (2022-06-18) +# Suitable for small-scale deployments. Uses its own format for local users DB, +# should be managed via maddyctl utility. +# +# See tutorials at https://maddy.email for guidance on typical +# configuration changes. + +# ---------------------------------------------------------------------------- +# Base variables + +$(hostname) = example.org +$(primary_domain) = example.org +$(local_domains) = $(primary_domain) + +tls file /etc/maddy/certs/$(hostname)/fullchain.pem /etc/maddy/certs/$(hostname)/privkey.pem + +# ---------------------------------------------------------------------------- +# Local storage & authentication + +# pass_table provides local hashed passwords storage for authentication of +# users. It can be configured to use any "table" module, in default +# configuration a table in SQLite DB is used. +# Table can be replaced to use e.g. a file for passwords. Or pass_table module +# can be replaced altogether to use some external source of credentials (e.g. +# PAM, /etc/shadow file). +# +# If table module supports it (sql_table does) - credentials can be managed +# using 'maddyctl creds' command. + +auth.pass_table local_authdb { + table sql_table { + driver sqlite3 + dsn credentials.db + table_name passwords + } +} + +# imapsql module stores all indexes and metadata necessary for IMAP using a +# relational database. It is used by IMAP endpoint for mailbox access and +# also by SMTP & Submission endpoints for delivery of local messages. +# +# IMAP accounts, mailboxes and all message metadata can be inspected using +# imap-* subcommands of maddyctl utility. + +storage.imapsql local_mailboxes { + driver sqlite3 + dsn imapsql.db +} + +# ---------------------------------------------------------------------------- +# SMTP endpoints + message routing + +hostname $(hostname) + +table.chain local_rewrites { + optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3" + optional_step static { + entry postmaster postmaster@$(primary_domain) + } + optional_step file /etc/maddy/aliases +} + +msgpipeline local_routing { + # Insert handling for special-purpose local domains here. + # e.g. + # destination lists.example.org { + # deliver_to lmtp tcp://127.0.0.1:8024 + # } + + destination postmaster $(local_domains) { + modify { + replace_rcpt &local_rewrites + } + + deliver_to &local_mailboxes + } + + default_destination { + reject 550 5.1.1 "User doesn't exist" + } +} + +smtp tcp://0.0.0.0:25 { + limits { + # Up to 20 msgs/sec across max. 10 SMTP connections. + 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_routing + } + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } +} + +submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { + limits { + # Up to 50 msgs/sec across any amount of SMTP connections. + all rate 50 1s + } + + auth &local_authdb + + source $(local_domains) { + check { + authorize_sender { + prepare_email &local_rewrites + user_to_email identity + } + } + + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + modify { + dkim $(primary_domain) $(local_domains) default + } + deliver_to &remote_queue + } + } + default_source { + reject 501 5.1.8 "Non-local sender domain" + } +} + +target.remote outbound_delivery { + limits { + # Up to 20 msgs/sec across max. 10 SMTP connections + # for each recipient domain. + destination rate 20 1s + destination concurrency 10 + } + mx_auth { + dane + mtasts { + cache fs + fs_dir mtasts_cache/ + } + local_policy { + min_tls_level encrypted + min_mx_level none + } + } +} + +target.queue remote_queue { + target &outbound_delivery + + autogenerated_msg_domain $(primary_domain) + bounce { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" + } + } +} + +# ---------------------------------------------------------------------------- +# IMAP endpoints + +imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { + auth &local_authdb + storage &local_mailboxes +} diff --git a/maddy/files/lib/systemd/system/maddy.service b/maddy/files/lib/systemd/system/maddy.service new file mode 100644 index 0000000..0f5ace2 --- /dev/null +++ b/maddy/files/lib/systemd/system/maddy.service @@ -0,0 +1,81 @@ +[Unit] +Description=maddy mail server +Documentation=man:maddy(1) +Documentation=man:maddy.conf(5) +Documentation=https://maddy.email +After=network.target + +[Service] +Type=notify +NotifyAccess=main + +User=maddy +Group=maddy + +# cd to state directory to make sure any relative paths +# in config will be relative to it unless handled specially. +WorkingDirectory=/var/lib/maddy + +ConfigurationDirectory=maddy +RuntimeDirectory=maddy +StateDirectory=maddy +LogsDirectory=maddy +ReadOnlyPaths=/usr/lib/maddy +ReadWritePaths=/var/lib/maddy + +# Strict sandboxing. You have no reason to trust code written by strangers from GitHub. +PrivateTmp=true +ProtectHome=true +ProtectSystem=strict +ProtectKernelTunables=true +ProtectHostname=true +ProtectClock=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 + +# Additional sandboxing. You need to disable all of these options +# for privileged helper binaries (for system auth) to work correctly. +NoNewPrivileges=true +PrivateDevices=true +DeviceAllow=/dev/syslog +RestrictSUIDSGID=true +ProtectKernelModules=true +MemoryDenyWriteExecute=true +RestrictNamespaces=true +RestrictRealtime=true +LockPersonality=true + +# Graceful shutdown with a reasonable timeout. +TimeoutStopSec=7s +KillMode=mixed +KillSignal=SIGTERM + +# Required to bind on ports lower than 1024. +AmbientCapabilities=CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_BIND_SERVICE + +# Force all files created by maddy to be only readable by it. +UMask=0027 + +# Bump FD limitations. Even idle mail server can have a lot of FDs open (think +# of idle IMAP connections, especially ones abandoned on the other end and +# slowly timing out). +LimitNOFILE=131072 + +# Limit processes count to something reasonable to +# prevent resources exhausting due to big amounts of helper +# processes launched. +LimitNPROC=512 + +# Restart server on any problem. +Restart=on-failure +# ... Unless it is a configuration problem. +RestartPreventExitStatus=2 + +ExecStart=/usr/local/bin/maddy run + +ExecReload=/bin/kill -USR1 $MAINPID +ExecReload=/bin/kill -USR2 $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/maddy/files/lib/systemd/system/maddy@.service b/maddy/files/lib/systemd/system/maddy@.service new file mode 100644 index 0000000..cc77682 --- /dev/null +++ b/maddy/files/lib/systemd/system/maddy@.service @@ -0,0 +1,77 @@ +[Unit] +Description=maddy mail server (using %i.conf) +Documentation=man:maddy(1) +Documentation=man:maddy.conf(5) +Documentation=https://maddy.email +After=network.target + +[Service] +Type=notify +NotifyAccess=main + +User=maddy +Group=maddy + +ConfigurationDirectory=maddy +RuntimeDirectory=maddy +StateDirectory=maddy +LogsDirectory=maddy +ReadOnlyPaths=/usr/lib/maddy +ReadWritePaths=/var/lib/maddy + +# Strict sandboxing. You have no reason to trust code written by strangers from GitHub. +PrivateTmp=true +PrivateHome=true +ProtectSystem=strict +ProtectKernelTunables=true +ProtectHostname=true +ProtectClock=true +ProtectControlGroups=true +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +DeviceAllow=/dev/syslog + +# Additional sandboxing. You need to disable all of these options +# for privileged helper binaries (for system auth) to work correctly. +NoNewPrivileges=true +PrivateDevices=true +RestrictSUIDSGID=true +ProtectKernelModules=true +MemoryDenyWriteExecute=true +RestrictNamespaces=true +RestrictRealtime=true +LockPersonality=true + +# Graceful shutdown with a reasonable timeout. +TimeoutStopSec=7s +KillMode=mixed +KillSignal=SIGTERM + +# Required to bind on ports lower than 1024. +AmbientCapabilities=CAP_NET_BIND_SERVICE +CapabilityBoundingSet=CAP_NET_BIND_SERVICE + +# Force all files created by maddy to be only readable by it. +UMask=0027 + +# Bump FD limitations. Even idle mail server can have a lot of FDs open (think +# of idle IMAP connections, especially ones abandoned on the other end and +# slowly timing out). +LimitNOFILE=131072 + +# Limit processes count to something reasonable to +# prevent resources exhausting due to big amounts of helper +# processes launched. +LimitNPROC=512 + +# Restart server on any problem. +Restart=on-failure +# ... Unless it is a configuration problem. +RestartPreventExitStatus=2 + +ExecStart=/usr/local/bin/maddy --config /etc/maddy/%i.conf run + +ExecReload=/bin/kill -USR1 $MAINPID +ExecReload=/bin/kill -USR2 $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/maddy/postinst b/maddy/postinst new file mode 100755 index 0000000..1a24852 --- /dev/null +++ b/maddy/postinst @@ -0,0 +1 @@ +#!/bin/sh