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
- Introduction
- Prerequisites & Basic System Setup
- Install Required Packages
- Configure MySQL for Virtual Domains & Users
- Configure Postfix
- Configure Dovecot
- Configure Roundcube
- SSL Certificates with Let’s Encrypt (Optional)
- Testing the Setup
- Managing Users
- Enabling Sent Folders & Basic Roundcube Customization
- 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
- Ubuntu or Debian server with root or sudo privileges.
- A FQDN (Fully Qualified Domain Name) for your mail server, e.g.
mail.example.com
. - DNS records pointing
mail.example.com
to your server’s IP. - 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.
- 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
(orforwardings
) 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 byroot:root
and has0600
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
- Check Postfix is listening on ports 25 & 587:
sudo ss -plnt | grep ':25\|:587'
- Check Dovecot on ports 143/993:
sudo ss -plnt | grep ':993\|:143'
- IMAP test:
openssl s_client -connect mail.example.com:993 a login bob@example.com yourpassword a logout
- 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
- If it says
Authentication successful
and the mail is queued, you’re good. - Roundcube test:
- Go to
https://mail.example.com/roundcube
. - Log in with
bob@example.com
+ your pass. - Send a test email. Check logs in
/var/log/mail.log
and/var/log/roundcube/errors.log
.
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:
- Postfix for SMTP inbound/outbound.
- Dovecot for IMAP/POP3 and user authentication (using MySQL).
- 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!