---
title: Webmail using Roundcube
lastUpdated: 2025-11-01
slug: ispmail-trixie/webmail
sidebar:
  order: 170
---

import { Aside } from "@astrojs/starlight/components";

## Configure Apache

Now that the email has arrived, our valued user surely wants to read it. Most humans nowadays seem to prefer reading
their email in the web browser, because it's the simplest way. (Don't worry. Power users who prefer mail clients like
Thunderbird will also get what they want.) So let's prepare [Roundcube](https://roundcube.net/) for them.

<details class="collapsible">
  <summary>Click here to learn more about virtual hosts…</summary>

A web server like Apache has the job of answering HTTP or HTTPS requests from people’s browsers. Running just a single
website per server (or per IP address) would be both inefficient and limiting, so the idea of _virtual hosts_ was
introduced. With virtual hosts, one server can host many different websites. The browser helps by sending a
`Host: mail.example.org` header with each request, which tells the server which website it should serve. This works fine
for HTTP—though plain HTTP is rarely used anymore.

With HTTPS, things get trickier. Browsers expect the server to present a TLS certificate that matches the domain being
requested. If you try to open mail.example.org but the server responds with a certificate for shop.example.org, the
browser will block the connection. That means the server needs to know which domain the browser is asking for before the
encrypted connection is set up.

The solution is a feature called SNI (Server Name Indication). When establishing an HTTPS connection, the browser
includes the domain name it wants in the handshake. This allows the server to pick the correct TLS certificate right
from the start.

Fortunately you do not have to worry about it that much because Apache is doing the heavy lifting for you. A virtual
host configuration essentially looks like:

```
<VirtualHost *:443>
  ServerName mail.example.org
  SSLCertificateFile /etc/letsencrypt/live/mail.example.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/mail.example.org/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
```

There are two directories dealing with virtual hosts:

- /etc/apache2/sites-available
- /etc/apache2/sites-enabled

The actual file containing the configuration lives in _sites-available_. If that configuration should be active, then a
symbolic link (symlink) is added to the _sites-enabled_ directory pointing to the file in the _sites-available_
directory. That way you can switch sites on and off without deleting the actual configuration file. You can enable a
site using the `a2ensite` (apache2 enable config) command or disable it using `a2dissite`.

</details>

Since you ran `certbot` earlier to create a TLS certificate for your site, the default configuration files for HTTP and
HTTPS have been adapted already:

- **000-default.conf**: This is the virtual host configuration for HTTP requests. It uses a `RewriteRule` to redirect
  users to the HTTPS site. So if user accidentally forget to type `https://`, we will add it for them.
- **000-default-le-ssl.conf**: This is the HTTPS virtual host.

So to get Apache to serve the Roundcube application you need to edit the
`/etc/apache2/sites-available/000-default-le-ssl.conf` file.

<Aside type="danger" title="Important">

Please replace `mail.example.org` by the FQDN you chose.

</Aside>

Set this:

```text title="Edit /etc/apache2/sites-available/000-default-le-ssl.conf"
ServerName mail.example.org
DocumentRoot /var/lib/roundcube/public_html
Include /etc/roundcube/apache.conf
```

Meaning:

- `ServerName` sets the domain name that a user's browser will request.
- `DocumentRoot` points the entire web site to the directory where Roundcube is installed.
- `Include` loads additional security settings that the Roundcube package provides.

And as usual Apache needs to be restarted after the configuration change:

```sh
systemctl restart apache2
```

Check that Apache is running properly:

```sh
systemctl status apache2
```

In case of a problem run `apache2ctl configtest` to find the cause.

## Limit access to localhost

The main configuration file of Roundcube is located at `/etc/roundcube/config.inc.php`. Feel free to customize the file.
Fortunately nowadays the basic settings are already as we need them. However these two settings need to be changed by
you.

<Aside type="danger" title="Important">

Please replace `mail.example.org` by the FQDN you chose.

</Aside>

```text title="Edit /etc/roundcube/config.inc.php"
$config['imap_host'] = 'tls://mail.example.org:143';
$config['smtp_host'] = 'tls://mail.example.org:587';
```

So now when your users enter `https://webmail.example.org/` in their browser they should get the Roundcube login form:

![Roundcube login dialog](images/roundcube-login.png)

Keep in mind that we are using the email address as the account name of the user. So when logging in please enter the
email address as the user name. E.g. `john@example.org` and password `summersun`.

If the login fails, check `/var/log/roundcube/errors.log`.

<Aside type="tip" title="Important">

Before you get overly enthusiastic: you can't send emails from Roundcube yet. We will fix that now.

</Aside>

## Plugins

Roundcube comes with various plugins that you can offer your users. I suggest that you enable at least

- the **password** plugin so that your users can change their access password
- the **managesieve** plugin so that your users can create server-based filtering rules

Again edit the `/etc/roundcube/config.inc.php` file and look for the _plugins_ configuration. To enable the recommended
plugins change it to:

```
$config['plugins'] = array(
     'password',
     'managesieve',
);
```

Plugins are configured through files located in the `/etc/roundcube/plugins` directory.

### password

Let's quickly set up the password plugin:

```sh title="Run this on your server"
cat > /etc/roundcube/plugins/password/config.inc.php << 'EOF'
<?php
$config['password_driver'] = 'sql';
$config['password_minimum_length'] = 12;
$config['password_force_save'] = true;
$config['password_algorithm'] = 'blowfish-crypt';
$config['password_algorithm_prefix'] = '{CRYPT}';
$config['password_db_dsn'] = 'mysql://mailadmin:MAILADMIN-PASSWORD-HERE@localhost/mailserver';
$config['password_query'] = "UPDATE virtual_users SET password=%P WHERE email=%u";
?>
EOF

chown root:www-data /etc/roundcube/plugins/password/config.inc.php
chmod u=rw,g=r,o= /etc/roundcube/plugins/password/config.inc.php
```

What these settings mean:

- `$config['password_driver'] = 'sql';`\
  Use SQL as a backend.
- `$config['password_minimum_length'] = 12;`\
  New passwords must be at least 12 characters long.
- `$config['password_force_save'] = true;`\
  This will overwrite the password in the database even if it hasn’t changed. It helps us improve the strength of the
  password hash by re-encoding it with a better algorithm even if the user chooses to keep his old password.
- `$config['password_algorithm'] = 'blowfish-crypt';`\
  The cryptographic algorithm to encode the password. This one is considered very secure and supported by Dovecot.
- `$config['password_algorithm_prefix'] = '{CRYPT}';`\
  Prepend every password with this string so that Dovecot knows how we encrypted the password.
- `$config['password_db_dsn'] = 'mysql://mailadmin:MAILADMIN-PASSWORD-HERE@localhost/mailserver';`\
  Connection information for the local database. Use your own password for the _mailadmin_ (!) database user here. We
  cannot use the restricted _mailserver_ user because we have to write the new password to the database.
- `$config['password_query'] = "UPDATE virtual_users SET password=%P WHERE email=%u";`\
  The SQL query that is run to write the new password hash into the database. `%P` is a placeholder for the new password
  hash. `%u` is the logged-in user and conveniently matches the email address.

For a complete reference please see `/usr/share/roundcube/plugins/password/config.inc.php.dist`.

The last two lines make sure that this config file is only accessible to everyone.

![Roundcube password dialog](images/roundcube-password.png)

Try it. Log into Roundcube as `john@example.org` with password ‘summersun’. Go to the _Settings_. Choose _Password_.
Enter a new password twice. You should get a success message at the bottom right. Now logout and login with the new
password. Does it work? Great.

### managesieve

[Sieve](<https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)>) is a simple programming language to be used for
server-side rules. Dovecot executes these rules every time a new email comes in. There are global rules that are
executed for every email. And of course every user/mailbox can have its own rules. To manage sieve rules Dovecot offers
the _managesieve_ interface that you enabled earlier. So we just need to tell Roundcube how to access it.

The configuration file for Roundcube’s _managesieve_ plugin is found at
`/etc/roundcube/plugins/managesieve/config.inc.php`. But the defaults are fine so you do not need to change it.

Sieve rules are stored in a special syntax on the server. This is an example that moves all incoming emails to the
_test_ folder that have “test” in the subject:

```
require ["fileinto"];
if header :contains "subject" "test"
{
  fileinto "INBOX/test";
}
```

You do not need to learn this syntax though. Roundcube’s sieve rule editor is way more user-friendly.

Try adding a sieve rule for `john@example.org` in Roundcube. That feature is located in Settings/Filters. You will find
the machine-readable sieve code at `/var/vmail/example.org/john/sieve/roundcube.sieve`.

The rule editor looks like this:

![Roundcube's sieve rule editor](images/webmail-roundcube-sieve-editor.png)
