How to Self-Host Revolt Chat with Docker: Complete Guide

Written by:

A self-hosted Revolt Chat instance runs entirely on your own hardware — every message, file, and user record stays under your direct control with zero third-party data exposure. The full stack deploys via a single docker compose up -d command, spinning up six containers: the Rust-powered API backend, Bonfire WebSocket server, Autumn file proxy, MongoDB database, Redis cache, and MinIO object storage. If you are new to Revolt Chat, the Revolt Chat platform overview covers the full feature set and privacy architecture before you dive into deployment.

The official self-hosting repository at github.com/stoatchat/self-hosted (2,300+ GitHub stars) provides the reference docker-compose.yml and environment configuration. This guide walks through hardware requirements, the full annotated compose file, environment variable setup, reverse proxy configuration, and the common failure points that trip up first-time deployers.

Prerequisites and System Requirements

A production-ready Revolt Chat Docker deployment needs at least 2 GB RAM, 1-2 CPU cores, and 20 GB disk space. Under-provisioned hardware causes MongoDB and Bonfire restart loops before you ever see a login screen — get the baseline right first.

prerequisites and system requirements
Minimum and recommended hardware specifications for running a Revolt Chat self-hosted Docker deployment

Hardware Specifications

According to MongoDB’s official production notes, a single-node MongoDB instance requires a minimum of 1 GB RAM — meaning the full Revolt stack needs well beyond that floor. The practical recommendation is 4 GB RAM for a responsive instance under real user load.

ResourceMinimumRecommendedNotes
RAM2 GB4 GBMongoDB + Redis are the heaviest consumers
CPU1 core2 coresARM64 (Raspberry Pi 4) supported
Disk20 GB40 GB+MinIO storage grows with file attachments
OSAny Linux with DockerUbuntu 22.04 LTS / Debian 12Docker Engine v24+ and Compose v2 required

A Raspberry Pi 4 with 4 GB RAM handles a small community (under 50 concurrent users) comfortably, provided you use a USB-attached SSD instead of a microSD card. Disk I/O is the bottleneck on ARM hardware, not CPU.

Required Software

Docker Engine v24+ and Docker Compose v2 plugin are non-negotiable. The older standalone docker-compose binary has compatibility gaps with modern compose syntax. Verify both:

docker --version        # Expect: Docker version 24.x or higher
docker compose version  # Expect: Docker Compose version v2.x

A registered domain name pointed at your host’s public IP is also required — Revolt Chat serves its web frontend over HTTPS, and TLS certificates need a valid domain for automatic issuance via Let’s Encrypt.

Understanding the Revolt Docker Architecture

A complete self-hosted Revolt Chat deployment runs six containers, each handling one layer of the stack. Understanding the architecture before editing configuration files prevents the most common debugging time sinks.

understanding the revolt docker architecture
The six Revolt Chat Docker containers communicate over an internal bridge network with MongoDB and MinIO providing persistent storage

Container Roles and Communication

The backend API (revoltchat/server) handles every REST call — authentication, message history, channel management. Bonfire (revoltchat/bonfire) maintains WebSocket connections for real-time message delivery. Autumn (revoltchat/autumn) proxies file uploads between the API and MinIO, the S3-compatible object storage engine that keeps all attachments on your hardware.

ContainerImageRolePersists Data?
API Backendrevoltchat/serverREST API, authentication, business logicNo (stateless)
WebSocket Serverrevoltchat/bonfireReal-time event deliveryNo (stateless)
File Proxyrevoltchat/autumnUpload/download routing to MinIONo (delegates to MinIO)
Web Frontendrevoltchat/reviteBrowser UI (Solid.js/TypeScript)No (stateless)
Databasemongo:6Users, messages, channels, serversYes (named volume)
Object Storageminio/minioFile attachments, avatars, emojiYes (named volume)

Why Redis Matters

Redis handles session token caching and pub/sub messaging between the API and Bonfire. Without Redis, the WebSocket server cannot reliably invalidate sessions or broadcast events across API processes. It is the connective tissue that makes real-time messaging work — and the Alpine image (redis:7-alpine) keeps the layer size under 30 MB.

All containers share a single internal Docker bridge network. Each service resolves others by name: the API reaches MongoDB at mongodb:27017 and Redis at redis:6379. No database port needs external exposure.

Setting Up docker-compose.yml and .env

Two files control the entire deployment: docker-compose.yml defines every container and its relationships, and .env injects secrets and URLs at runtime. Clone the official self-hosted repository for the reference configuration, then customize with the variables below.

Essential Environment Variables

VariableDescriptionExample Value
REVOLT_PUBLIC_URLPublic-facing API URL. Mismatches here cause CORS errors.https://api.revolt.example.com
MONGODB_URIMongoDB connection string using Docker service name.mongodb://mongodb:27017/revolt
REDIS_URIRedis connection for session caching and pub/sub.redis://redis:6379
MINIO_ROOT_USERMinIO admin username.revolt_admin
MINIO_ROOT_PASSWORDMinIO admin password (8+ characters required by MinIO).str0ng_s3cret_key
VAPID_PRIVATE_KEY / VAPID_PUBLIC_KEYWeb Push notification keys. Generate with Node.js.See generation command below

Generate VAPID keys with a single Node.js command:

node -e "const {generateVAPIDKeys} = require('web-push'); console.log(generateVAPIDKeys());"

Lock down the .env file permissions immediately: chmod 600 .env. Leaving it world-readable on a shared host is a genuine security exposure.

Launching the Stack

With both files in place, start everything in detached mode:

docker compose up -d

Verify all containers reached running state with docker compose ps. If any container shows “restarting,” check its logs with docker compose logs [service-name] — the most common culprits are MongoDB connection timeouts (RAM too low) and CORS mismatches (REVOLT_PUBLIC_URL not matching the actual domain).

Reverse Proxy and TLS Configuration

Revolt Chat requires HTTPS with valid TLS certificates. A reverse proxy sits in front of the Docker containers, terminates SSL, and routes traffic to the correct internal port. Caddy, Traefik, and Nginx Proxy Manager all work — the critical requirement is WebSocket upgrade support for the Bonfire event server.

Caddy (Simplest Option)

Caddy handles automatic HTTPS with zero configuration for certificate renewal. A minimal Caddyfile:

revolt.example.com {
    reverse_proxy /api/* localhost:3000
    reverse_proxy /ws   localhost:9009
    reverse_proxy /autumn/* localhost:3003
    reverse_proxy localhost:5173
}

The /ws route must reach Bonfire on port 9009 with WebSocket upgrade headers intact. Caddy handles this automatically — no additional configuration needed.

Common Reverse Proxy Mistakes

  • WebSocket upgrades not forwarded: Bonfire requires Connection: Upgrade headers. Nginx users must add proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection "upgrade" explicitly.
  • REVOLT_PUBLIC_URL mismatch: The URL in .env must exactly match the domain the reverse proxy serves. Trailing slashes, http vs https, and subdomain mismatches all trigger CORS failures.
  • Ports 80/443 blocked: Let’s Encrypt HTTP-01 challenges require port 80 open. Firewall rules or ISP blocks will cause certificate issuance to fail silently.

Frequently Asked Questions

What are the minimum requirements to self-host Revolt Chat?

A self-hosted Revolt Chat Docker deployment requires at least 2 GB RAM, 1-2 CPU cores, and 20 GB disk space. The recommended setup is 4 GB RAM with an SSD for storage. A Raspberry Pi 4 with 4 GB RAM and USB SSD is a viable budget host for small communities.

How do I set up HTTPS for my self-hosted Revolt instance?

Point your domain’s DNS A record at the server, then configure a reverse proxy (Caddy, Traefik, or Nginx) to terminate TLS with automatic Let’s Encrypt certificates. The reverse proxy must forward WebSocket upgrade headers to Bonfire on port 9009, or real-time messaging will silently fail.

How do I update my self-hosted Revolt containers?

Run docker compose pull && docker compose up -d to fetch updated images and recreate containers with minimal downtime. Pull images before stopping the stack to reduce the offline window to seconds. Pin to specific image tags in docker-compose.yml if you need stability over bleeding-edge updates.

Can I deploy Revolt Chat on Kubernetes?

Yes. Community-maintained Helm charts exist for Kubernetes deployment, though the official self-hosting documentation primarily covers Docker Compose. Kubernetes is best suited for teams that need horizontal scaling, automated failover, or integration with existing cluster infrastructure. For most small to mid-size communities, Docker Compose is simpler and sufficient.

Why self-host Revolt Chat instead of using the hosted version?

Self-hosting gives complete data sovereignty — every message, file, and metadata record stays on infrastructure you physically control. For organizations with GDPR obligations or teams handling sensitive communications, self-hosting eliminates third-party data exposure entirely. The AGPL-3.0 license guarantees the right to deploy and modify the code.

Next Steps

A self-hosted Revolt Chat instance puts complete control of your community’s data on your own infrastructure. The Docker Compose deployment covered here handles all six services — API, WebSocket, file storage, database, cache, and frontend — with under 2 GB RAM at idle on modest hardware.

After your first successful login, explore the admin panel for user management and server configuration. If anything goes wrong during or after setup, the Revolt Chat troubleshooting guide covers the most common failure points. For extending your instance with automated moderation or custom integrations, the Revolt Chat bots and API guide walks through bot development on self-hosted deployments. Keep the stack current with docker compose pull && docker compose up -d whenever new releases drop.

Last modified: March 26, 2026