You are here: Home / Postfix, Dovecot, PostGreSQL, and SOGo Webmail on Debian 13

Postfix, Dovecot, PostGreSQL, and SOGo Webmail on Debian 13

Debian 13 was fairly recently released, but AWS is already shoving it as the primary AMI, and make getting a good Debian 12 a few more steps. Most apps aren't yet compatible with Debian 13, so I recommend waiting for it to stabilize, but here is some information on getting a basic mail server working on Debian 13...

OVERVIEW

Debian 13 was only recently released, and is not compatible with MOST packages out there. There are a LOT of breaking changes.

I strongly advise in most situations sticking with Debian 12 (as of September 24th, 2025).

This will improve over time.

That being said, I had a situation where I need to make it work for a new mail server. And this documents the solutions (after a LOT of headaches to get there).

There isn't a good, currently working, all-in-one libre open source end-to-end self-hosted email solution package currently available that works on Debian 13.

This posting helps anyone trying to setup a self-hosted full-service email server, know what hoops to jump through on Debian 13, until there are other options available over time as Debian 13 matures.

BACKGROUND (OPTIONAL READ)

I wasn't able to find ANY single location that covered this specific configuration, so I am hoping by posting this, as we have often been on the bleeding edge, this will help save a lot of others the headache I had to go through to get all this actually working.

It isn't straightforward, but I wanted an alternative to Modoboa (after years of dealing with its cruft).

I've been setting mail servers since the early 1990s. For a long time after sendmail, I ran on qmail and ezmlm based setups quite happily (and securely) , supporting millions of emails, lists, etc. But over time the qmail ecosystem failed to adapt and keep up.

For a few years I had to back to cobbling together manually, there weren't any good bundles anymore.

Redmail, Cube, Squirrel, and others appeared, I tried them all.

Some in production environments for a few months or years here and there, but never really found that Postmaster nirvana I had had for over a decade prior.

Out frustration I made do with Modoboa, at least it would work initially. But it always had a lot of trouble upgrading and keeping up. So every few years we had to do a new setup migrate the email to the new setup, etc. In-place upgrades were a bigger headache than they were worth.

Over time that became full of cruft, and users were especially complaining about the webmail interface, incomplete CalDAV/CardDAV implementations, and other features that were never actually ever quite finished. Then they started an overhaul of the admin interface, which started to break the rest of the setup, they were going backwards, not forwards.

So it was time to find something else.

This summer I began dabbling with SOGo. Other than it relying too much of cryptic icons that users are NOT finding intuitive, the features and UI they are finding much better for the webmail, and CalDAV/CardDAV is MUCH better.

However, SOGo is not a complete setup, it just a subset webmail/calendar/address-book that you put on top of an existing setup (either remotely connected to you IMAP servers, or on the same box, depending on your preferences and needs.

CONFIGURATION OVERVIEW

Operating System: Debian 13 (AWS AMI)

Database: PostGreSQL version 17.6 (apt-installed)

SMTP+: Postfix 3.10.4 (apt-installed)

IMAP, POP3+: Dovecot 2.4.1 (apt-installed)

SOGo: 5.12 (apt-installed)

Domains/Users/Aliases Types: Virtual DB-Based Domains, Users, Aliases.

 

 

DETAILS FOR SETUP

 

# Setting Up Dovecot 2.4 with PostgreSQL Virtual Mailboxes on Debian 13

## Introduction

Setting up a mail server with virtual domains and users on Debian 13 (Trixie) presents unique challenges due to significant changes in Dovecot 2.4. This guide documents a working configuration for Dovecot 2.4 with PostgreSQL-backed virtual mailboxes, addressing the breaking changes and common pitfalls.

## The Challenge

Debian 13 ships with Dovecot 2.4, which introduces **breaking changes** from version 2.3:
- Configuration files are completely incompatible
- External `.conf.ext` files are obsolete
- SQL authentication syntax has changed dramatically
- Variable substitution uses new syntax

If you're migrating from Debian 12 (Dovecot 2.3) to Debian 13 (Dovecot 2.4), your existing configuration **will not work**.

## Prerequisites

- Debian 13 (Trixie)
- PostgreSQL (tested with version 17)
- Postfix for mail transport
- Root or sudo access

## Step 1: Install Required Packages

**Critical:** Debian 13 does not install the PostgreSQL driver for Dovecot by default!

```bash
# Install Dovecot with PostgreSQL support
sudo apt install dovecot-core dovecot-imapd dovecot-pop3d dovecot-pgsql

# The dovecot-pgsql package is ESSENTIAL and often missed
```

Without `dovecot-pgsql`, you'll get the cryptic error:
```
Fatal: Error in configuration file... passdb { } is missing section name
```

## Step 2: PostgreSQL Database Setup

Create your virtual mailbox database structure:

```sql
-- Connect as postgres superuser
sudo -u postgres psql

-- Create mail user and database
CREATE USER mailuser WITH ENCRYPTED PASSWORD 'SecurePassword123';
CREATE DATABASE maildb OWNER mailuser;
\c maildb

-- Create mailbox table for virtual users
CREATE TABLE mailbox (
username VARCHAR(255) PRIMARY KEY,
password VARCHAR(255) NOT NULL,
name VARCHAR(255),
maildir VARCHAR(255),
quota BIGINT DEFAULT 0,
active BOOLEAN DEFAULT true,
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Create alias table
CREATE TABLE alias (
address VARCHAR(255) PRIMARY KEY,
goto TEXT NOT NULL,
domain VARCHAR(255),
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
active BOOLEAN DEFAULT true
);

-- Create domain table
CREATE TABLE domain (
domain VARCHAR(255) PRIMARY KEY,
description TEXT,
aliases INTEGER DEFAULT 0,
mailboxes INTEGER DEFAULT 0,
maxquota BIGINT DEFAULT 0,
quota BIGINT DEFAULT 0,
transport VARCHAR(255) DEFAULT 'virtual',
backupmx BOOLEAN DEFAULT false,
created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
active BOOLEAN DEFAULT true
);

-- Grant permissions
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO mailuser;
GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO mailuser;

-- Insert test domain and user
INSERT INTO domain (domain, description, active)
VALUES ('example.com', 'Example Domain', true);

-- Password generated with: doveadm pw -s SHA512-CRYPT
-- This example password is "TestPass123"
INSERT INTO mailbox (username, password, name, maildir, active)
VALUES ('user@example.com',
'{SHA512-CRYPT}$6$salt$hash...',
'Test User',
'example.com/user/',
true);
```

## Step 3: Dovecot 2.4 Configuration

### Critical Configuration Changes

1. **Named sections are required** - `passdb sql { }` not just `passdb { }`
2. **No external dovecot-sql.conf.ext** - SQL config goes inline
3. **New variable syntax** - Use `%{user}` instead of `%u`
4. **Must return `mail` not `maildir`** from userdb queries

### Configure /etc/dovecot/conf.d/10-auth.conf

**Important:** First, find and comment out this line (usually around line 52):
```conf
# THIS LINE BREAKS SQL AUTHENTICATION - MUST BE COMMENTED OUT
#auth_username_format = %u
```

Then add at the END of the file:
```conf
# SQL driver configuration for Dovecot 2.4
sql_driver = pgsql

pgsql localhost {
parameters {
user = mailuser
password = SecurePassword123
dbname = maildb
}
}

# Password scheme used in database
passdb_default_password_scheme = SHA512-CRYPT

# Enable SQL authentication
!include auth-sql.conf.ext
```

### Create /etc/dovecot/conf.d/auth-sql.conf.ext

This file now only contains the queries, not the connection info:

```conf
# Authentication for SQL users - Dovecot 2.4

passdb sql {
query = SELECT username AS user, password FROM mailbox WHERE username = '%{user}' AND active = true
}

userdb sql {
# CRITICAL: Must return 'mail' not 'maildir', with full path and storage type
query = SELECT 'maildir:/var/vmail/' || maildir AS mail, 500 AS uid, 500 AS gid FROM mailbox WHERE username = '%{user}' AND active = true
iterate_query = SELECT username AS user FROM mailbox
}
```

### Remove Obsolete Files

```bash
# This file is no longer used in Dovecot 2.4
sudo rm -f /etc/dovecot/dovecot-sql.conf.ext
```

## Step 4: Create Mail Storage Directory

```bash
sudo mkdir -p /var/vmail
sudo useradd -u 500 -g 500 -d /var/vmail vmail
sudo chown -R vmail:vmail /var/vmail
```

## Step 5: Test Configuration

```bash
# Restart Dovecot
sudo systemctl restart dovecot

# Check status
sudo systemctl status dovecot

# Test authentication
sudo doveadm auth test user@example.com TestPass123

# Expected output:
# passdb: user@example.com auth succeeded
# extra fields:
# user=user@example.com

# Test IMAP connection
openssl s_client -connect localhost:143 -starttls imap -quiet
# Then type:
a login user@example.com TestPass123
# Should return: a OK Logged in
b logout
```

## Common Errors and Solutions

### Error: "passdb { } is missing section name"
**Cause:** Missing dovecot-pgsql package or using old syntax
**Solution:** Install dovecot-pgsql and use named sections: `passdb sql { }`

### Error: "sql_driver setting is empty"
**Cause:** SQL driver not configured
**Solution:** Add `sql_driver = pgsql` to 10-auth.conf

### Error: "args: Unknown setting"
**Cause:** Using Dovecot 2.3 syntax with `args = /path/to/config`
**Solution:** Remove `args` line, configuration is now inline

### Error: "Invalid maildir=... Setting is a named filter"
**Cause:** Returning `maildir` from userdb query
**Solution:** Return `mail` with full path: `'maildir:/var/vmail/' || maildir AS mail`

### Authentication works but shows "user=%u"
**Cause:** `auth_username_format = %u` is overriding variable substitution
**Solution:** Comment out the auth_username_format line

## Postfix Integration

For Postfix to use the same PostgreSQL database:

```conf
# Add to /etc/postfix/main.cf
virtual_mailbox_domains = proxy:pgsql:/etc/postfix/sql/virtual_domains.cf
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/sql/virtual_mailboxes.cf
virtual_alias_maps = proxy:pgsql:/etc/postfix/sql/virtual_aliases.cf
virtual_mailbox_base = /var/vmail
virtual_uid_maps = static:500
virtual_gid_maps = static:500
```

Create /etc/postfix/sql/virtual_domains.cf:
```
user = mailuser
password = SecurePassword123
hosts = localhost
dbname = maildb
query = SELECT domain FROM domain WHERE domain='%s' AND active=true
```

## Migration Checklist from Dovecot 2.3 to 2.4

- [ ] Install dovecot-pgsql package
- [ ] Convert anonymous sections to named sections
- [ ] Move SQL config from external file to main config
- [ ] Update all variables from `%u` to `%{user}`
- [ ] Change userdb query to return `mail` not `maildir`
- [ ] Comment out `auth_username_format = %u`
- [ ] Remove dovecot-sql.conf.ext file
- [ ] Update password scheme configuration

## Conclusion

Dovecot 2.4 on Debian 13 requires significant configuration changes from previous versions. The key issues are:

1. Missing dovecot-pgsql package (not installed by default)
2. Required named sections for passdb/userdb
3. SQL configuration now inline, not in external files
4. New variable syntax and return field requirements

With these changes addressed, Dovecot 2.4 works well with PostgreSQL virtual mailboxes. This configuration has been tested and is running in production on Debian 13 systems.

## Additional Resources

- [Dovecot 2.3 to 2.4 Migration Guide](https://doc.dovecot.org/main/installation/upgrade/2.3-to-2.4.html)
- [Dovecot SQL Authentication](https://doc.dovecot.org/main/core/config/auth/databases/sql.html)
- [PostgreSQL Virtual Mailbox Setup](https://doc.dovecot.org/main/howto/virtual_users.html)

---

*Tested on: Debian 13 (Trixie), Dovecot 2.4.1-4, PostgreSQL 17, Postfix 3.9*

 

REFERENCES

TODO

 

 

Navigation