
You don’t need a full mail suite to get a solid webmail interface. If you already run IMAP (Dovecot) and SMTP (Postfix), you can host Roundcube webmail on the same VPS (or on a separate VPS). You don’t need to change how mail is delivered.
This walkthrough puts Roundcube behind Nginx with Let’s Encrypt TLS. It connects Roundcube to your existing mail services. It also adds a few small hardening steps that prevent the usual “why is webmail broken?” surprises.
What you’ll build (and what you need first)
By the end, you’ll have:
- Roundcube served at
https://webmail.example.comvia Nginx - PHP-FPM tuned for a webmail workload
- Roundcube configured to talk to Dovecot IMAP (993) and Postfix submission (587)
- A working login, inbox view, and send test
Assumptions / prerequisites:
- A VPS running Ubuntu 24.04 LTS or Debian 12 (commands below target these). AlmaLinux/Rocky notes are included where it differs.
- You already have working email accounts on a mail server running Postfix + Dovecot. That can be the same VPS or a different host.
- A domain you control, and DNS access to create an
A/AAAArecord forwebmail. - Ports open to clients:
80/443to the webmail VPS. From the webmail VPS to your mail server:993(IMAPS) and587(submission). (If Roundcube runs on the same box as Dovecot/Postfix, it’s local.)
If you need to fix deliverability basics (SPF/DKIM/DMARC) before exposing webmail publicly, use Set up DKIM, SPF, and DMARC for a domain.
Hosting note: Roundcube is small, but it is still a public-facing PHP app. Run it on a VPS you can patch quickly.
Monitor it like any other internet-exposed service.
A small HostMyCode VPS is a sensible baseline for most webmail installs.
Step 1: Point DNS for webmail to your VPS
Create DNS records:
webmail.example.com→ A record to your VPS IPv4- (Optional)
webmail.example.com→ AAAA record to your VPS IPv6
Verify from your laptop:
dig +short webmail.example.com A
dig +short webmail.example.com AAAA
Common mistake: enabling a CDN/proxy for webmail before the origin works.
Webmail can run behind many proxies, but start direct-to-origin. You’ll know exactly what you’re debugging.
If you are moving DNS providers, use this DNS migration without-downtime process. It helps you avoid breaking mail-related records during the cutover.
Step 2: Install Nginx, PHP-FPM, and MariaDB (Ubuntu/Debian)
Update packages and install the stack:
sudo apt update
sudo apt -y install nginx mariadb-server \
php-fpm php-mysql php-xml php-mbstring php-intl php-curl php-zip php-gd \
unzip curl ca-certificates
Check services:
systemctl status nginx --no-pager
systemctl status php*-fpm --no-pager
systemctl status mariadb --no-pager
Find your PHP-FPM socket path (you’ll need it for Nginx):
ls -1 /run/php/
On Ubuntu 24.04, you’ll typically see something like php8.3-fpm.sock. On Debian 12, it is often php8.2-fpm.sock. Use whatever your server actually has.
AlmaLinux/Rocky note: use dnf install and PHP from AppStream/Remi as needed, plus php-fpm, nginx, mariadb-server. The Roundcube packaging differs, so this tutorial stays with the upstream tarball method for consistency.
Step 3: Create a database and user for Roundcube
Secure MariaDB if this server is fresh:
sudo mysql_secure_installation
Create the DB and user (pick a strong password):
sudo mysql -u root -p <<'SQL'
CREATE DATABASE roundcube DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'roundcube'@'localhost' IDENTIFIED BY 'REPLACE_WITH_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON roundcube.* TO 'roundcube'@'localhost';
FLUSH PRIVILEGES;
SQL
Quick check:
sudo mysql -u roundcube -p -e "SHOW DATABASES;"
Step 4: Download and install Roundcube under /var/www
Install the latest stable Roundcube release available when you deploy. As of 2026, security releases still arrive regularly.
Plan to update it, not “set and forget.”
Create directories:
sudo mkdir -p /var/www/roundcube
sudo chown -R www-data:www-data /var/www/roundcube
Download Roundcube, extract, and place it:
cd /tmp
# Replace the URL with the current stable tarball from roundcube.net
curl -fL -o roundcube.tar.gz https://github.com/roundcube/roundcubemail/releases/latest/download/roundcubemail-complete.tar.gz
sudo tar -xzf roundcube.tar.gz
# The extracted folder name varies; list it
ls -1
# Example (adjust): sudo rsync -a roundcubemail-*/ /var/www/roundcube/
sudo rsync -a roundcubemail-*/ /var/www/roundcube/
sudo chown -R www-data:www-data /var/www/roundcube
Confirm expected files exist:
ls -1 /var/www/roundcube | head
Step 5: Import the Roundcube database schema
The schema file lives under SQL/:
ls -1 /var/www/roundcube/SQL
Import for MariaDB/MySQL:
sudo mysql -u roundcube -p roundcube < /var/www/roundcube/SQL/mysql.initial.sql
Verify tables were created:
sudo mysql -u roundcube -p -e "USE roundcube; SHOW TABLES;"
Step 6: Configure Nginx for webmail.example.com
Create an Nginx server block. This config focuses on three things:
- Serves Roundcube from
/var/www/roundcube - Passes PHP to PHP-FPM via a Unix socket
- Blocks direct access to sensitive folders like
/config,/temp, and/logs
Create the file:
sudo nano /etc/nginx/sites-available/webmail.example.com
Paste (adjust server_name and PHP socket path):
server {
listen 80;
listen [::]:80;
server_name webmail.example.com;
root /var/www/roundcube/public_html;
index index.php index.html;
# Roundcube from upstream tarball often uses the root as web root.
# If /public_html doesn't exist, point root to /var/www/roundcube instead.
access_log /var/log/nginx/webmail.access.log;
error_log /var/log/nginx/webmail.error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
# Block common sensitive paths
location ~ ^/(config|temp|logs)/ {
deny all;
return 404;
}
location ~ ^/SQL/ {
deny all;
return 404;
}
location ~* \.(?:ini|log|conf|dist)$ {
deny all;
return 404;
}
client_max_body_size 25m;
}
Fix the web root if needed. Many Roundcube builds use the main directory as the web root.
If /var/www/roundcube/public_html doesn’t exist, change root to:
root /var/www/roundcube;
Enable the site and test Nginx:
sudo ln -s /etc/nginx/sites-available/webmail.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
If you get a 502 here, it is usually one of two things:
- The PHP-FPM socket path is wrong.
- PHP-FPM isn’t running.
Use this checklist and re-check your fastcgi_pass: Nginx 502 Bad Gateway fix on Ubuntu VPS.
Step 7: Issue a TLS certificate (Let’s Encrypt) for Roundcube
Install Certbot for Nginx:
sudo apt -y install certbot python3-certbot-nginx
Request the certificate and let Certbot update your Nginx config:
sudo certbot --nginx -d webmail.example.com
Verify auto-renewal:
sudo systemctl status certbot.timer --no-pager
sudo certbot renew --dry-run
If you need a deeper SSL troubleshooting checklist (chain problems, mixed content, HSTS gotchas), follow this TLS setup guide for 2026.
Step 8: Run the Roundcube installer and lock it down
Roundcube ships with a web installer that generates a clean baseline config. Keep it available long enough to run the wizard.
When you finish, remove it.
Ensure the installer directory exists:
ls -1 /var/www/roundcube/installer
Open in your browser:
https://webmail.example.com/installer/
Follow the steps:
- Database setup: MySQL/MariaDB
- Database name:
roundcube - DB user:
roundcube - DB password: your chosen password
Then set IMAP/SMTP (you’ll make this more explicit in the next step):
- IMAP host:
tls://mail.example.com(ortls://127.0.0.1if local) on 993 - SMTP host:
tls://mail.example.comon 587 - SMTP authentication: enabled, with “use current login/password”
When the installer generates a config, it typically outputs content you paste into a file. Create it at:
sudo nano /var/www/roundcube/config/config.inc.php
Make sure it’s owned by the web user and not world-readable:
sudo chown www-data:www-data /var/www/roundcube/config/config.inc.php
sudo chmod 640 /var/www/roundcube/config/config.inc.php
Disable the installer once you’re done:
sudo rm -rf /var/www/roundcube/installer
Don’t skip this. Leaving the installer reachable is one of the most common ways PHP apps get compromised.
Step 9: Configure Roundcube for your Postfix/Dovecot setup
Now make the main config deliberate and boring. Use explicit TLS and explicit ports.
Avoid any fallback to plaintext.
sudo nano /var/www/roundcube/config/config.inc.php
Use these settings as a baseline (adjust hostnames):
<?php
$config['db_dsnw'] = 'mysql://roundcube:REPLACE_WITH_STRONG_PASSWORD@localhost/roundcube';
// Where users log in (Dovecot IMAP)
$config['imap_host'] = 'tls://mail.example.com:993';
// Where Roundcube submits outbound mail (Postfix submission)
$config['smtp_host'] = 'tls://mail.example.com:587';
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
// Ensure Roundcube itself uses a stable product name and correct URLs
$config['product_name'] = 'Webmail';
$config['default_host'] = 'tls://mail.example.com';
// If your IMAP server expects full email address as username, keep %u.
// If it expects only the local part, you can switch to %n.
// Good defaults
$config['des_key'] = 'REPLACE_WITH_A_LONG_RANDOM_STRING_24+CHARS';
$config['plugins'] = ['archive', 'zipdownload'];
// Prefer modern ciphers; most admins can rely on system defaults.
Pick the right username format:
- If Dovecot logins are
user@example.com, keep%u. - If Dovecot logins are just
user, use%nfor SMTP auth.
Reload services. This is not always required for PHP, but it clears state.
It also helps with troubleshooting:
sudo systemctl reload php8.3-fpm 2>/dev/null || true
sudo systemctl reload nginx
TLS verification tip: From the Roundcube VPS, confirm your mail server presents a valid certificate. Also confirm the hostname matches what you configured:
openssl s_client -connect mail.example.com:993 -servername mail.example.com -brief
openssl s_client -connect mail.example.com:587 -servername mail.example.com -starttls smtp -brief
If these show certificate errors, Roundcube logins will be unreliable or fail completely. Fix the mail server TLS first.
Step 10: Fix file permissions and PHP settings that break attachments
Roundcube writes temporary files for attachments and caching. Those directories should be writable by www-data, not by everyone.
Confirm directories and permissions:
sudo find /var/www/roundcube -maxdepth 1 -type d -name 'temp' -o -name 'logs' -print
sudo chown -R www-data:www-data /var/www/roundcube/temp /var/www/roundcube/logs 2>/dev/null || true
sudo chmod -R 750 /var/www/roundcube/temp /var/www/roundcube/logs 2>/dev/null || true
Now check PHP upload limits. Many VPS defaults cap uploads at 2 MB.
That turns “attach a PDF” into a support ticket.
Edit PHP-FPM config (adjust version):
sudo nano /etc/php/8.3/fpm/php.ini
Set realistic limits for webmail:
upload_max_filesize = 25M
post_max_size = 25M
memory_limit = 256M
max_execution_time = 60
Restart PHP-FPM:
sudo systemctl restart php8.3-fpm
Verify with a quick PHP info file, then remove it:
echo "<?php phpinfo();" | sudo tee /var/www/roundcube/phpinfo.php
curl -s https://webmail.example.com/phpinfo.php | grep -E 'upload_max_filesize|post_max_size' | head
sudo rm -f /var/www/roundcube/phpinfo.php
Step 11: Add a few Nginx headers (without breaking webmail)
Some themes and plugins rely on inline scripts and styles. If you clamp down too hard with CSP, you can end up with a blank UI.
Start with a small set of safe headers. Tighten later if you want.
Edit your TLS-enabled server block (Certbot may have split it into a listen 443 ssl block):
sudo nano /etc/nginx/sites-available/webmail.example.com
Inside the server block for 443, add:
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header Referrer-Policy strict-origin-when-cross-origin always;
add_header Permissions-Policy interest-cohort=() always;
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
Step 12: Verify end-to-end (login, IMAP, SMTP send, logs)
Run these checks in order. You’ll isolate problems faster.
-
Web reachability + TLS
curl -I https://webmail.example.com/You want
HTTP/2 200or a302to the login page, and no certificate warnings in the browser. -
Login via IMAP
Open the web UI, log in with a real mailbox, and confirm folders load.
-
Send a message
Send to a Gmail/Outlook address and also to another mailbox on your domain. Confirm the Sent folder updates.
-
Watch logs while testing
sudo tail -f /var/log/nginx/webmail.error.logAlso check Roundcube’s own logs (path varies; common locations below):
sudo ls -lah /var/www/roundcube/logs 2>/dev/null || true sudo tail -f /var/www/roundcube/logs/errors.log 2>/dev/null || true
If SMTP fails but IMAP works, start with Postfix submission.
Check the port, TLS, and username format.
If you’re building the mail server from scratch, this Postfix + SPF/DKIM tutorial pairs well with Roundcube.
Hardening checklist that matters for webmail
- Patch cadence: keep OS, PHP, and Roundcube updated. Webmail attracts constant probing.
- Firewall: only open 80/443 to the world. Don’t expose MariaDB externally. If Roundcube talks to a remote mail server, allow 587/993 outbound.
- Fail2ban (optional but useful): ban repeated login attempts based on Nginx logs. If you already run it for other sites, add a jail for
webmail.access.log. - Disable installer: already done. Keep it that way.
- Backups: back up Roundcube config + DB. The DB stores identities, address books, and preferences.
If you want unattended security patches on Ubuntu, follow Set up automated security updates on Ubuntu VPS.
Back up Roundcube (and test a restore)
Roundcube backups are straightforward because there are only three moving parts: files, config, and the database.
1) Back up the database:
sudo mkdir -p /root/backups/roundcube
sudo mysqldump --single-transaction roundcube | gzip > /root/backups/roundcube/roundcube.sql.gz
2) Back up config (and optionally the full directory):
sudo tar -czf /root/backups/roundcube/roundcube-config.tgz -C /var/www/roundcube config
# Optional: full app backup (bigger)
sudo tar -czf /root/backups/roundcube/roundcube-app.tgz -C /var/www roundcube
3) Test restore (quick sanity check): restore into a new database name and confirm tables exist.
sudo mysql -u root -p -e "CREATE DATABASE roundcube_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
zcat /root/backups/roundcube/roundcube.sql.gz | sudo mysql -u root -p roundcube_restore
sudo mysql -u root -p -e "USE roundcube_restore; SHOW TABLES;"
That restore test is the part people skip. It is also the part that saves you during an outage.
Troubleshooting: the failures you’ll actually see
-
Blank page after login: check the browser console for blocked assets. Then review Nginx error logs.
A too-strict header or a PHP fatal error is the usual cause.
-
IMAP connection failed: confirm Dovecot is listening on 993 and the certificate is valid. Run:
openssl s_client -connect mail.example.com:993 -servername mail.example.com -brief -
SMTP authentication failed: confirm you’re using submission on 587, not port 25.
Then verify whether the server expects full email-address usernames.
-
Attachments fail: raise PHP upload limits and confirm
/var/www/roundcube/tempis writable bywww-data. -
502 Bad Gateway: wrong PHP-FPM socket or PHP-FPM down. Use this 502 fix guide and re-check
fastcgi_pass.
Summary: a clean Roundcube deployment that stays maintainable
You now have Roundcube behind Nginx with HTTPS. It is connected to your existing Postfix/Dovecot services.
The installer is removed, and you have backups you can restore.
Keep it boring. Apply updates promptly. Watch the Nginx error log.
Occasionally test login + send from outside your network.
If you’d rather not maintain PHP, Nginx, updates, and mail connectivity yourself, managed VPS hosting is a practical option. If you’re running it yourself, start with a right-sized HostMyCode VPS so you have predictable performance and root access when something needs fixing.
If you’re putting webmail on the public internet, run it like production software: patch on a schedule, keep logs readable, and prove your backups restore cleanly. HostMyCode helps by providing predictable Linux environments and support that’s familiar with real-world mail stacks.
Start with a HostMyCode VPS, or choose managed VPS hosting if you want help keeping Nginx/PHP and security updates under control.
FAQ
Can I host Roundcube on a different VPS than my mail server?
Yes. Roundcube only needs network access to IMAPS (993) and submission (587) on your mail server.
Make sure TLS is valid and the mail server allows those connections from the Roundcube VPS.
Should Roundcube connect to SMTP on port 25 or 587?
Use 587 (submission) with authentication. Port 25 is for server-to-server delivery and is often rate-limited or blocked by providers.
Do I need MariaDB if I don’t care about address books?
Roundcube can run with minimal storage, but MariaDB is strongly recommended. Preferences, identities, and address books make webmail usable day-to-day.
How do I update Roundcube safely?
Back up the DB and config/, unpack the new release into a fresh directory, copy config/ over, run any provided update steps, then switch the Nginx root (or replace files) during a short maintenance window.
What’s the quickest way to confirm the issue is IMAP vs SMTP?
If login fails, it’s IMAP (or PHP). If login works but sending fails, it’s SMTP submission/auth. Use the openssl s_client checks for 993 and 587 to validate connectivity and TLS.