Compare commits

...

7 commits

2 changed files with 255 additions and 0 deletions

5
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,5 @@
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks

View file

@ -2,6 +2,7 @@
date = '2024-11-19T16:29:01Z'
draft = true
title = 'How to Set up a Mail Server on Alpine Linux with Postfix and Dovecot'
tags = ['mail server', 'alpine linux', 'postfix', 'dovecot']
+++
# About mail servers
@ -52,6 +53,13 @@ you can at least know that your email is secure, though not private; Google will
knowledge and skills to secure a mail server. If you are not confident in your ability to do this and not interested in
learning, you may want to find another solution.
There are also existing solutions that aim to "simplify" the process of managing a mail server; there have always been
plenty of services offering mail server hosting which is managed for you, the customer, and there are also projects
like [Mailcow](https://mailcow.email/), which is an attempt to make a user-friendly distributable mail server stack
based on Docker. It has a web GUI you can use to configure your mail server. This may be an option for people who value
digital sovereignty but don't want to get their hands dirty with config files. I only mention this as something you may
want to look into; I have never used Mailcow and cannot recommend it personally.
# Why this tutorial?
There are many tutorials on the internet about how to set up a mail server. I don't claim that mine is particularly
@ -295,6 +303,16 @@ Now set `mydomain` to the domain you intend to send email from. For instance, my
`myorigin` determines the domain name in the `From:` field of locally sent emails. So you could for instance set this
to `revsuine.xyz`.
Set `mydestination` to the following:
```conf
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
```
`mydestination` states the list of domains your machine will consider itself the destination for, e.g. if `mydomain` is
set to `revsuine.xyz` then any emails sent to `username@revsuine.xyz` will be sent to my server according to the above
configuration.
`maillog_file` denotes where Postfix's log file is. By default this is `/var/log/messages`; you may want to configure
Postfix to have a dedicated log file like `/var/log/postfix.log`.
@ -532,6 +550,238 @@ mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtputf8_enable = no
```
## Configuring authentication
Edit `/etc/dovecot/conf.d/10-auth.conf` and uncomment the following line:
```conf
disable_plaintext_auth = yes
```
This disables plaintext authentication *unless* SSL/TLS is used.
In the same file, configure `auth_username_format`. As the variable name suggests, this denotes the format the server
expects usernames in for authentication. Setting it to `%n` removes the domain, so to sign in to `user@domain.com`
you'd enter your username as `user`. For this setup, you should set `auth_username_format` to `%n`, because we are
using Unix user accounts for email accounts; Dovecot wouldn't be able to find `user@domain.com` because the mailbox
user is just `user`.
In the same file again, `auth_mechanisms` is a space-separated list of authentication mechanisms your server uses. Set
this to
```conf
auth_mechanisms = plain login
```
`login` is mostly to support older email clients, but is optional.
Edit `/etc/dovecot/conf.d/10-master.conf`, and change `service auth` to the following:
```conf
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
```
Now we need to set the actual mechanism through which the server knows what password to expect, and what users exist.
We will use a file at `/etc/dovecot/passwd` to manage this. Edit `/etc/dovecot/conf.d/auth-passwdfile.conf.ext` to be
the following:
```conf
passdb {
driver = passwd-file
args = scheme=argon2id username_format=%n /etc/dovecot/passwd
}
userdb {
driver = passwd
}
```
See [this documentation](https://doc.dovecot.org/main/core/config/auth/schemes.html) to decide on a password scheme to
use. I picked `argon2id` as the most secure option, however also the most expensive option, so it may be a poor option
if you have many users. Dovecot recommends that, if using ARGON2ID, you set `vsz_limit = 2G` for the `auth` service. To
do that with our setup, edit `/etc/dovecot/conf.d/10-master.conf` and add the line
```conf
vsz_limit = 2G
```
to the `service auth {}` section.
Now we want to include this file. Edit `/etc/dovecot/10-auth.conf` and ensure it includes this line, and that other
`!include` lines for other `auth-*.conf.ext` files are commented out:
```conf
!include auth-passwdfile.conf.ext
```
## Creating a user
Now let's create a user. We will be using a Unix user account, so create one with `adduser` if you don't already have
one. Their Unix username will be their email username, and what appears before the `@` in their email address. They
should also be in the `mail` group. So for instance:
# adduser revsuine
# adduser revsuine mail
We will not, however, be using their Unix password for authentication. Instead, we'll set them a password dedicated for
their email account. Create or edit the `/etc/dovecot/passwd` text file. Have a look at the following example:
```passwd
revsuine:{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$H1oyL7UdwUWiBuZGnyXorQ$3aW/cfyNdrjoHw3OK7HlOzwgKqdg61prln8QMtWJijg
muffalo:{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$KLnLOiqlhbhOPLhmTUqllA$Raki8Rw/+eOgJzDSEXxtw0mqI+aYLyFf+gpi+MQTdfo
thrumbo:{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$8R4rVQ2hlKmiZ0Zmyzwg0g$tkesrePjJfLAEKu1wyJY1tu6V+fR5+C6/etyKq6WJlQ
```
This lists three users, `revsuine`, `muffalo`, and `thrumbo` (those are their usernames). These will all be system
users in the `mail` group. After the colon is the ARGON2ID hash of their password.
If you're storing passwords with ARGON2ID, to get what goes after the colon in your passwd file, run this command:
# doveadm pw -s argon2id
You will be prompted to enter a password, and then it will output exactly what to put after the colon, such as
`{ARGON2ID}$argon2id$v=19$m=65536,t=3,p=1$H1oyL7UdwUWiBuZGnyXorQ$3aW/cfyNdrjoHw3OK7HlOzwgKqdg61prln8QMtWJijg`. Each
user is their own line of the file.
Set up your `/etc/dovecot/passwd` file accordingly, making sure each user listed is also a system user, because we are
storing their mail in their home directories.
## Use your TLS certificate
Edit `/etc/dovecot/conf.d/10-ssl.conf` and set the following options (some should already be present, so you should
just change their values):
```conf
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.domain.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.domain.com/privkey.pem
ssl_prefer_server_ciphers = yes
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305
```
Replace `mail.domain.com` with the domain you obtained your TLS certificate for. You can check
$ ls /etc/letsencrypt/live
if you're not sure.
The cipher list is from [Mailcow](https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-harden_ciphers/).
OpenSSL 3.x has a FIPS provider which is incompatible with Dovecot, so it should be disabled. Edit
`/etc/ssl/openssl.conf` and make sure the following line is commented out:
```conf
# providers = provider_sect
```
## Configure "special" mailboxes
The file `/etc/dovecot/conf.d/15-mailboxes.conf` denotes "special" mailboxes, such as your spam folder. You can
configure these, including setting these to auto-create, in `/etc/dovecot/conf.d/15-mailboxes.conf`. I have mine set
to:
```conf
# NOTE: Assumes "namespace inbox" has been defined in 10-mail.conf.
namespace inbox {
# These mailboxes are widely used and could perhaps be created automatically:
mailbox Drafts {
special_use = \Drafts
auto = create
}
mailbox Junk {
special_use = \Junk
}
mailbox Spam {
special_use = \Junk
auto = create
}
mailbox Trash {
special_use = \Trash
auto = create
}
# For \Sent mailboxes there are two widely used names. We'll mark both of
# them as \Sent. User typically deletes one of them if duplicates are created.
mailbox Sent {
special_use = \Sent
}
mailbox "Sent Messages" {
special_use = \Sent
auto = create
}
mailbox Drafts {
special_use = \Drafts
auto = create
}
}
```
You can set the `auto = create` option for any mailbox you want to be auto-created for users.
Now restart Dovecot. Keep an eye on terminal output, as if there's a configuration error, you'll get an error message
when restarting.
# rc-service dovecot restart
# Use a local email client
You are now ready to try logging in on a local email client such as Thunderbird, Evolution, Geary, KMail, etc.
To log in:
Enter your display name, email address (this is `[Unix user]@[mydomain variable in Postfix config]`), and the password
you set for yourself in `/etc/dovecot/passwd`. Set the following settings:
<!-- html table so that the headers can be on the left & colspan -->
<table>
<tr>
<td></td>
<th>Incoming</th>
<th>Outgoing</th>
</tr>
<tr>
<th>Server type</th>
<td>IMAP</td>
<td>SMTP</td>
</tr>
<tr>
<th>Server</th>
<td colspan="2"><code>mail.domain.com</code>, or whatever your MX record is set to</td>
</tr>
<tr>
<th>Port</th>
<td>993</td>
<td>465</td>
</tr>
<tr>
<th>Username</th>
<td colspan="2">Your system username; this should be the contents of your email address before the
<code>@</code></td>
</tr>
<tr>
<th>Encryption</th>
<td colspan="2">SSL/TLS</td>
</tr>
<tr>
<th>Authentication</th>
<td>Password</td>
<td>PLAIN (shows up as <code>Normal password</code> in Thunderbird)</td>
</tr>
</table>
With our setup, we are also able to use STARTTLS on port 143 (incoming) and 587 (outgoing) too.
You should be able to send and receive emails as normal now.
<!-- FOOTNOTES: -->
[^server_trust]: This is only true to the extent that your server is not compromised. You could say there's an order of