Enabling proper mail for runbsd.eu (OpenBSD + Postfix + Dovecot + OpenDKIM)
Posted on zo 16 november 2025 in runbsd
On the list of things that should work on OpenBSD in my runbsd.eu project, e-mail is somewhere on the top. This is where the project helps to do stuff on OpenBSD. Because for normal use, I outsourced most of the e-mail server tasks to Soverin. And that works fine.
But the idea for the RunBSD hobby project is to run as much as possible on BSD. Using some unknown mailplatform would not be a good fit.
So I'm going to host the mail on my OpenBSD.Amsterdam virtual machine. The VM is now renamed to petpuffy.runbsd.eu, to fit in to the new project nicely. This virtual server, for most part, only serves this static website up till now. So handling a couple of e-mails should pose no issue at all.
Toolchain
This setup will consist of OpenBSD running Postfix, Dovecot and opendkim.
I already received feedback on the choice for postfix. Maybe in the future I will try the OpenBSD native mailer OpenSMTPD instead :-)
Cleaning up my own mess
As I started working on the VM, there already was an installation of postfix. Apparently past self had started installing postfix on the machine, got distracted and left it at that. So I found out the host has been trying to deliver over 700 system messages, but all was pretty much broken.
Before starting to fix stuff, I made sure the complete set of mails in the postfix queue got permanently deleted.
Getting postfix back to work
With the queue cleaned up, I started looking at errors in the logging and applying fixes for these errors. Soon enough the postfix install was somewhat in a usable state. Mails got go in and out and were being delivered.
Configuring Dovecot
The dovecot package was also already installed, but in a misconfigured state. So that took some trial and error to get on its feet again. But it worked out
Internet.nl testing
This is where de loop starting of testing the mailserver config with Internet.nl, applying fixes and re-running the tests. There were al sorts of things missing and/or misconfigured. This Internet.nl tool is so darn useful!
The end result:

Postfix /etc/postfix/main.cf
The settings and relevant context came trom a whole list of sites, I will list most of them at the bottom.
main.cf with commented lines removed:
smtpd_banner = ESMTP
biff = no
append_dot_mydomain = no
compatibility_level = 3.8
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
data_directory = /var/postfix
home_mailbox = Maildir/
sendmail_path = /usr/local/sbin/sendmail
newaliases_path = /usr/local/sbin/newaliases
mailq_path = /usr/local/sbin/mailq
html_directory = /usr/local/share/doc/postfix/html
manpage_directory = /usr/local/man
sample_directory = /etc/postfix
readme_directory = /usr/local/share/doc/postfix/readme
shlib_directory = no
meta_directory = /etc/postfix
smtpd_tls_cert_file=/etc/ssl/runbsd_eu-tls.crt
smtpd_tls_key_file=/etc/ssl/private/runbsd_eu-tls.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:/smtpd_scache
smtp_tls_session_cache_database = btree:/smtp_scache
smtpd_tls_protocols = TLSv1.3, !TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_protocols = TLSv1.3, !TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_exclude_ciphers = aNULL, eNULL, MD5,EXPORT,DES,RC4,CAMELLIA256-SHA,ECDHE-ECDSA-DES-CBC3-SHA,ECDHE-RSA-DES-CBC3-SHA,DHE-RSA-DES-CBC3-SHA,AES256-GCM-SHA384,AES128-GCM-SHA256,AES256-SHA256,AES256-SHA,AES128-SHA256,AES128-SHA,DES-CBC3-SHA,ADH-AES256-GCM-SHA384
smtp_tls_exclude_ciphers = aNULL, eNULL, MD5,EXPORT,DES,RC4,CAMELLIA256-SHA,ECDHE-ECDSA-DES-CBC3-SHA,ECDHE-RSA-DES-CBC3-SHA,DHE-RSA-DES-CBC3-SHA,AES256-GCM-SHA384,AES128-GCM-SHA256,AES256-SHA256,AES256-SHA,AES128-SHA256,AES128-SHA,DES-CBC3-SHA,ADH-AES256-GCM-SHA384
smtpd_tls_mandatory_exclude_ciphers = aNULL, eNULL, MD5,EXPORT,DES,RC4,CAMELLIA256-SHA,ECDHE-ECDSA-DES-CBC3-SHA,ECDHE-RSA-DES-CBC3-SHA,DHE-RSA-DES-CBC3-SHA,AES256-GCM-SHA384,AES128-GCM-SHA256,AES256-SHA256,AES256-SHA,AES128-SHA256,AES128-SHA,DES-CBC3-SHA,ADH-AES256-GCM-SHA384
smtpd_tls_mandatory_protocols = TLSv1.3, !TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_protocols = TLSv1.3, !TLSv1.2, !TLSv1.1, !TLSv1, !SSLv2, !SSLv3
smtp_tls_mandatory_ciphers = high
smtpd_tls_mandatory_ciphers = high
tls_preempt_cipherlist = yes
smtpd_tls_eecdh_grade = ultra
smtpd_tls_dh1024_param_file = /etc/postfix/dh4096.pem
smtpd_tls_loglevel = 1
smtp_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:/var/postfix/smtpd_tls_session_cache
smtp_tls_session_cache_database = btree:/var/postfix/smtp_tls_session_cache
smtpd_client_connection_rate_limit = 50
smtpd_client_message_rate_limit = 100
anvil_rate_time_unit = 60s
smtp_tls_note_starttls_offer = yes
mail_owner = _postfix
setgid_group = _postdrop
canonical_maps = hash:/etc/postfix/canonical
smtpd_helo_required = yes
smtpd_helo_restrictions =
permit_mynetworks,
reject_invalid_helo_hostname,
reject_non_fqdn_helo_hostname
smtpd_sender_restrictions =
permit_mynetworks,
reject_non_fqdn_sender,
reject_unknown_sender_domain,
reject_unauth_pipelining
smtpd_recipient_restrictions =
permit_mynetworks,
reject_unauth_destination,
reject_non_fqdn_recipient,
reject_unknown_recipient_domain
smtpd_relay_restrictions = permit_mynetworks defer_unauth_destination
myhostname = petpuffy.runbsd.eu
alias_maps = hash:/etc/postfix/aliases
alias_database = hash:/etc/postfix/aliases
mydestination = runbsd.eu, localhost
unknown_local_recipient_reject_code = 550
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = all
smtp_tls_wrappermode = no
smtp_tls_security_level = encrypt
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept
DNS changes
To fix certain Internet.nl tests, I set up CAA, DKIM, DANE and TLSA records


Dovecot changes
Dovecot was configured to use the common TLS key/cert and configured to work as submission proxy. The users in this
particular setup are actual local users, so no virtual accounts are used. Both postfix and Dovecot were configured to
expect to find mail for a user in its own homedir ~/Maildir. Pretty oldskool but perfectly simple for this scenario.
In /etc/dovecot/dovecot.conf:
protocols = imap lmtp submission
(no need for pop3 support)
In /etc/dovecot/conf.d/20-submission.conf:
submission_relay_host = 127.0.0.1
In /etc/dovecot/conf.d/10-auth.conf:
auth_mechanisms = plain login
!include auth-system.conf.ext
In /etc/dovecot/conf.d/10-mail.conf:
mail_location = maildir:~/Maildir
In /etc/dovecot/conf.d/10-ssl.conf:
ssl = required
ssl_cert = </etc/ssl/runbsd_eu-tls.crt
ssl_key = </etc/ssl/private/runbsd_eu-tls.key
Creating Maildir
To create maildirs I tried maildirmake, but it was not installed. It appears to be part of the courier-imap package. So I installed this package without using/enabling the courier-imap services.
cd ~eelco
maildirmake Maildir
chown -R eelco Maildir/
OpenDKIM configuration
Opendkim was installed using pkg_add opendkim
The opendkim.conf was changed as follows:
bash-5.3# grep -v ^# /etc/opendkim.conf | grep -v ^$
AuthservID runbsd.eu
Domain example.com
KeyTable /etc/opendkim/KeyTable
Selector my-selector-name
SigningTable /etc/opendkim/SigningTable
Socket inet:8891@localhost
Syslog Yes
Domain runbsd.eu
Then I created the /etc/opendkim directory and created various files:
/etc/opendkim/KeyTable:
default._domainkey.runbsd.eu runbsd.eu:default:/etc/opendkim/runbsd.eu/default.private
/etc/opendkim/SigningTable:
*@runbsd.eu default._domainkey.runbsd.eu
Then a key was generated and the permissions were fixed:
opendkim-genkey -b 1024 -d runbsd.eu -D /etc/opendkim/runbsd.eu -s default -v
chown -R _opendkim:_opendkim /etc/opendkim/runbsd.eu/
lastly the service was enabled and started:
rcctl enable opendkim
rcctl start opendkim
Getting DANE / TLSA right
Ok this was somewhat of a hassle to get right. I had no real experience setting this up, so ik took some time to find proper tools and examples. These are listed below, but the Bovenender.de blogpost on the subject was the most useful starting point for me.
The TransIP webinterface is not the best tool for this job, but it works:

Acknowledgements
This would have been a lot more work without the various bits and pieces I found on the Internet. First and foremost, I love the Internet.nl test tooling for both websites and mailservers. It provides great feedback. Internet.nl
Then in order of my open tabs:
- https://webhosting.de/en/postfix-configuration-maximum-security-expert-guide/
- https://kruyt.org/postfix-and-tls-encryption/
- https://usercomp.com/news/1163075/postfix-3-7-openssl-3-dh-parameters
- https://www.openbsdhandbook.com/networking_and_daemons/services/mail/dovecot/
- https://bobcares.com/blog/postfix-delete-mail-queue/
- https://easydmarc.com/blog/how-to-configure-dkim-opendkim-with-postfix/
- https://letsencrypt.org/docs/caa/
- https://www.transip.nl/knowledgebase/857-een-tlsa-record-instellen/
- https://www.huque.com/bin/gen_tlsa
- https://www.sidn.nl/en/modern-internet-standards/hands-on-implementing-dane-in-postfix
- https://www.bovender.de/posts/2024/10/create-or-renew-tlsa-records/
- https://dnssec-stats.ant.isi.edu/~viktor/x3hosts.html