Kennisbank › Mailserver › IMAP on Your Own Mailserver: Setup and Configuration
mailserver starter 25 September 2026

IMAP on Your Own Mailserver: Setup and Configuration

IMAP on Your Own Mailserver: Setup and Configuration IMAP4rev1 is defined in RFC 3501, and that document is the only specification you actually need to read if

This article walks through setting up an IMAP server with Dovecot 2.3 on a Linux host, connecting a client to it, and verifying that the whole chain works. It is written for anyone running their own mail infrastructure — a VPS, a home server, a small office box — and who wants mail stored on the server instead of scattered across local machines.

What IMAP actually does

IMAP keeps messages on the server. That single design decision is the whole protocol.

POP3, its older sibling, traditionally pulls mail down to one device and often deletes it from the server afterwards. IMAP does the opposite: the mailbox lives on the server, and every client — desktop, laptop, phone — sees the same state. Read a message on your phone, it shows as read on your laptop. Move it to a folder, it moves everywhere. Delete it, it is gone for all clients.

That consistency is why IMAP won. It is also why IMAP is heavier than POP3: the server does more work, keeps more state, and the client has to stay in sync rather than just grab a file and leave.

The protocol went through several revisions. IMAP2 appeared in RFC 1064 (July 1988), IMAP4 in RFC 1730 (December 1994), and the current version, IMAP4rev1, in RFC 3501. When someone says "IMAP" today, they mean IMAP4rev1. Anything older is a historical footnote.

Requirements

  • A Linux server (Debian 12 or Ubuntu 22.04 LTS work well) with root or sudo access
  • Dovecot 2.3.x installed — the current stable line is 2.3.21
  • A valid TLS certificate for your mail hostname, or a Let's Encrypt setup you can point to
  • An existing mail user account (a system user or a virtual user in your setup)
  • Port 993 open in your firewall for IMAPS; port 143 only if you also want STARTTLS
You do not need Postfix for IMAP to work, but most people run it alongside for outbound SMTP. This article focuses on the IMAP side only.

Steps

1. Install Dovecot

Dovecot is the de facto IMAP server on Linux. It is fast, it speaks IMAP4rev1 properly, and its configuration is readable once you understand the split between `dovecot.conf` and the files in `conf.d/`.

```bash sudo apt update sudo apt install dovecot-core dovecot-imapd ```

On Debian 12 this pulls Dovecot 2.3.19; on Ubuntu 22.04 it is 2.3.16. Both are fine, but if you need a specific patch level, check `dovecot --version` after install.

The `dovecot-core` package gives you the daemon and the config skeleton. `dovecot-imapd` adds the IMAP-specific binaries. You do not need `dovecot-pop3d` unless you also want POP3.

2. Decide on mail location

Dovecot needs to know where messages live on disk. The modern default is Maildir — one file per message, one directory per folder. It survives crashes better than mbox and works fine over NFS if you ever need that.

Edit `/etc/dovecot/conf.d/10-mail.conf` and set:

```bash mail_location = maildir:~/Maildir ```

This puts each user's mail in `~/Maildir` under their home directory. If you run virtual users with a database backend, you will instead point at something like `/var/mail/vhosts/%d/%n/Maildir`. The `%d` is the domain and `%n` is the username — Dovecot substitutes them at runtime.

Pick one model and stick to it. Mixing system users and virtual users in the same Dovecot instance is possible but doubles the configuration you have to maintain.

3. Enable IMAP and disable plaintext

Open `/etc/dovecot/conf.d/10-auth.conf` and make sure plaintext authentication is only allowed over TLS:

```bash disable_plaintext_auth = yes auth_mechanisms = plain login ```

`disable_plaintext_auth = yes` means Dovecot refuses to accept a password over an unencrypted connection. This is the setting that stops your users from sending credentials in the clear because their client defaulted to port 143 without STARTTLS.

If you have clients that genuinely cannot do TLS — old embedded devices, some printers — you can set this to `no`, but understand what you are giving up. Credentials on port 143 without STARTTLS are readable by anyone on the path.

4. Configure TLS

Dovecot expects certificate paths in `/etc/dovecot/conf.d/10-ssl.conf`. If you use Let's Encrypt with certbot, the paths look like this:

```bash ssl = required ssl_cert =

`ssl = required` forces TLS on every connection. Clients that try port 143 without STARTTLS get rejected. That is the behavior you want.

`ssl_min_protocol = TLSv1.2` drops TLS 1.0 and 1.1. Some very old clients will fail to connect. In 2024 that is an acceptable trade — TLS 1.0 has been deprecated for years and the attack surface is not worth keeping around.

Reload the certificate when it renews. Certbot's deploy hook can do this:

```bash sudo certbot renew --deploy-hook "systemctl reload dovecot" ```

Without that hook, Dovecot keeps serving the old certificate until you restart it manually, and your clients start complaining about expiry three months later.

5. Set up the mail user

If you are using system users, create one:

```bash sudo useradd -m -s /usr/sbin/nologin mailuser sudo passwd mailuser ```

The `nologin` shell means the account cannot SSH in. It exists only to own a Maildir and authenticate against Dovecot. That is the correct scope for a mail-only account.

For virtual users, you would instead configure a passwd-file or SQL backend in `10-auth.conf` and `auth-sql.conf.ext`. Virtual users are more flexible but require you to manage a user database separately. For a handful of accounts, system users are simpler.

6. Start and enable Dovecot

```bash sudo systemctl enable --now dovecot sudo systemctl status dovecot ```

`enable --now` starts the service and marks it to start on boot in one command. If the status output shows `active (running)` and no red lines about config errors, you are past the first hurdle.

Dovecot validates its configuration at startup. A typo in a path or an unsupported directive will show up here, not silently later.

7. Open the firewall

Only port 993 needs to be open for IMAPS. Port 143 is optional and only if you want STARTTLS.

```bash sudo ufw allow 993/tcp sudo ufw allow 143/tcp sudo ufw reload ```

If you run nftables or firewalld instead, the equivalent rules apply. The point is the same: 993 in, everything else closed.

8. Configure your client

In Alpine, Evolution, Thunderbird, or whatever you use, create a new IMAP account with these settings:
  • Server: `mail.example.com`
  • Port: `993`
  • Security: `SSL/TLS`
  • Authentication: `Normal password` (or `PLAIN` if the client labels it that way)
  • Username: `mailuser` (or `mailuser@example.com` if you use full addresses)
Most clients will try to autodetect settings. When they guess wrong, they fall back to port 143 without TLS and then fail authentication because of `disable_plaintext_auth = yes`. Setting the port manually avoids that loop.

Verification

Check that Dovecot is listening on the right ports:

```bash sudo ss -tlnp | grep -E ':(143|993)' ```

You should see `dovecot` bound to both. If only 143 shows up, the `dovecot-imapd` package did not install correctly.

Then test the IMAP conversation directly:

```bash openssl s_client -connect mail.example.com:993 -crlf ```

Once connected, type:

``` a1 LOGIN mailuser yourpassword a2 LIST "" "*" a3 LOGOUT ```

A successful login returns `a1 OK`, and the `LIST` command shows your mailbox folders. If you get `a1 NO`, the credentials are wrong or the auth backend is misconfigured. If the connection drops before you can type anything, TLS is failing — check the certificate paths.

You can also check the Dovecot log for what actually happened:

```bash sudo journalctl -u dovecot -n 50 ```

Failed logins, TLS errors, and mailbox permission problems all show up there with timestamps.

Common problems

Client connects but authentication fails every time. The username format is the usual culprit. Dovecot distinguishes between `mailuser` and `mailuser@example.com`, and your auth backend has to match what the client sends. Check `auth_username_format` in `10-auth.conf`. Setting it to `%Ln` strips the domain, which fixes the mismatch when clients insist on sending full addresses.

Maildir permission denied. Dovecot runs as the `dovecot` user and needs to read and write the Maildir. If you created it manually as root, the ownership is wrong:

```bash sudo chown -R mailuser:mailuser /home/mailuser/Maildir sudo chmod -R 700 /home/mailuser/Maildir ```

Run this only on the Maildir, not on the whole home directory.

TLS handshake fails after a certificate renewal. Dovecot caches the certificate until reload. Certbot renews silently in the background and your clients break three months later at the worst possible moment. The deploy hook in step 4 prevents this. If you skipped it, `systemctl reload dovecot` fixes it now.

Where this leaves you

IMAP is not a temporary protocol that stuck around by accident. It solved a real problem — keeping mail consistent across devices — and the solution held up for three decades because the design was right: state on the server, clients as views.

What you have now is a working Dovecot instance serving IMAP4rev1 over TLS, with messages stored in Maildir and authentication that refuses to happen in the clear. That is the floor, not the ceiling. Quotas, sieve filtering, shared folders, and IMAP IDLE for push notifications are all one configuration block away in the same `conf.d/` directory.

The next thing to break will be something you did not configure. It always is.

← Terug naar kennisbank
← Terug naar kennisbank