Deploy Chatto — Self-Hosted Slack & Discord Alternative
Fast open-source team chat with voice calls, SSO, and encryption
Chatto
Just deployed
/data
Deploy and Host Chatto on Railway
Chatto is an open-source team and community chat server — channels, rooms, threads, file sharing, roles and permissions, and SSO with no enterprise upsell. It went open source in July 2026 under AGPL-3.0-or-later and is built as a single compact Go binary serving its own Svelte frontend.
This template deploys Chatto with an external NATS JetStream data store, which is the topology the project recommends for production.
What This Template Deploys
| Service | Purpose |
|---|---|
| Chatto | Chat server, web app, and ConnectRPC API on port 4000 |
| NATS (JetStream) | Persistent data store — messages, users, rooms, and attachments |
Chatto reaches NATS over Railway's private network on port 4222. NATS is never exposed publicly, and Railway terminates TLS in front of Chatto, so no Caddy or reverse proxy is needed.
About Hosting Chatto
Chatto has no database. Not PostgreSQL, not SQLite — it persists everything in NATS JetStream. This surprises people, and it is the single most important thing to understand before deploying: your entire community lives in the NATS volume. Back it up.
The standalone binary embeds NATS inside the Chatto process, which is elegant for a laptop but couples your app lifecycle to your data lifecycle. This template runs NATS as its own Railway service instead. Redeploying, upgrading, or restarting Chatto never touches the data store, and you can add Chatto replicas later against the same NATS without a migration.
Migration between the two models is supported in both directions — chatto backup produces a portable JetStream archive that chatto restore loads into either embedded or external NATS.
Chatto encrypts message text and selected durable account fields with per-user keys, and supports crypto-shredding on account deletion: delete the account, the keys are destroyed, the data is unrecoverable. There is no third-party tracking or analytics anywhere in the stack.
Typical cost: ~$5–10/month on Railway's Hobby plan for both services. Slack charges roughly $8.75/user/month on its paid tier; at ten users that is $87 monthly for a product you do not own.
Voice and Video Calls on Railway
Read this before deploying if calls matter to you.
Chatto's voice and video is powered by LiveKit, which needs direct WebRTC media paths: UDP 3478 for TURN/STUN, the UDP 50000–50200 media range, and TCP 7881 for fallback. Railway routes HTTP and single-port TCP only — no UDP ingress and no port ranges. LiveKit cannot be deployed inside this template and function.
Two working options:
- Use LiveKit Cloud. Set
CHATTO_LIVEKIT_URLto your LiveKit Cloudwss://endpoint plus the matching API key and secret. Browsers connect to LiveKit directly, so this works perfectly alongside a Railway-hosted Chatto. - Run text-only. Leave the
CHATTO_LIVEKIT_*variables unset. Everything except calls works normally — channels, threads, files, notifications, permissions.
Text chat, file sharing, and realtime messaging are fully functional on Railway either way. Only the media path has this constraint.
Deploy in Under 5 Minutes
- Click Deploy on Railway and wait for both services to build
- Confirm the NATS volume is mounted and
NATS_TOKENmatchesCHATTO_NATS_CLIENT_TOKEN— the most common startup failure is these two drifting apart - Set
CHATTO_BASE_URLto your Railway public domain - Configure SMTP and set
CHATTO_OWNERS_EMAILSto the address you'll register with - Open your domain, register with that email, and you're the server owner
Registration sends a verification code by email, so SMTP must work before the first account can be created.
Common Use Cases
- Slack replacement for small teams — channels, threads, and search without per-seat billing or a message history cap
- Community server you actually own — run a paid community, cohort, or user group without Discord's data policies or moderation surprises
- Privacy-sensitive internal chat — per-user encryption at rest and crypto-shredding on deletion make GDPR erasure requests a supported operation rather than a scramble
- SSO-first deployments — external login providers are available in the open-source build, not behind an enterprise contract
- Client workspaces at an agency — one Chatto process per community; a separate Railway project per client
Configuration
| Variable | Required | Description |
|---|---|---|
CHATTO_BASE_URL | Required | Your Railway public URL — used for links and email content |
CHATTO_NATS_URL | Auto-injected | NATS address via Railway reference variable |
CHATTO_NATS_CLIENT_TOKEN | Required | Must exactly match the NATS service's NATS_TOKEN |
NATS_TOKEN | Required | Auth token on the NATS service |
CHATTO_OWNERS_EMAILS | Required | Emails granted the owner role on boot; set before first registration |
CHATTO_SMTP_ENABLED | Required | true — needed for registration codes, verification, and password reset |
CHATTO_SMTP_HOST | Required | SMTP hostname |
CHATTO_SMTP_PORT | Required | 587 for STARTTLS, 465 for SMTPS |
CHATTO_SMTP_TLS | Required | Set to implicit for port 465 providers |
CHATTO_SMTP_FROM | Required | Sender address |
CHATTO_AUTH_DIRECT_REGISTRATION | Optional | Set false after the owner exists to close public signup |
CHATTO_LIVEKIT_URL | Optional | LiveKit Cloud wss:// endpoint — omit to disable calls |
CHATTO_LIVEKIT_API_KEY | Optional | LiveKit API key |
CHATTO_LIVEKIT_API_SECRET | Optional | LiveKit API secret |
CHATTO_PUSH_ENABLED | Optional | Web push for closed-browser notifications |
CHATTO_PUSH_VAPID_PUBLIC_KEY | Optional | Generate with npx web-push generate-vapid-keys |
CHATTO_PUSH_VAPID_PRIVATE_KEY | Optional | Keep secret |
CHATTO_VIDEO_ENABLED | Optional | Video transcoding — ffmpeg ships in the image |
The NATS volume is your entire community. Messages, accounts, rooms, and by default all uploaded attachments live in JetStream. Take backups with
chatto backup, and consider S3-compatible storage for media once the volume grows.
Dependencies for Chatto Hosting
- Railway account — Hobby plan (~$5–10/month) covers both services
- Working SMTP credentials — registration cannot complete without them
- Optional: a LiveKit Cloud project for voice and video
- Optional: S3-compatible storage to offload attachments out of NATS
Deployment Dependencies
- Chatto GitHub Repository
- Chatto Self-Hosting Documentation
- Environment Variable Reference
- Backup & Restore Guide
- Railway Volumes Documentation
Implementation Details
Chatto runs from the official image with NATS JetStream as a separate Railway service holding the persistent volume. Caddy is omitted deliberately — Railway already provides TLS and routing, so the proxy layer from the upstream Compose example is redundant here.
The image runs as a non-root user (1000:1000). If you attach additional volumes, set PUID and PGID to match, since the entrypoint does not recursively fix ownership on mounts.
Chatto exposes a local operator socket for account administration. It is deliberately not published in this template — socket access carries root-equivalent authority over the server. Use railway run against the service when you need operator commands.
Frequently Asked Questions
Where is my data stored? In NATS JetStream, on the volume attached to the NATS service. Chatto uses no SQL database at all. Back up that volume, and use chatto backup for portable archives.
Do voice and video calls work on Railway? Only with LiveKit Cloud. Railway does not route UDP or port ranges, which WebRTC media requires, so a self-hosted LiveKit cannot work here. Point CHATTO_LIVEKIT_URL at LiveKit Cloud, or leave the variables unset and run text-only.
Why is NATS a separate service instead of embedded? So Chatto can be restarted, upgraded, or scaled to multiple replicas without disturbing the data store. The embedded mode is simpler for a single machine; this is the topology the project recommends for production.
Do I need SMTP? Yes, for direct registration. Chatto emails a verification code during signup, so without working SMTP no account can be created — including the first one.
How do I become the server owner? Put your email in CHATTO_OWNERS_EMAILS before registering. Chatto assigns matching owner roles on boot; if you set it after registering, restart the service.
Is Chatto production-ready? It is pre-1.0 and moving quickly, currently in the 0.4.x line. The privacy and permissions work is substantial, but treat it as early software: take backups and read release notes before upgrading.
What's the license? AGPL-3.0-or-later, with Apache-2.0 exceptions covering the standalone frontend, integration surfaces, documentation, and examples. Self-hosting for your own team or community is entirely within scope.
Why Deploy Chatto 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 Chatto on Railway you get a team chat server that is yours end to end — private networking between Chatto and NATS, automatic HTTPS with no Caddy to configure, a persistent volume for your community's history, and per-user encryption at rest. No per-seat billing, no message history limit, no vendor holding your conversations.
Template Content
Chatto
bon5co/chatto:latest