Back to tutorials
Tutorial

Set Up Roundcube Webmail on a VPS With HTTPS

Host Roundcube webmail on your VPS with Nginx + HTTPS, then connect it to Postfix/Dovecot for secure browser email access.

By Anurag Singh
Updated on Oct 31, 2026
Category: Tutorial
Share article
Set Up Roundcube Webmail on a VPS With HTTPS

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.com via 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/AAAA record for webmail.
  • Ports open to clients: 80/443 to the webmail VPS. From the webmail VPS to your mail server: 993 (IMAPS) and 587 (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 (or tls://127.0.0.1 if local) on 993
  • SMTP host: tls://mail.example.com on 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 %n for 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.

  1. Web reachability + TLS

    curl -I https://webmail.example.com/

    You want HTTP/2 200 or a 302 to the login page, and no certificate warnings in the browser.

  2. Login via IMAP

    Open the web UI, log in with a real mailbox, and confirm folders load.

  3. Send a message

    Send to a Gmail/Outlook address and also to another mailbox on your domain. Confirm the Sent folder updates.

  4. Watch logs while testing

    sudo tail -f /var/log/nginx/webmail.error.log

    Also 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/temp is writable by www-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.