What you need
- A Linux host with Docker and Docker Compose.
- A domain name pointing at the host (with subdomains for the media server and file storage).
- Open ports for the web app and for real-time media (calls use UDP).
What’s in the stack
A singledocker compose setup brings up everything the platform needs, so you’re not wiring services together by hand:
Bastion node
The API and real-time layer for chat, calls, keys and uploads.
Database & cache
PostgreSQL for durable data, Redis for presence and real-time fan-out.
File storage
S3-compatible object storage for encrypted attachments (bundled, or bring your own).
Media server
Carries encrypted call audio, video and screen share — on your infrastructure.
Background worker
A separate worker process delivers notifications and fans messages out to large channels, so it never competes with the API for responsiveness.
Bring it up
1
Generate config and secrets
2
Start the stack
3
Register your organization
Create the organization once, then invite members from the admin panel.
Configuration worth knowing
A few environment settings shape privacy and limits (sensible defaults ship out of the box):MESSAGE_PUSH_HIDE_METADATA— keep notifications generic (no sender/chat identity in the push). On by default; setfalsefor richer named notifications.MAX_ATTACHMENT_BYTES— hard cap on a single attachment (default 100 MiB), enforced both up front and against the stored object.FANOUT_MODE—dedicated(default in the prod stack) runs the separate worker container above;inlinefolds that work into the API for a minimal single-container deploy.
Secure by default
- HTTPS is issued and renewed automatically by the bundled reverse proxy.
- The database and file storage bind to localhost — never exposed to the open internet. Only the web app and media server are reachable from outside.
- Fail-closed secrets: if a required secret is missing, the stack refuses to start rather than booting with a weak default.
What still depends on the control plane
Identity (passwordless sign-in), push notifications and licensing are brokered by the shared control plane, so accounts work across every app and across devices. Your content — messages, files and calls — never leaves your node; only that identity and licensing traffic goes to the control plane. See Accounts & privacy.Don’t want to run any of this? The managed option is the exact same stack, operated for you. See Pricing.