DarDev Roundcube at https://webmail.dardev.net is the browser interface for Stalwart-hosted mailboxes on send.dardev.net and sales.dardev.net. It is not a second mail server: Roundcube connects over the internal Docker network to Stalwart IMAP on port 993 and SMTP on port 465. User settings—signatures, identities, two-factor authentication—persist in a PostgreSQL database named roundcube. @dardev.net staff mail remains on Zoho and does not log in here.
This guide documents the stack as deployed on dardev-vps. For the migration story from SnappyMail, read snappymail-to-roundcube-migration. For outbound identity rules, see why-send-dardev-subdomain. For how webmail sits beside Listmonk and Stalwart MTA, see inside-unified-mailer-stack.
Component map
- Public URL — https://webmail.dardev.net via host nginx TLS
- Container — dardev/roundcube:1.6.11 bound to 127.0.0.1:8888
- Metadata DB — PostgreSQL database roundcube on shared postgres service
- Mail backend — Stalwart accounts created in WebAdmin at mta.dardev.net
- IMAP — internal ssl://stalwart:993 (not published on host firewall)
- SMTP submission — internal ssl://stalwart:465
Plugins we ship
Production Roundcube enables password change against Stalwart API, archive and zipdownload for mailbox hygiene, contextmenu and markasjunk for operator UX, managesieve for server-side filters when Stalwart exposes Sieve on port 4190 with STARTTLS, carddav for personal Stalwart address books, twofactor_gauthenticator for TOTP 2FA, stalwart_directory for cross-mailbox compose autocomplete via JMAP principals, and zipdownload for thread export.
Deploy and validate
From a developer workstation with WSL: wsl bash scripts/deploy-webmail.sh syncs repo files, ensures ROUNDCUBEMAIL_DES_KEY exists in VPS .env, runs init-roundcube-db.sh idempotently, and brings up the roundcube service. On the VPS directly: cd /opt/dardev-mailer, bash scripts/mail/init-roundcube-db.sh, docker compose -f docker-compose.yml -f docker-compose.dardev-vps.yml up -d roundcube, then bash scripts/mail/validate-webmail.sh.
Validation checks container health, PostgreSQL connectivity, nc stalwart 993 from inside the Roundcube container, and an HTTPS smoke against the login page. Probe scripts under scripts/mail/ diagnose IMAP and directory issues without exposing credentials in logs.
Login and daily use
- Open https://webmail.dardev.net
- Log in with full Stalwart email—for example contact@send.dardev.net or sales@sales.dardev.net
- Set signature under Settings → Identities
- Optional: enable 2FA under Settings → 2-Factor Authentication
- Optional: change password under Settings → Password when Stalwart API account modify is configured
- Optional: edit filters under Settings → Filters when ManageSieve listener is live
There is no separate webmail admin UI like SnappyMail had. Operators edit roundcube/config/custom.inc.php and plugin configs under roundcube/ in git, then redeploy. Domain allowlist login_username_filter blocks random domains from authenticating even if someone guesses the URL.
Stalwart prerequisites
Before webmail works for an account, Stalwart WebAdmin must have the send domain with inbound enabled, IMAP listener on [::]:993 with implicit TLS inside Docker only, and an account row with IMAP plus submission permissions. Sales domain mailboxes follow the same pattern when sales.dardev.net is live. Public SMTP ports 25, 587, and 465 on Stalwart remain unchanged for outbound campaign and transactional traffic described in deployed-realities-explained.
Configuration highlights
custom.inc.php sets mail_domain to send.dardev.net and sales.dardev.net, relaxes TLS verification for internal stalwart hostname, sets product_name to DarDev Webmail, disables ip_check behind nginx, and wires autocomplete_addressbooks to stalwart_directory plus sql. stalwart_directory_jmap_url points to http://stalwart:8080/jmap on the Docker network. CardDAV discovery uses stalwart-admin-proxy on port 18080 for .well-known/carddav.
Backup and troubleshooting
Back up PostgreSQL roundcube with other company databases. Mail message storage is Stalwart volumes stalwart-data and stalwart-etc—not Roundcube. Common failures: login rejected when domain not in custom.inc.php; IMAP errors fixed by probe-stalwart-from-webmail.sh; 502 when container down or DES key missing; empty contacts after CardDAV deploy—log out and back in once; signature not saved when roundcube database was never created—run init-roundcube-db.sh.
Webmail is staff-facing infrastructure on the company platform, not a product tenant surface. It shares dardev-vps with CRM, Listmonk, and ops-console—the same multi-product-saas-one-core host pattern where each solution gets connectors but mail truth stays in Stalwart.
Ports and network boundaries
Only 127.0.0.1:8888 binds Roundcube on the host. Public internet sees nginx 443 terminating TLS for webmail.dardev.net. IMAP 993 and SMTP 465 between Roundcube and Stalwart never leave the mailer Docker bridge. That layout matches inside-unified-mailer-stack security posture: one public web entry, internal service mesh for mail protocols.
Extending to new send domains
When agents.dardev.net or additional Stalwart outbound domains go live, add the domain to mail_domain and login_username_filter in custom.inc.php, enable inbound on the domain in WebAdmin, provision accounts, redeploy Roundcube. Webmail does not need a new public hostname per domain—full-email login covers multi-domain in one UI.
Image builds use roundcube/Dockerfile extending official Roundcube with DarDev plugins baked in. CI does not publish the image to public registries; dardev-vps pulls from local build on deploy. Version bumps require updating ROUNDCUBE_TAG in .env and re-running deploy-webmail.sh with validate-webmail.sh green before announcing to staff.
Which email addresses can log into webmail.dardev.net?
Stalwart mailboxes on configured send domains—currently send.dardev.net and sales.dardev.net. Not @dardev.net Zoho accounts.
Where are signatures stored?
PostgreSQL roundcube database, not browser local storage. They survive container restarts unlike our retired SnappyMail setup.
Is IMAP exposed on the public internet?
No. Only Roundcube inside the mailer Docker network reaches stalwart:993. Staff access mail through HTTPS webmail only.
How do I deploy an updated plugin config?
Commit changes under roundcube/, run scripts/deploy-webmail.sh or compose up -d roundcube on the VPS.
What image tag do we run?
dardev/roundcube:1.6.11 pinned in .env as ROUNDCUBE_TAG—not :latest in production.



