[2026-01-31 Sat 19:05]
I wanted to see if it's possible to host a mail server from home on IPv6 (spoiler: nearly).
I added the following records to my DNS config:
Certbot is happy to generate a certificate for mail.
Config firewall to open TCP 25.
Then exim can't read certs because it's not root. That's ok kitnil has the solution for that, a hook on cert bot:
Next exim's email routing failed because it still isn't running as root and it is installed without setuid binaries so it can't gain root privileges. Which is good for security, but means we have to disable some functionality, namely checking a user's ~/.forward file before delivering email.
Then I setup dovecot with local lmtp delivery.
Exim config looks like this:
Dovecot service is a bit verbose but not complex, just make sure the lmtp ports match on both sides:
At this point I was able to receive email 🥳
Let's try to send some. I setup DMARC, SPF & DKIM:
btw now is a good time to mention that exim doc is very complete and you should refer to it every step of the way: 58. DKIM, SPF, SRS and DMARC
My DMARC, SPF & DKIM records in DNS:
DKIM is added to exim like so:
Aaaand all of this fails to send email because free (my internet provider) won't let you add PTR record on IPv6 and without one gmail & co just drop your email :'( This would work if you just wanted to interact with other self-hosted folk.
[2026-04-18 Sat 23:25]
Fallback to IPv4 then because free will let you add a PTR record for that.
So maxipass.at now has IPv6 & IPv4 web records, but mail is only advertised on IPv4 so it can get through to gmail & co.
I replaced the AAAA record with this one:
Then I had to convince exim to use only the local IPv4 that is forwarded as my public IP address by my router when sending email:
And now gmail deigns to talk to us.
You can dig through of-course-i-still-love-you.scm, mail.scm & exim.conf for the final result.
You can also send me an email so I didn't do all of this for nothing: webmaster@maxipass.at
I wanted to see if it's possible to host a mail server from home on IPv6 (spoiler: nearly).
I added the following records to my DNS config:
#+begin_example @ MX 10800 10 mail.maxipass.at.
mail AAAA 10800 2a01:e0a:b5a:de71::1#+end_exampleCertbot is happy to generate a certificate for mail.
Config firewall to open TCP 25.
Then exim can't read certs because it's not root. That's ok kitnil has the solution for that, a hook on cert bot:
#+begin_src scheme
(define exim-deploy-hook
(program-file
"exim-deploy-hook"
#~(begin
(unless (file-exists? "/etc/exim")
(mkdir "/etc/exim"))
(let* ((cert-directory (getenv "RENEWED_LINEAGE"))
(user (getpw "exim"))
(uid (passwd:uid user))
(gid (passwd:gid user)))
(copy-file (string-append cert-directory "/"
(readlink (string-append cert-directory "/fullchain.pem")))
"/etc/exim/exim.crt")
(copy-file (string-append cert-directory "/"
(readlink (string-append cert-directory "/privkey.pem")))
"/etc/exim/exim.pem")
(chown "/etc/exim" uid gid)
(chown "/etc/exim/exim.crt" uid gid)
(chown "/etc/exim/exim.pem" uid gid)
(invoke
#$(file-append psmisc "/bin/killall")
#$(file-append exim-content-scan "/bin/exim"))))))
;; ... which is then used like so:
(service certbot-service-type
(certbot-configuration
(certificates
(list
(certificate-configuration
(domains '("mail.maxipass.at"))
(deploy-hook exim-deploy-hook)) ;; <- here
(certificate-configuration
(domains '("maxipass.at" "www.maxipass.at")))))))#+end_srcNext exim's email routing failed because it still isn't running as root and it is installed without setuid binaries so it can't gain root privileges. Which is good for security, but means we have to disable some functionality, namely checking a user's ~/.forward file before delivering email.
#+begin_src conf
userforward:
driver = redirect
check_local_user
data = ""
no_verify
no_expn
check_ancestor
file_transport = address_file
pipe_transport = address_pipe
reply_transport = address_reply#+end_srcThen I setup dovecot with local lmtp delivery.
Exim config looks like this:
#+begin_src conf
local_user:
debug_print = "R: local_user for $local_part@$domain"
driver = accept
domains = +local_domains
check_local_user
transport = dovecot_lmtp
cannot_route_message = Unknown user
# ...
dovecot_lmtp:
driver = smtp
#allow suffixes/prefixes (default unset)
rcpt_include_affixes
protocol = lmtp
allow_localhost = true # <- this is important
hosts = 127.0.0.1
port = 2525#+end_srcDovecot service is a bit verbose but not complex, just make sure the lmtp ports match on both sides:
#+begin_src scheme
(service dovecot-service-type
(dovecot-configuration
(mail-location "maildir:~/.mail")
(services
(list
(service-configuration
(kind "imap-login")
(client-limit 0)
(process-limit 0)
(listeners
(list
(inet-listener-configuration (protocol "imaps")
(port 993)
(ssl? #t)))))
(service-configuration
(kind "lmtp")
(client-limit 1)
(process-limit 0)
(listeners
(list
(inet-listener-configuration (protocol "lmtp")
(port 2525)
(ssl? #f)))))
(service-configuration
(kind "auth")
(service-count 0)
(client-limit 0)
(process-limit 1)
(listeners
(list (unix-listener-configuration (path "auth-userdb")))))
(service-configuration
(kind "auth-worker")
(client-limit 1)
(process-limit 0))
(service-configuration
(kind "dict")
(client-limit 1)
(process-limit 0)
(listeners (list (unix-listener-configuration (path "dict")))))))
;; (mail-debug? #t) <-- helpful when mucking around
(auth-username-format "%n")
(protocols
(list (protocol-configuration
(name "lmtp"))
(protocol-configuration
(name "imap"))))))#+end_srcAt this point I was able to receive email 🥳
Let's try to send some. I setup DMARC, SPF & DKIM:
#+begin_src shell
openssl genrsa -out dkim.private.key 2048
openssl rsa -in dkim.private.key -out dkim.public.key -pubout -outform PEM#+end_srcbtw now is a good time to mention that exim doc is very complete and you should refer to it every step of the way: 58. DKIM, SPF, SRS and DMARC
My DMARC, SPF & DKIM records in DNS:
#+begin_example @ TXT 10800 "v=spf1 mx -all"
_dmarc TXT 10800 "v=DMARC1; p=quarantine; rua=mailto:webmaster@maxipass.at"
default._domainkey TXT 10800 "v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxG7jjFxmeSpkHQMQ2fKbMG2KTrGGELVT9G1n6rWRKVgYxMXKpf8FkJRDLqsg0f9cf1KcRlWtvDxb0X" "VZmjVz9Xe2mQw4YRMhdb4HtI27BJU6cuJ5MLRnQoj4aEpf1Qg8POFlVYSYuqpBprTXOH+BddmHSmIHQ4VhHuxqmQjn9i7fKdSofYX6PuQj9EoMvK5MTztnRlGYPJKphbwE2youqZxW/wtdT+Z/ucFR" "pWiB86IXmwHGHUSp24uzGcZIOR5HP3Sh7mfJ/vQNPkYStxruuA4zPiyyPfgAo/x0w5oQlkk0JCEznSMrEzLcT+MPbQFJwTZ5s9srVuxEhvi5X8t8iwIDAQAB"#+end_exampleDKIM is added to exim like so:
#+begin_src conf
remote_smtp:
driver = smtp
dkim_domain = maxipass.at
dkim_selector = default
dkim_private_key = /etc/exim/dkim.private.key
dkim_canon = relaxed
.ifdef _HAVE_TLS_RESUME
tls_resumption_hosts = *
.endif#+end_srcAaaand all of this fails to send email because free (my internet provider) won't let you add PTR record on IPv6 and without one gmail & co just drop your email :'( This would work if you just wanted to interact with other self-hosted folk.
[2026-04-18 Sat 23:25]
Fallback to IPv4 then because free will let you add a PTR record for that.
So maxipass.at now has IPv6 & IPv4 web records, but mail is only advertised on IPv4 so it can get through to gmail & co.
I replaced the AAAA record with this one:
#+begin_example mail.maxipass.at. 10800 IN A 82.65.216.189#+end_exampleThen I had to convince exim to use only the local IPv4 that is forwarded as my public IP address by my router when sending email:
#+begin_src conf
local_interfaces = <; 127.0.0.1 ; \
192.168.1.101 ; \ # public facing IP
10.42.0.7 # my vpn
# ...
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ipv4_only = true # <- (sad ipv6 noizes)
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
no_more
# ...
remote_smtp:
driver = smtp
dkim_domain = maxipass.at
dkim_selector = default
dkim_private_key = /etc/exim/dkim.private.key
dkim_canon = relaxed
.ifdef _HAVE_TLS_RESUME
tls_resumption_hosts = *
.endif
interface = 192.168.1.101 # <- this (also add this to smarthost_smtp if needed)#+end_srcAnd now gmail deigns to talk to us.
You can dig through of-course-i-still-love-you.scm, mail.scm & exim.conf for the final result.
You can also send me an email so I didn't do all of this for nothing: webmaster@maxipass.at