Full mail server with virtual users

"Virtual users" means they are not UNIX system users with a shell. However, they are obviously using your mail server.

New accounts won't be created with "adduser" but you will edit a file with the username and it's password hash.

Here we'll discuss how to install a SMTP (Opensmtpd) and IMAP (Dovecot) server

One user to rule them all : _vmail

We will create an user with the sweet name "_vmail" to manage every emails access. It won't have any shell, it's safer 😊.

# useradd -m -g =uid -c "Virtual Mail" -d /var/vmail -s /sbin/nologin _vmail

A new directory is created : /var/vmail. Emails will be stored inside, but following a structure with subdirectories for each virtual users. As example :

/var/vmail/athome.tld/batman/Maildir
/var/vmail/athome.tld/user/Maildir
/var/vmail/athome.tld/ninja/Maildir
...

/etc/mail/virtuals

In this file, we write user's emails, one on each line. Actually, it works like the file /etc/mail/aliases. (read man aliases(5) 😉)

heroes@athome.tld batman@athome.tld,superman@athome.tld
batman@athome.tld _vmail
superman@athome.tld _vmail
kiki@athome.tld _vmail

As you can see, every email addresses belongs to user _vmail.

Notice the first line : you see an example showing how to transfer emails sent to "heroes@athome.tld" to "batman@athome.tld" and "superman@athome.tld".

Notez que sur la première ligne, on a fait un alias à titre d'exemple pour transférer un mail d'une adresse à une autre.

/etc/mail/passwd

Same as before, one line per passphrase :

batman@athome.tld:$2b$09$lerdFpdQtnu.Bs5EpAsVbeF851GjdD0aza8IDhho38i1DOHk.ujzi
superman@athome.tld:$2b$09$VRU/CYJUS3QZHVUFP70xIOURPbiNQeyOEZHoZo6NOY3uO.XSpd2MW

Notice how ":" split email address and the hashed passphrase : <email>:<hash>.

To hash passphrases, use "encrypt" command :

encrypt -p

Or "smtpctl encrypt passphrase".

(Facultative) Fine tuning files permissions

Previous files shouldn't be readable by everyone. Let's adjust permissions so root and mail daemons -- dovecot and smtpd -- can read passwords. It is not mandatory, but I suggest this part as good habits that can hurt anyone 😉.

Dovecot and smtpd run as users _dovecot and _smtpd. If one day, one of this process is compromised, it will avoid privilege escalation and threaten the whole system.

Let's create a new group _maildaemons for _dovecot and _smtpd to ease permissions :

# groupadd _maildaemons
# usermod -G _maildaemons _smtpd
# usermod -G _maildaemons _dovecot

Of course, if you haven't installed dovecot yet since we discuss about it later : "# pkg_add dovecot".

Now we can set owner and group for files storing logins and passwords :

# chown root:_maildaemons /etc/mail/passwd /etc/mail/virtuals

Finally, only root can modify these files and _maildaemons can only read. Others can't do anything :

# chmod 640 /etc/mail/passwd /etc/mail/virtuals

To check everything is as expected :

# ls -l /etc/mail/passwd
-rw-r-----  1 root  _maildaemons  17226 Nov 12 08:40 /etc/mail/passwd

Opensmtpd (smtpd) config

Opensmtpd or smtpd is the default mail server shipped with OpenBSD. You just have to configure it.

First of all, make sure you opened thos ports : 25 (smtp), 587 (submission) and 993 (imaps). The latter will be user with dovecot. Do not care about 465 (smtps) since it is deprecated.

To configure smtpd, edit "/etc/mail/smtpd.conf". Instructions will be applied in order.

We will split it in 3 parts :

Adjust the example below to your needs :

# Generic configuration
## Tables 
table aliases "/etc/mail/aliases"
table passwd "/etc/mail/passwd"
table virtuals "/etc/mail/virtuals"
## Certificates
pki athome.tld key "/etc/ssl/private/athome.tld.key"
pki athome.tld cert "/etc/ssl/athome.tld.crt"
## Listening ports
### Reception
listen on all tls pki athome.tld 
### Sending with a mail client
listen on all port submission tls-require pki athome.tld auth <passwd> 
# ACTIONS 
action "sendthismail" relay 
action local_mail maildir alias <aliases>
action virtual_maildir maildir "/var/vmail/%{dest.domain:lowercase}/%{dest.user:lowercase}/Maildir" virtual <virtuals>
# In/Out
## Reception
### Message for virtual users
match from any for domain athome.tld action virtual_maildir
### Message for system users
match from any for local action local_mail
## Sending
match auth from any for any action "sendthismail"
match for any action "sendthismail"

There is almost nothing to change in this file, except domain name.

WAIIIIIT a minute! Tell me more!

Take a look at each lines :

First, there are generic instructions

Then, we define actions applied on envelopes.

At last, we apply actions according to envelope criterias.

If not mentioned, the rule is matching for a local mail. In other case, we add "from any".

Finally, in order to label your outgoing messages with the appropriate domain name, add in "/etc/mail/mailname" your email's domain name. It's the domain mentioned in the MX record.

athome.tld

Now enable and start smtpd :

# rcctl enable smtpd
# rcctl restart smtpd

That's all for 😊.

Dovecot

We will use Dovecot as IMAP server so you can read mails from a client like Thunderbird.

As usual, install dovecot with pkg_add :

# pkg_add dovecot

Now configure dovecot. Edit "/etc/dovecot/local.conf" :

# listen IPv4 and IPv6
listen = *, [::]
# imap
protocols = imap
# Encryption. Edit those lines according to your certificates.
ssl = yes
ssl_cert = </etc/ssl/athome.tld.crt
ssl_key = </etc/ssl/private/athome.tld.key
disable_plaintext_auth = yes
# where mails are stored. %d is domain, %n is username
mail_location = maildir:/var/vmail/%d/%n/Maildir
# essential since we edited persmission on /etc/mail/passwd
service auth {
    user = $default_internal_user
    group = _maildaemons
}
# Auth methodes
passdb {
    args = scheme=blf-crypt /etc/mail/passwd
    driver = passwd-file
}
# Mails are /var/vmail , belongs to _vmail
userdb {
    driver = static
    args = uid=_vmail gid=_vmail home=/var/vmail/%d/%n/ 
}

I left comments above to help you understand what is done here.

Adjust ssl_cert and ssl_key according to your certificates.

By the way, ssl configuration is already available in "/etc/dovecot/conf.d/10-ssl.conf". It is supposed to help up with a script generating a self-signed certificate. However, you probably already have your own. You should comment lines in this file :

## /etc/dovecot/conf.d/10-ssl.conf
#ssl_cert = </etc/ssl/dovecotcert.pem
#ssl_key = </etc/ssl/private/dovecot.pem

Finally, reload mail daemons :

# rcctl enable dovecot
# rcctl start dovecot
# rcctl restart smtpd

Now you can use a mail client to read your messages.

Add a mail account

Add a new line for the new account in "/etc/mail/virtuals" and "/etc/mail/passwd" then reload tables for smtpd (dovecot read them on the fly) :

smtpctl update table virtuals
smtpctl update table passwd

Or "rcctl restart smtpd"