This guide explains how to install Roundcube manually on Ubuntu 26.04 with Nginx, PHP 8.5, MariaDB, Postfix, Dovecot, and PostfixAdmin.
Because the packaged Roundcube version may not work correctly with PHP 8.5, this guide installs Roundcube manually from the official release archive.
1. Download and Extract Roundcube
Change to the web directory:
cd /var/www
Download Roundcube 1.6.12:
sudo wget https://github.com/roundcube/roundcubemail/releases/download/1.6.12/roundcubemail-1.6.12-complete.tar.gz
Extract the archive:
sudo tar -xzf roundcubemail-1.6.12-complete.tar.gz
Rename the extracted directory:
sudo mv roundcubemail-1.6.12 roundcube
2. Install Composer
Check whether Composer is already installed:
composer --version
If Composer is not installed, install it:
sudo apt update sudo apt install -y composer
3. Install Roundcube Dependencies
Change to the Roundcube directory:
cd /var/www/roundcube
Install the required Composer dependencies:
composer install --no-dev
4. Set File Permissions
Set the Roundcube files to be owned by the Nginx and PHP user:
sudo chown -R www-data:www-data /var/www/roundcube
Set directory permissions:
sudo find /var/www/roundcube -type d -exec chmod 755 {} \;
Set file permissions:
sudo find /var/www/roundcube -type f -exec chmod 644 {} \;
5. Create the Roundcube Web Link
First, check whether the Roundcube installation contains a public_html directory:
ls -l /var/www/roundcube
If the public_html directory exists, create this symbolic link:
sudo ln -s /var/www/roundcube/public_html /var/www/html/roundcube
If public_html does not exist, link the complete Roundcube directory instead:
sudo rm -f /var/www/html/roundcube sudo ln -s /var/www/roundcube /var/www/html/roundcube
Restart Nginx and PHP-FPM:
sudo systemctl restart nginx sudo systemctl restart php8.5-fpm
6. Create the Roundcube Configuration File
Check whether the configuration file already exists:
ls -l /var/www/roundcube/config/config.inc.php
If the file does not exist, create it from the sample configuration:
sudo cp /var/www/roundcube/config/config.inc.php.sample \ /var/www/roundcube/config/config.inc.php
If an older Roundcube configuration still exists under /etc/roundcube, you can copy it:
sudo cp /etc/roundcube/config.inc.php /var/www/roundcube/config/
After copying an older configuration, review it carefully because some settings may not match the manually installed Roundcube version.
7. Configure the Roundcube Database
First, check whether the Roundcube database already exists:
sudo mariadb -e "SHOW DATABASES LIKE 'roundcubemail';"
If the command returns roundcubemail, the database already exists.
Set a New Database Password
Open MariaDB:
sudo mariadb
Set a new password for the Roundcube database user:
ALTER USER 'roundcube'@'localhost' IDENTIFIED BY 'YOUR_STRONG_ROUNDCUBE_DB_PASSWORD'; FLUSH PRIVILEGES; EXIT;
Replace YOUR_STRONG_ROUNDCUBE_DB_PASSWORD with a strong password.
Update the Roundcube Database Connection
Use the same password that you assigned to the MariaDB user.
9. Create the Roundcube Database if It Does Not Exist
If this command returns nothing:
sudo mariadb -e "SHOW DATABASES LIKE 'roundcubemail';"
create the database manually.
Open MariaDB:
sudo mariadb
Create the database and database user:
CREATE DATABASE roundcubemail CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER IF NOT EXISTS 'roundcube'@'localhost' IDENTIFIED BY 'YOUR_STRONG_ROUNDCUBE_DB_PASSWORD'; ALTER USER 'roundcube'@'localhost' IDENTIFIED BY 'YOUR_STRONG_ROUNDCUBE_DB_PASSWORD'; GRANT ALL PRIVILEGES ON roundcubemail.* TO 'roundcube'@'localhost'; FLUSH PRIVILEGES; EXIT;
Import the Roundcube Database Schema
sudo mariadb roundcubemail \ < /var/www/roundcube/SQL/mysql.initial.sql
Restart PHP-FPM:
sudo systemctl restart php8.5-fpm
8. Enable the Roundcube Installer Temporarily
Edit the Roundcube configuration:
sudo nano /var/www/roundcube/config/config.inc.php
Find:
$config['enable_installer'] = false;
Change it to:
$config['enable_installer'] = true;
If the setting does not exist, add this line at the end of the file:
$config['enable_installer'] = true;
You can check whether the setting exists with:
grep enable_installer /var/www/roundcube/config/config.inc.php
Find a line similar to:
$config['db_dsnw'] = 'mysql://roundcube:pass@localhost/roundcubemail';
Change it to:
$config['db_dsnw'] = 'mysql://roundcube:YOUR_STRONG_ROUNDCUBE_DB_PASSWORD@localhost/roundcubemail';
Configure Roundcube IMAP and SMTP
For SSL add or update the following settings, be carefull, they could already exist:
$config['imap_host'] = 'ssl://mail.myDomain.com'; $config['default_port'] = 993; $config['smtp_host'] = 'tls://mail.myDomain.com'; $config['smtp_port'] = 587; $config['smtp_user'] = '%u'; $config['smtp_pass'] = '%p'; $config['product_name'] = 'My Webmail';
Without SSL first check if returns nothing:
sudo doveconf -n | grep disable_plaintext_auth
$config['imap_host'] = 'localhost:143'; $config['smtp_host'] = 'localhost:587'; $config['smtp_user'] = '%u'; $config['smtp_pass'] = '%p'; $config['product_name'] = 'My Webmail';
To disable certificate add:
$config['imap_conn_options'] = [
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
],
];
Replace mail.myDomain.com with your mail server hostname.
Save the file in Nano:
Ctrl+O Enter Ctrl+X
Restart PHP-FPM and Nginx:
sudo systemctl restart php8.5-fpm sudo systemctl restart nginx
Temporarily point the symlink to the complete Roundcube directory:
Remove the existing symlink:
sudo rm /var/www/html/roundcube
Create a temporary installation symlink:
sudo ln -s /var/www/roundcube /var/www/html/roundcube
Open the Roundcube installer in your browser:
http://mail.myDomain.com/roundcube/installer/
If you cant Test IMAP config then execute
sudo journalctl -u dovecot -f
Check, password should be without hash and user "user" should have access to database mailserver
sudo nano /etc/dovecot/dovecot-sql.conf.ext
For dovecot --version: 2.4.2 (0962ed2104) looks like:
sql_driver = mysql
mysql localhost {
user = postfixadmin
password = YOUR_POSTFIXADMIN_PASSWORD
dbname = mailserver
}
passdb sql {
default_password_scheme = ARGON2ID
query = \
SELECT password \
FROM mailbox \
WHERE username = '%{user}' AND active = 1
}
userdb static {
fields {
uid = vmail
gid = vmail
home = /var/mail/vhosts/%{user|domain}/%{user|username}
mail_driver = maildir
mail_path = ~/Maildir
}
}
mariadb -u user -p mailserver
sudo mariadb -e "SHOW GRANTS FOR 'user'@'localhost';"
sudo doveadm auth test email@myDomain.com YOUR_MAILBOX_PASSWORD
php -m | grep -i imap
php -r '$fp = stream_socket_client("ssl://mail.testmail.milosev.com:993", $errno, $errstr, 10); var_dump($fp, $errno, $errstr);'
Replace myDomain.com with your own domain name.
11. Restore Dovecot SQL Authentication if Required
This section is only required if Dovecot SQL authentication was lost during a reinstall or package replacement.
Ubuntu 26.04 ships Dovecot 2.4. Dovecot 2.4 configuration syntax differs from Dovecot 2.3, so old Dovecot 2.3 examples should not be copied directly.
Configure Dovecot 2.4 SQL Authentication
Edit the SQL authentication configuration:
sudo nano /etc/dovecot/conf.d/auth-sql.conf.ext
Replace its contents with:
sql_driver = mysql
mysql 127.0.0.1 {
user = postfixadmin
password = YOUR_POSTFIXADMIN_DATABASE_PASSWORD
dbname = mailserver
}
passdb sql {
default_password_scheme = ARGON2ID
query = SELECT username AS "user", password \
FROM mailbox \
WHERE username='%{user}' AND active='1'
}
userdb sql {
query = SELECT CONCAT('/var/mail/vhosts/', SUBSTRING_INDEX(username,'@',-1), '/', SUBSTRING_INDEX(username,'@',1)) AS home, 5000 AS uid, 5000 AS gid FROM mailbox WHERE username='%{user}' AND active='1'
iterate_query = SELECT username AS "user" FROM mailbox WHERE active='1'
}
Replace YOUR_POSTFIXADMIN_DATABASE_PASSWORD with the MariaDB password used by the postfixadmin database user.
Validate the Dovecot Configuration
sudo doveconf -n
If no errors are displayed, restart Dovecot:
sudo systemctl restart dovecot
Check its status:
sudo systemctl status dovecot --no-pager
Test Mailbox Authentication
sudo doveadm auth test username@myDomain.com
Dovecot will prompt you for the mailbox password.
12. Reset a Mailbox Password for Testing
If authentication fails, reset the mailbox password to a password you know.
Change to the PostfixAdmin installation directory:
cd /var/www/postfixadmin
Reset the mailbox password:
php scripts/postfixadmin-cli.php mailbox update username@myDomain.com \ --password "Test123456!" \ --password2 "Test123456!"
Test authentication again:
sudo doveadm auth test username@myDomain.com
Enter:
Test123456!
13. Configure Postfix MariaDB Maps
Postfix needs MariaDB map files to look up virtual domains, mailboxes, and aliases stored by PostfixAdmin.
Create the Virtual Domain Map
sudo nano /etc/postfix/mysql-virtual-mailbox-domains.cf
Paste:
user = postfixadmin password = YOUR_POSTFIXADMIN_DATABASE_PASSWORD hosts = 127.0.0.1 dbname = mailserver query = SELECT domain FROM domain WHERE domain='%s' AND active='1'
To be sure that password is correct execute:
mysql -h 127.0.0.1 -u postfixadmin -p mailserver
And enter YOUR_POSTFIXADMIN_DATABASE_PASSWORD
If you forgot password:
ALTER USER 'postfixadmin'@'localhost' IDENTIFIED BY 'YOUR_POSTFIXADMIN_DATABASE_PASSWORD'; FLUSH PRIVILEGES; EXIT;
Create the Virtual Mailbox Map
sudo nano /etc/postfix/mysql-virtual-mailbox-maps.cf
Paste:
user = postfixadmin password = YOUR_POSTFIXADMIN_DATABASE_PASSWORD hosts = 127.0.0.1 dbname = mailserver query = SELECT CONCAT(maildir,'Maildir/') FROM mailbox WHERE username='%s' AND active='1'
Create the Virtual Alias Map
sudo nano /etc/postfix/mysql-virtual-alias-maps.cf
Paste:
user = postfixadmin password = YOUR_POSTFIXADMIN_DATABASE_PASSWORD hosts = 127.0.0.1 dbname = mailserver query = SELECT goto FROM alias WHERE address='%s' AND active='1'
Replace YOUR_POSTFIXADMIN_DATABASE_PASSWORD in all three files with the actual database password.
Secure the Postfix Database Files
sudo chmod 640 /etc/postfix/mysql-virtual-*.cf sudo chown root:postfix /etc/postfix/mysql-virtual-*.cf
14. Update the Postfix Main Configuration
Edit the Postfix configuration:
sudo nano /etc/postfix/main.cf
Add or update these settings:
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 virtual_transport = virtual virtual_mailbox_base = /var/mail/vhosts virtual_minimum_uid = 5000 virtual_uid_maps = static:5000 virtual_gid_maps = static:5000
Restart Postfix:
sudo systemctl restart postfix
Verify the virtual mailbox configuration:
postconf -n | grep virtual
15. Verify the Postfix Database Queries
Test whether Postfix can find a virtual domain:
postmap -q myDomain.com \ mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
Test whether Postfix can find a mailbox:
postmap -q username@myDomain.com \ mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
Test whether Postfix can find an alias:
postmap -q username@myDomain.com \ mysql:/etc/postfix/mysql-virtual-alias-maps.cf
16. Complete the Roundcube Installer
Return to the Roundcube installer:
http://mail.myDomain.com/roundcube/installer/
Check that all required PHP extensions and database connections are working, then complete the installation.
17. Disable and Remove the Installer
For security reasons, disable the installer after completing the installation.
Edit the Roundcube configuration:
sudo nano /var/www/roundcube/config/config.inc.php
Change:
$config['enable_installer'] = true;
to:
$config['enable_installer'] = false;
Remove the installer directory:
sudo rm -rf /var/www/roundcube/installer
Restart PHP-FPM and Nginx:
sudo systemctl restart php8.5-fpm sudo systemctl restart nginx
18. Log In to Roundcube
You can now open Roundcube at:
http://mail.myDomain.com/roundcube/
Log in with the complete mailbox address and mailbox password, for example:
username@myDomain.com
19. Check Services and Logs
Check the status of Nginx, PHP-FPM, MariaDB, Dovecot, and Postfix:
sudo systemctl status nginx --no-pager sudo systemctl status php8.5-fpm --no-pager sudo systemctl status mariadb --no-pager sudo systemctl status dovecot --no-pager sudo systemctl status postfix --no-pager
Check the Nginx error log:
sudo tail -n 100 /var/log/nginx/error.log
Check the mail log:
sudo tail -n 100 /var/log/mail.log
Follow the mail log in real time:
sudo tail -f /var/log/mail.log
Check recent Dovecot messages:
sudo journalctl -u dovecot -n 100 --no-pager
Check recent PHP-FPM messages:
sudo journalctl -u php8.5-fpm -n 100 --no-pager