Deploy Roundcube | (Just Updated) Self-Hosted Webmail Client for Any IMAP/SMTP Server, Sessions Survive Redeploys
Roundcube webmail client: read and send mail over IMAP/SMTP, self-host
roundcube
Just deployed
/var/roundcube/db
Deploy and Host Roundcube on Railway
Built for an LLM agent to deploy and use. The deploy form has no fields. Roundcube, the open-source browser webmail client, comes up with a login page that asks which IMAP server to sign in to, a volume that keeps its database and its session-encryption key across redeploys, and a public HTTPS address. It holds no mailbox of its own: you bring the mail server, it brings the webmail. The contract below lists every address, variable name and one script that logs in to a mailbox and opens the inbox.
Roundcube here is the official roundcube/roundcubemail Apache image, version 1.7.5, with the Elastic skin and the archive and zipdownload plugins. It speaks IMAP to read and SMTP to send, so it works with any mail host: Dovecot, Gmail, Fastmail, Mailcow, Stalwart, Mailu, your own server.
About Hosting Roundcube
This template runs one service from a wrapper image pinned by digest. The wrapper makes Apache listen on Railway's injected PORT, marks requests that arrived over the edge's HTTPS as secure so session cookies carry the Secure flag, and keeps Roundcube's SQLite database and a generated 24-character session key on the single volume mounted at /var/roundcube/db. The mount is write-tested at every boot, so a volume the app cannot write fails the deploy instead of losing every setting silently.
The login page shows a free-text Server field. Type the IMAP host (imap.example.com, or host:port, or ssl://host:993). Outgoing mail goes through the same host on port 587 with STARTTLS, using the login's own username and password. To pin the mail server for everyone instead, add the optional variables ROUNDCUBEMAIL_DEFAULT_HOST (and ROUNDCUBEMAIL_DEFAULT_PORT, default 143), and ROUNDCUBEMAIL_SMTP_SERVER (and ROUNDCUBEMAIL_SMTP_PORT, default 587), then redeploy.
Roundcube stores per-user preferences, contacts and identities in SQLite. Mail itself stays on your mail server. The IP-address check on sessions is switched off because Railway's edge address changes between requests and would log users out at random.
Agent contract
- Public URL:
https://$RAILWAY_PUBLIC_DOMAIN(theroundcubeservice's generated domain) - Private URL:
http://roundcube.railway.internal:8080 - Credentials: the mailbox login you bring,
IMAP_USERandIMAP_PASSWORD; the template generates no secret of its own and needs none - Auth: a form login.
GET /?_task=loginreturns a_tokenfield and a session cookie;POST /?_task=loginwith_token,_task=login,_action=login,_host(the IMAP host,IMAP_HOST),_user,_passanswers 302 and sets the session on success and 401 on a wrong password - Health:
GET /returns 200 without authentication (the login page)
# needs: RAILWAY_PUBLIC_DOMAIN of the roundcube service, plus IMAP_HOST (host or host:port), IMAP_USER and IMAP_PASSWORD of a mailbox you own
RC="https://$RAILWAY_PUBLIC_DOMAIN"
JAR=$(mktemp)
token() { curl -s -c "$JAR" -b "$JAR" "$RC/?_task=login" | sed -n 's/.*name="_token" value="\([^"]*\)".*/\1/p' | head -1; }
curl -s -o /dev/null -w "health: %{http_code}\n" "$RC/"
TOKEN=$(token)
curl -s -o /dev/null -w "write without key: %{http_code}\n" -c "$JAR" -b "$JAR" -X POST "$RC/?_task=login" --data-urlencode "_token=$TOKEN" -d _task=login -d _action=login -d _timezone=UTC --data-urlencode "_host=$IMAP_HOST" -d _user=nobody -d _pass=wrong-password
TOKEN=$(token)
curl -s -o /dev/null -w "login: %{http_code}\n" -c "$JAR" -b "$JAR" -X POST "$RC/?_task=login" --data-urlencode "_token=$TOKEN" -d _task=login -d _action=login -d _timezone=UTC --data-urlencode "_host=$IMAP_HOST" --data-urlencode "_user=$IMAP_USER" --data-urlencode "_pass=$IMAP_PASSWORD"
curl -s -b "$JAR" "$RC/?_task=mail" | grep -o '"task":"[a-z]*"\|"mailbox":"[A-Za-z]*"' | sort -u
A fresh deploy prints health: 200, write without key: 401 (a login with a wrong password is refused), login: 302 for a correct mailbox login, then "mailbox":"INBOX" and "task":"mail", which the server prints only inside a signed-in session. If IMAP_HOST is unreachable or IMAP_PASSWORD is wrong the second request prints login: 401.
Why Deploy Roundcube on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Roundcube on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
- Agent-ready - no deployer fields, a contract block and one working login-and-open-the-inbox script.
- Any mail server - the login page takes the IMAP host, so one deploy serves every mailbox you own.
- Persistent - a volume at
/var/roundcube/dbholds the database and the session key, write-tested at every boot; the image is pinned by digest. - Secure cookies behind Railway's edge - HTTPS is detected from
X-Forwarded-Proto, so sessions carry theSecureflag. - Health-checked - Railway restarts the service if the login page stops answering.
Common Use Cases
- Webmail for a self-hosted mail server - put a browser inbox in front of Dovecot, Mailcow, Mailu or Stalwart.
- Shared inbox UI for a team - several people sign in with their own mailbox on one address.
- Mail access for an AI agent - an agent that holds IMAP credentials signs in and reads or sends mail through a real client.
- Replacing a hosted webmail - move off a provider's web interface to one you control, with contacts and identities in SQLite.
Dependencies for Roundcube Hosting
- An IMAP mail server you can sign in to (and an SMTP server on port 587 for sending). Roundcube does not receive or store mail itself.
Deployment Dependencies
Implementation Details
| Variable | Purpose |
|---|---|
ROUNDCUBEMAIL_DEFAULT_HOST | Optional. Pins the IMAP server for every login instead of asking. |
ROUNDCUBEMAIL_DEFAULT_PORT | Optional. IMAP port with the pinned host, default 143. |
ROUNDCUBEMAIL_SMTP_SERVER | Optional. SMTP server; default is the login host with STARTTLS. |
ROUNDCUBEMAIL_SMTP_PORT | Optional. SMTP port with the pinned server, default 587. |
ROUNDCUBEMAIL_DES_KEY | Optional. 24-character session key; generated and stored on the volume when unset. |
Apache listens on Railway's PORT (8080). The database lives in /var/roundcube/db.
Template Content
