How to Self-Host Roundcube: Open Source Webmail 2026
TL;DR
Roundcube (GPL 3.0, ~5K GitHub stars, PHP) is the most widely deployed open source webmail client — it powers the webmail interface for millions of hosting providers worldwide. Unlike SOGo (used in Mailcow) which targets enterprise, Roundcube is lean and focused: fast IMAP webmail with a clean UI, PGP encryption via Enigma plugin, CardDAV contacts via plugin, and a responsive "Elastic" skin that works on mobile. If you run your own mail server (Mailcow, Stalwart, Postfix+Dovecot) and want a webmail UI, Roundcube is the go-to option.
Key Takeaways
- Roundcube: GPL 3.0, ~5K stars, PHP — most widely deployed open source webmail
- IMAP-only: Roundcube connects to any IMAP server — not tied to a specific mail backend
- Elastic skin: Modern responsive skin that works well on mobile
- Enigma plugin: PGP email encryption/decryption built-in
- Plugin ecosystem: CardDAV contacts, 2FA, HTML signatures, calendar preview, and more
- vs SOGo: Roundcube is simpler, faster, and easier to theme; SOGo includes calendar/contacts natively
Part 1: Docker Setup
# docker-compose.yml
services:
roundcube:
image: roundcube/roundcubemail:latest
container_name: roundcube
restart: unless-stopped
ports:
- "9090:80"
volumes:
- roundcube_config:/var/roundcube/config
- roundcube_db:/var/roundcube/db
- roundcube_temp:/tmp/roundcube-temp
- roundcube_logs:/var/log/roundcube
environment:
# IMAP server (your mail server):
ROUNDCUBEMAIL_DEFAULT_HOST: "tls://mail.yourdomain.com"
ROUNDCUBEMAIL_DEFAULT_PORT: 993
# SMTP server for sending:
ROUNDCUBEMAIL_SMTP_SERVER: "tls://mail.yourdomain.com"
ROUNDCUBEMAIL_SMTP_PORT: 587
# Database (SQLite for simple setup):
ROUNDCUBEMAIL_DB_TYPE: sqlite
# Session security:
ROUNDCUBEMAIL_DES_KEY: "rcdeskeyrandomchange" # 24 chars
# UI settings:
ROUNDCUBEMAIL_SKIN: elastic
ROUNDCUBEMAIL_LANGUAGE: en_US
# Upload size limit:
ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE: 25M
# Enable plugins:
ROUNDCUBEMAIL_PLUGINS: "archive,zipdownload,carddav,enigma"
volumes:
roundcube_config:
roundcube_db:
roundcube_temp:
roundcube_logs:
docker compose up -d
Visit http://your-server:9090 (or via Caddy at https://mail.yourdomain.com/webmail).
Part 2: HTTPS with Caddy
Standalone webmail subdomain
webmail.yourdomain.com {
reverse_proxy localhost:9090
}
Subpath under existing domain
mail.yourdomain.com {
# Admin UI:
handle /admin* {
reverse_proxy localhost:8080
}
# Webmail:
handle /webmail* {
uri strip_prefix /webmail
reverse_proxy localhost:9090
}
# Default → webmail:
handle {
reverse_proxy localhost:9090
}
}
Part 3: PostgreSQL for Production
Switch from SQLite to PostgreSQL for better performance with multiple users:
services:
roundcube:
image: roundcube/roundcubemail:latest
environment:
ROUNDCUBEMAIL_DB_TYPE: pgsql
ROUNDCUBEMAIL_DB_HOST: db
ROUNDCUBEMAIL_DB_PORT: 5432
ROUNDCUBEMAIL_DB_USER: roundcube
ROUNDCUBEMAIL_DB_PASSWORD: "${DB_PASSWORD}"
ROUNDCUBEMAIL_DB_NAME: roundcube
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: roundcube
POSTGRES_USER: roundcube
POSTGRES_PASSWORD: "${DB_PASSWORD}"
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U roundcube"]
interval: 10s
start_period: 20s
volumes:
db_data:
Part 4: Plugins
CardDAV Contacts (roundcube-carddav)
Sync contacts from any CardDAV server (Nextcloud, Baikal, Radicale):
# Add plugin to Roundcube config:
# The carddav plugin is included in the Docker image via ROUNDCUBEMAIL_PLUGINS env var.
# Users configure their CardDAV sources in:
# Settings → Contacts → Add address book
Enigma (PGP Encryption)
Enable PGP email encryption:
environment:
ROUNDCUBEMAIL_PLUGINS: "archive,zipdownload,enigma"
Users import their PGP key in Settings → Encryption. Outgoing emails to contacts with known public keys are automatically encrypted.
Two-Factor Authentication (2FA)
# Install via plugin manager or docker build:
# Popular plugin: roundcube/two_factor_auth
# Add to custom Docker image:
FROM roundcube/roundcubemail:latest
RUN git clone https://github.com/alexandregz/twofactor_gauthenticator.git \
/var/www/html/plugins/twofactor_gauthenticator
Part 5: Configuration File
For advanced configuration beyond environment variables:
<?php
// /var/roundcube/config/config.inc.php (mounted volume)
// Session lifetime (minutes):
$config['session_lifetime'] = 10;
// Max login attempts before lockout:
$config['login_rate_limit'] = 3;
// Show only this domain in username field:
$config['username_domain'] = 'yourdomain.com';
// With this set, users log in as "hello" instead of "hello@yourdomain.com"
// Default folders:
$config['drafts_mbox'] = 'Drafts';
$config['sent_mbox'] = 'Sent';
$config['trash_mbox'] = 'Trash';
$config['junk_mbox'] = 'Junk';
// Preview pane enabled by default:
$config['preview_pane'] = true;
// HTML email on by default:
$config['htmleditor'] = 1;
// Auto-save drafts every N seconds:
$config['draft_autosave'] = 300;
// Spell check (aspell required in image):
$config['enable_spellcheck'] = true;
$config['spellcheck_engine'] = 'aspell';
// Max email size:
$config['max_message_size'] = '25M';
// SMTP authentication type:
$config['smtp_auth_type'] = 'PLAIN';
// Hide other users' folders on shared IMAP:
$config['show_other_folders'] = false;
// Vacation auto-reply via Sieve:
$config['managesieve_host'] = 'tls://mail.yourdomain.com';
$config['managesieve_port'] = 4190;
Part 6: Skins and Themes
Roundcube ships with two skins:
| Skin | Description |
|---|---|
| elastic | Modern, responsive — works on mobile (recommended) |
| larry | Classic three-pane layout (legacy) |
Custom skin
# Download a community skin:
git clone https://github.com/example/roundcube-skin-custom.git \
/var/roundcube/skins/custom
# Set as default:
echo "\$config['skin'] = 'custom';" >> /var/roundcube/config/config.inc.php
Custom logo
// Replace the Roundcube logo with your own:
$config['product_name'] = 'YourDomain Mail';
$config['skin_logo'] = '/path/to/logo.png';
Part 7: Integration with Mailcow
Mailcow ships SOGo as webmail by default, but you can add Roundcube alongside it:
# Add to mailcow-dockerized docker-compose.override.yml:
services:
roundcube:
image: roundcube/roundcubemail:latest
restart: unless-stopped
ports:
- "127.0.0.1:9090:80"
environment:
ROUNDCUBEMAIL_DEFAULT_HOST: dovecot
ROUNDCUBEMAIL_DEFAULT_PORT: 993
ROUNDCUBEMAIL_SMTP_SERVER: postfix
ROUNDCUBEMAIL_SMTP_PORT: 587
ROUNDCUBEMAIL_DB_TYPE: sqlite
ROUNDCUBEMAIL_SKIN: elastic
networks:
- mailcow-network
networks:
mailcow-network:
external: true
name: mailcow-dockerized_mailcow-network
# Add to mailcow Nginx config (mailcow.conf):
location /webmail {
proxy_pass http://roundcube:80;
}
Part 8: Vacation Auto-Reply and Filters
With ManageSieve enabled (port 4190 on Stalwart/Dovecot):
// config.inc.php:
$config['managesieve_host'] = 'tls://mail.yourdomain.com';
$config['managesieve_port'] = 4190;
$config['managesieve_usetls'] = true;
Users then get in Settings:
- Filters — create mail filtering rules (move to folders, auto-respond, etc.)
- Vacation — set auto-reply with start/end dates
Maintenance
# Update Roundcube:
docker compose pull
docker compose up -d
# Cleanup old sessions (run weekly):
docker exec roundcube php /var/www/html/bin/cleandb.sh
# Backup:
# SQLite:
docker cp roundcube:/var/roundcube/db/sqlite.db ./roundcube-backup-$(date +%Y%m%d).db
# PostgreSQL:
docker exec roundcube-db-1 pg_dump -U roundcube roundcube \
| gzip > roundcube-db-$(date +%Y%m%d).sql.gz
# Logs:
docker compose logs -f roundcube
See our email server guides: Mailcow, Stalwart
See all open source email tools at OSSAlt.com/categories/email.