Feed Item
Added a class  to  , Linux Servers Set Up & Management

A comprehensive installation and configuration manual that consolidates all the insights from our previous discussions. It walks you through installing, configuring, and managing a Postfix + Dovecot + MySQL + Roundcube mail server on a typical Ubuntu/Debian system. It includes SSL/TLS, SMTP AUTH, MySQL-based virtual users, and Roundcube webmail.

Installation Manual:

Postfix + Dovecot + MySQL + Roundcube Setup

Table of Contents

  1. Introduction
  2. Prerequisites & Basic System Setup
  3. Install Required Packages
  4. Configure MySQL for Virtual Domains & Users
  5. Configure Postfix
  6. Configure Dovecot
  7. Configure Roundcube
  8. SSL Certificates with Let’s Encrypt (Optional)
  9. Testing the Setup
  10. Managing Users
  11. Enabling Sent Folders & Basic Roundcube Customization
  12. Troubleshooting Tips

1. Introduction

This guide describes how to build a mail server that uses:

  • Postfix as the SMTP server (handles sending and receiving).
  • Dovecot as the IMAP/POP3 server for mail storage and authentication.
  • MySQL for storing virtual domain and mailbox information.
  • Roundcube as a webmail client.

When completed, you’ll have:

  • Encrypted (TLS) IMAP on port 993 and SMTP on port 587 (for sending).
  • MySQL-based user accounts (no need for system users).
  • A Roundcube webmail interface for sending and receiving mail.

2. Prerequisites & Basic System Setup

  1. Ubuntu or Debian server with root or sudo privileges.
  2. A FQDN (Fully Qualified Domain Name) for your mail server, e.g. mail.example.com.
  3. DNS records pointing mail.example.com to your server’s IP.
  4. Open ports on your firewall:
  • 25 (SMTP inbound), 587 (SMTP submission), 993 (IMAP), 995 or 110 (POP3, optional), 80/443 for Let’s Encrypt if using web-based ACME.
  1. SSL certificate (Let’s Encrypt or other). This guide shows optional Let’s Encrypt steps in Section 8.

Make sure your server’s hostname is set correctly:

sudo hostnamectl set-hostname mail.example.com

3. Install Required Packages

Update your system and install essential mail-related packages:

sudo apt-get update
sudo apt-get install postfix postfix-mysql dovecot-core dovecot-imapd dovecot-pop3d \
  dovecot-mysql mysql-server libsasl2-2 libsasl2-modules pwgen \
  apache2 php php-mysql # (for Roundcube via Apache/PHP)
Note: If you prefer Nginx or another web server, install that instead of Apache.
During Postfix installation, it may ask “General type of mail configuration”—choose “Internet Site” or something minimal, since we’ll override it with our custom configs.

4. Configure MySQL for Virtual Domains & Users

4.1 Create Database & User

If not done already:

sudo mysql -u root -p

Then:

CREATE DATABASE mailserver;
CREATE USER 'mail_admin'@'localhost' IDENTIFIED BY 'SomeStrongPassword';
GRANT ALL PRIVILEGES ON mailserver.* TO 'mail_admin'@'localhost';
FLUSH PRIVILEGES;
EXIT;

4.2 Create Tables

Inside mailserver, we usually have:

  • A domain table for each domain (e.g. example.com).
  • A mailbox table for each user/mailbox.
  • An alias (or forwardings) table for any aliases.

For example:

USE mailserver;

CREATE TABLE domain (
  domain VARCHAR(50) NOT NULL,
  PRIMARY KEY (domain)
);

CREATE TABLE mailbox (
  username VARCHAR(100) NOT NULL,
  password VARCHAR(255) NOT NULL,
  name VARCHAR(100) NOT NULL,
  maildir VARCHAR(255) NOT NULL,
  quota INT(10) NOT NULL DEFAULT 0,
  local_part VARCHAR(64) NOT NULL,
  domain VARCHAR(50) NOT NULL,
  created DATETIME NOT NULL,
  modified DATETIME NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (username)
);

CREATE TABLE alias (
  address VARCHAR(100) NOT NULL,
  goto TEXT NOT NULL,
  domain VARCHAR(50) NOT NULL,
  created DATETIME NOT NULL,
  modified DATETIME NOT NULL,
  active TINYINT(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (address)
);
Adjust sizes/columns as needed.

4.3 Insert Your Domain

INSERT INTO domain (domain) VALUES ('example.com');

4.4 MySQL Queries for Postfix & Dovecot

We’ll reference these .cf files in Postfix’s config. They typically contain lines like:

/etc/postfix/mysql-virtual-mailbox-domains.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT 1 FROM domain WHERE domain='%s'

/etc/postfix/mysql-virtual-mailbox-maps.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT maildir FROM mailbox WHERE username='%s' AND active=1

/etc/postfix/mysql-virtual-alias-maps.cf:

user = mail_admin
password = SomeStrongPassword
hosts = 127.0.0.1
dbname = mailserver
query = SELECT goto FROM alias WHERE address='%s' AND active=1
Make sure each file is owned by root:root and has 0600 or similarly restrictive permissions.

5. Configure Postfix

5.1 Main Configuration (/etc/postfix/main.cf)

Key directives (some lines might already exist):

myhostname = mail.example.com
mydomain = example.com
myorigin = /etc/mailname
mydestination = $myhostname, localhost.$mydomain, localhost
relayhost =

smtpd_banner = $myhostname ESMTP $mail_name (Ubuntu)
append_dot_mydomain = no
biff = no
inet_interfaces = all
inet_protocols = all

# Virtual domains
virtual_mailbox_base = /var/vmail
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_transport = lmtp:unix:private/dovecot-lmtp

virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-virtual-alias-maps.cf

# TLS
smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3,!TLSv1,!TLSv1.1

# Authentication
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
Adjust to match your paths and Let’s Encrypt cert. If you’re not using Let’s Encrypt, point to your existing SSL cert/key.

5.2 Master Configuration (/etc/postfix/master.cf)

Make sure submission (port 587) is enabled:

submission inet n       -       y       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_tls_security_level=encrypt
  -o smtpd_tls_wrappermode=no
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject_unauth_destination
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_tls_auth_only=yes

Make sure indentation is correct: the line submission inet ... has no leading spaces, each -o line is indented by at least one space.

Then restart Postfix:

sudo systemctl restart postfix

6. Configure Dovecot

6.1 Dovecot main config: /etc/dovecot/dovecot.conf

Likely references conf.d. Ensure protocols are correct:

protocols = imap pop3 lmtp

6.2 10-auth.conf

disable_plaintext_auth = yes
auth_mechanisms = plain login

!include auth-sql.conf.ext

6.3 10-master.conf

Check the service auth & service lmtp sections:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  user = dovecot
}

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0666
    user = postfix
    group = postfix
  }
}

This ensures Postfix can communicate with Dovecot for both AUTH and LMTP.

6.4 auth-sql.conf.ext

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

6.5 dovecot-sql.conf.ext

driver = mysql
connect = host=127.0.0.1 dbname=mailserver user=mail_admin password=SomeStrongPassword
default_pass_scheme = SHA512-CRYPT

password_query = SELECT username as user, password FROM mailbox WHERE username = '%u' AND active=1
Adjust pass scheme as needed if your mailbox table uses a different hash.

Restart Dovecot:

sudo systemctl restart dovecot

7. Configure Roundcube

7.1 Install Roundcube

On Ubuntu/Debian:

sudo apt-get install roundcube roundcube-core roundcube-mysql roundcube-plugins

It may prompt for initial DB config. Let it create a DB for Roundcube (separate from mailserver).

7.2 Adjust /etc/roundcube/config.inc.php

Example settings:

$config['db_dsnw'] = 'mysql://roundcube:RoundcubeDBPass@localhost/roundcube';

$config['default_host'] = 'ssl://mail.example.com:993';
$config['smtp_server']  = 'mail.example.com';
$config['smtp_port']    = 587;
$config['smtp_user']    = '%u';
$config['smtp_pass']    = '%p';
$config['smtp_secure']  = 'tls';

$config['product_name'] = 'My Webmail';
$config['des_key'] = 'ReplaceWith24RandomChars';

$config['plugins'] = array();

7.3 Make Sure the Web Server is Enabled

For Apache, ensure /etc/apache2/conf-enabled/roundcube.conf or similar is in place. Then:

sudo systemctl restart apache2

Visit http://your_server/roundcube or https://your_server/roundcube.

8. SSL Certificates with Let’s Encrypt (Optional)

If you used Let’s Encrypt:

sudo apt-get install certbot
sudo certbot certonly --apache -d mail.example.com

or with Nginx: --nginx. Then set smtpd_tls_cert_file and smtpd_tls_key_file in Postfix (and ssl_cert/ssl_key in Dovecot) to point to the Let’s Encrypt cert paths.

9. Testing the Setup

  1. Check Postfix is listening on ports 25 & 587:
sudo ss -plnt | grep ':25\|:587'
  1. Check Dovecot on ports 143/993:
sudo ss -plnt | grep ':993\|:143'
  1. IMAP test:
openssl s_client -connect mail.example.com:993
a login bob@example.com yourpassword
a logout
  1. SMTP test with swaks:
swaks --to test@otherdomain.com --from bob@example.com --server mail.example.com:587 \
      --auth LOGIN --auth-user bob@example.com --auth-password 'yourpass' --tls
  1. If it says Authentication successful and the mail is queued, you’re good.
  2. Roundcube test:

10. Managing Users

10.1 Creating a New Mail User

  • Generate a hashed password:
doveadm pw -s SHA512-CRYPT
  • Insert into MySQL:
USE mailserver;
INSERT INTO mailbox (username, password, name, maildir, quota, local_part, domain, created, modified, active)
VALUES (
  'alice@example.com',
  '{SHA512-CRYPT}$6$...',
  'Alice Smith',
  'example.com/alice/',
  0,
  'alice',
  'example.com',
  NOW(),
  NOW(),
  1
);
  • Domain must exist in the domain table.
  • That’s it—Postfix & Dovecot will pick it up immediately.

10.2 Aliases

If you want alias@domain.com to deliver into bob@domain.com:

INSERT INTO alias (address, goto, domain, created, modified, active)
VALUES (
  'alias@domain.com',
  'bob@domain.com',
  'domain.com',
  NOW(),
  NOW(),
  1
);

11. Enabling Sent Folders & Basic Roundcube Customization

11.1 Sent Folder Setup

Roundcube ? Settings ? Preferences ? Composing Messages:

  • Save sent messages ? “Sent” folder.
  • Subscribe to “Sent” in Roundcube’s Settings ? Folders.

11.2 Auto-Creation of Folders in Dovecot

/etc/dovecot/conf.d/15-mailboxes.conf example:

namespace inbox {
  inbox = yesmailbox Drafts {
    special_use = \Draftsauto = create
  }
  mailbox Sent {
    special_use = \Sentauto = create
  }
  mailbox Junk {
    special_use = \Junkauto = create
  }
  mailbox Trash {
    special_use = \Trashauto = create
  }
}

11.3 Adding an Outbox (Optional)

You can create a normal IMAP folder called “Outbox.” However, Roundcube does not queue mail there by default. If you want true “send later” or “outbox” functionality, you need a plugin or custom behavior.

12. Troubleshooting Tips

  • Check mail logs:
  • /var/log/mail.log or /var/log/maillog for Postfix & Dovecot messages.
  • /var/log/roundcube/errors.log for Roundcube logs.
  • Verify Postfix is offering AUTH:
openssl s_client -starttls smtp -connect mail.example.com:587
EHLO test
# Must see: 250-AUTH PLAIN LOGIN
  • Ensure Dovecot’s auth_mechanisms = plain login, plus the socket is at /var/spool/postfix/private/auth with correct permissions.
  • MySQL queries: use postmap -q youruser@example.com mysql:/etc/postfix/mysql-...cf to confirm Postfix sees the right maildir or alias.
  • SELinux/AppArmor: if in “enforcing” mode, may block the socket. Consider checking or disabling for testing.
  • For Roundcube issues, enable $config['smtp_debug'] = true; to see exactly how Roundcube is talking to your SMTP server.

Conclusion

You now have a complete mail server with:

  1. Postfix for SMTP inbound/outbound.
  2. Dovecot for IMAP/POP3 and user authentication (using MySQL).
  3. Roundcube providing a modern webmail interface.

You can manage new domains and users simply by inserting rows into the MySQL domain, mailbox, and alias tables. Roundcube’s settings let you control sent/drafts folders, and with Dovecot’s auto-creation, users get a straightforward mail experience. Keep an eye on your SSL certificates, watch your logs for errors, and enjoy your fully functional mail system!

IMREAL.LIFE

Close