Personal mail server on OpenBSD
It’s time to host your email yourself!
A step-by-step guide for installing and configuring a mail server on OpenBSD.
As most of the entries in this blog, this is more of a reminder for me in case I need to do it again. But I publish it in the hope it might be useful to someone planning to do the same thing.
This was done with OpenBSD 6.4.
The stack
Let’s begin with a description of the stack and what we’re going to use:
- OS: OpenBSD. Stable, secure, perfect for hosting email, a precious thing in this day and age
- SMTP: Opensmtpd. A clean codebase with a sane config file.
- IMAP: Dovecot. Never used anything else anyway.
- DKIM: Dkimproxy. Works nicely with opensmtpd.
- SPAM: Spamd.
OS
The server
Ok the first thing to do is to get a hand on an OpenBSD server. If you already have one, great. If not, do like me, get one from Vultr.com. If you use this link you’ll get $10, so about 2 months free!
Also, Vultr.com is one of the few VPS provider supporting OpenBSD. Another one would be OpenBSD.amsterdam.
The cheapest offer of Vultr.com is more than enough for an email server.
First steps on the server
Once you get the IP address of your server, check to see if the IP is not blacklisted with this tool. If it is, ask for a new server. If not, go on.
Now to connect to it, edit your ssh config file and add an entry where <hostname>
is the name of the instance and <ip>
its IP address.
File: ~/.ssh/config
Host <hostname>
Hostname <ip>
Now connect:
ssh root@<hostname>
tmux
Set source for packages, use a mirror close to the server’s location:
File: /etc/installurl
https://ftp.fr.openbsd.org/pub/OpenBSD/
Patch the system and reboot:
syspatch -c
reboot
# wait for reboot
ssh root@<hostname>
Fix time:
ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime
Install the essentials
pkg_add -v vim zsh git htop unzip cmake
# select vim no x11 python3 (10)
# select unzip iconv (2)
Dotfiles install (skip this if you’re not me)
git clone --recursive https://github.com/NicolasCARPi/.dotfiles
./.dotfiles/install.sh
vim ~/.vim/vimrc
# set g:ycm_server_python_interpreter to /usr/local/bin/python3
# close vim
vim
:PluginInstall
# finish YCM install
cd ~/.vim/plugins/YouCompleteMe
python3 install.py
# remove the --color=auto from zshrc and fix path in git_prompt plugin in zsh folder
Configure SSH
In the file /etc/ssh/sshd_config
, change the port to something other than 22, preferably > 10000.
rcctl reload sshd
Add your user
Enough with root already, let’s add a user:
adduser
# login groups: <username> staff
Allow member of staff to execute commands as root:
File: /etc/doas.conf
permit setenv { -ENV PS1=$DOAS_PS1 SSH_AUTH_SOCK } :staff
Disconnect from server.
On your host, edit ~/.ssh/config
and add a line Port <port>
for the server. Add a line User <user>
if your local user is different from the one you created on the server.
Copy your public key to the server:
ssh-copy-id -i ~/.ssh/id_ed25519.pub <hostname>
ssh <hostname>
Repeat the dotfiles step.
Edit /etc/ssh/sshd_config
and set “EnableRootLogin” to no; doas rcctl reload sshd
.
DNS
Add AAAA and A pointing to IP of the server.
Add MX ponting to <domain>.
(point at the end!)
OpenSMTPD
Good news, you don’t have to install it as it’s shipped with the base, how great is that! :)
Here is my config file (/etc/mail/smtpd.conf
), adapt to your needs:
# $OpenBSD: smtpd.conf,v 1.11 2018/06/04 21:10:58 jmc Exp $
# configure TLS
pki <domain> key "/etc/letsencrypt/live/<domain>/privkey.pem"
pki <domain> cert "/etc/letsencrypt/live/<domain>/fullchain.pem"
# aliases table
table aliases file:/etc/mail/aliases
# listen directives
listen on all tls hostname <domain>
listen on all port 587 hostname <domain> tls pki <domain> auth
listen on lo0 port 10028 tag DKIM
# send mail to maildir ~/.mail for local accounts in alias table
action "local" maildir "%{user.directory}/.mail" alias <aliases>
action "relay" relay helo <domain>
action "relay_dkim" relay host smtp://127.0.0.1:10027
# <domain>
match from any for domain "<domain>" action "local"
# local
match for local action "local"
# dkim
match tag DKIM for any action "relay"
##match auth from any for any action "relay"
match auth from any for any action "relay_dkim"
TLS
For getting a certificate for the domain, we will use acme-client, shipped with OpenBSD.
acme-client -ADv <domain>
Dovecot
pkg_add dovecot
There is an issue with dovecot triggering the max open files limit, so let’s fix that first.
File: /etc/sysctl.conf
kern.maxfiles=102400
File: /etc/login.conf
dovecot:\
:openfiles-cur=1024:\
:openfiles-max=2048:\
:tc=daemon:
Now let’s tweak the base config of Dovecot to our liking.
cd /etc/dovecot/conf.d
File: 10-mail.conf
mail_location = maildir:~/.mail
File: 10-ssl.conf
ssl_cert
ssl_key
ssl_dh_parameters_length = 2048
rcctl enable dovecot
rcctl start dovecot
DKIMProxy
Sign the outgoing emails with DKIM or expect going to the spam folder…
pkg_add dkimproxy
File: /etc/dkimproxy_out.conf
listen 127.0.0.1:10027
relay 127.0.0.1:10028
domain <domain>
signature dkim(c=relaxed)
keyfile /etc/mail/private.key
selector mail
Generate the private/public keys for DKIM:
cd /etc/mail
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -out public.key
rcctl enable dkimproxy_out
rcctl start dkimproxy_out
Spamd
I don’t use it (yet).
ENJOY!
~Nico