- SmartStack: AI, Self-Hosting & Smart Finance/
- Posts/
- State of the Discord – The Ultimate Self‑Host Lesson from r/selfhosted (2024‑2026)/
State of the Discord – The Ultimate Self‑Host Lesson from r/selfhosted (2024‑2026)
Table of Contents
The Community Spark: Why “State of the Discord – A Lesson” Went Viral #
In early 2024 a Reddit thread titled “State of the Discord – A Lesson” exploded on r/selfhosted, amassing over 12 k up‑votes and a dozen deep‑dive comment chains. The core question was simple yet powerful:
“If you’re running a community, should you keep relying on Discord, or is it time to migrate to a self‑hosted alternative?”
The post resonated because it touched three pain points that self‑hosters repeatedly flag:
- Data sovereignty – Discord’s Terms of Service give the company sweeping rights over user content.
- Feature parity – Many alternatives claim to be “Discord‑compatible” but fall short on voice, bots, or UI polish.
- Operational cost – Running a VPS with real‑time chat, media storage, and voice can feel pricey compared to a free Discord server.
What followed was a week‑long “town‑hall” of lived experiences: success stories, hard‑won failures, and a collective checklist that now serves as the de‑facto guide for anyone contemplating a migration. This article synthesizes those community insights, augments them with expert technical walk‑throughs, and delivers a definitive, action‑oriented playbook for 2026.
Synthesized Community Perspectives: Consensus, Debates, and the “Lesson” Everyone Learned #
| Community Theme | What the Majority Said | Notable Counter‑Arguments |
|---|---|---|
| Data Ownership | Users overwhelmingly value full control of chat logs, media, and bot data. | A few argued that Discord’s backups and export tools are “good enough” for small hobby groups. |
| Feature Parity | Revolt and Matrix (via Element) were praised for text chat & bots; voice remained a gap. | Some veterans claimed that “good enough” voice can be achieved with Jitsi or Mumble, while others insisted on native Discord‑style low‑latency voice. |
| Operational Complexity | Docker‑Compose + Systemd was the preferred deployment method for most. | A minority advocated for Kubernetes for scaling, but many warned it’s overkill for <200 users. |
| Cost vs. Benefit | A $10‑$15 /month VPS (2 vCPU, 4 GB RAM) was deemed sufficient for up to 150 active users. | A handful of high‑traffic gaming clans reported spikes that required auto‑scaling on Hetzner Cloud. |
| Community Migration | A phased migration (export → import → parallel run) reduced friction. | Some users tried a “big bang” cut‑over and suffered data loss due to Discord rate limits. |
The Core Lesson #
Self‑hosting is feasible and rewarding, but only when you match the solution to your community’s size, feature expectations, and operational bandwidth.
The community’s collective “lesson” is a three‑step decision matrix:
- Define Requirements – Text only? Voice? Bot ecosystem? GDPR compliance?
- Benchmark Resources – Estimate concurrent users, storage, and bandwidth.
- Pick the Right Stack – Revolt for Discord‑like UI, Matrix for federation, or a hybrid (Matrix + Jitsi) for voice.
With that framework in place, let’s dive into the technical tutorial that the Redditors voted most helpful: Deploying Revolt on a modest VPS with Docker, Nginx reverse proxy, and automatic backups.
Deep‑Dive Actionable Guide: Deploying a Production‑Ready Revolt Server (2026 Edition) #
Assumption: You have a fresh VPS (Ubuntu 24.04 LTS, 2 vCPU, 4 GB RAM, 80 GB SSD) and root access.
1. Prerequisites #
# Update OS and install essential tools
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl gnupg2 ca-certificates lsb-release software-properties-common git
2. Install Docker Engine (recommended version 27.x) #
# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Set up the stable repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
# Verify
docker version
3. Create a Dedicated Non‑Root User for Docker #
sudo adduser --disabled-password --gecos "" revolt
sudo usermod -aG docker revolt
# Log out/in or `newgrp docker` to apply group change
4. Clone the Official Revolt Docker Compose Template #
sudo -u revolt mkdir -p ~/revolt && cd ~/revolt
git clone https://github.com/revoltchat/revolt-docker.git .
5. Adjust Environment Variables #
Edit docker-compose.yml (or env.example → .env) to suit your domain and storage:
# .env
REVOlt_DOMAIN=chat.example.com
REVOlt_LETSENCRYPT_EMAIL=admin@example.com
REVOlt_DB_PASSWORD=StrongRandomPassword123!
Tip from r/selfhosted: Use
openssl rand -base64 32to generate a cryptographically‑secure password.
6. Set Up Nginx Reverse Proxy with Automatic HTTPS (Caddy Alternative) #
While Revolt ships its own Caddy‑based proxy, many community members preferred Traefik for fine‑grained middleware (rate‑limit, auth‑basic). Below is a minimal Traefik v3 config.
# Install Traefik (binary method)
curl -L https://github.com/traefik/traefik/releases/download/v3.0.0/traefik_v3.0.0_linux_amd64.tar.gz | tar -xz
sudo mv traefik /usr/local/bin/
sudo mkdir -p /etc/traefik && sudo chown revolt:revolt /etc/traefik
Create traefik.yml:
# /etc/traefik/traefik.yml
log:
level: INFO
api:
dashboard: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
providers:
docker:
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: ${REVOlt_LETSENCRYPT_EMAIL}
storage: acme.json
httpChallenge:
entryPoint: web
Create acme.json (must be 600):
touch /etc/traefik/acme.json
chmod 600 /etc/traefik/acme.json
7. Launch Revolt with Docker‑Compose (using Traefik labels) #
Edit docker-compose.yml to include Traefik labels:
services:
api:
image: revoltchat/api:latest
restart: unless-stopped
env_file: .env
labels:
- "traefik.enable=true"
- "traefik.http.routers.revolt-api.rule=Host(`${REVOlt_DOMAIN}`) && PathPrefix(`/api`)"
- "traefik.http.routers.revolt-api.entrypoints=websecure"
- "traefik.http.routers.revolt-api.tls.certresolver=letsencrypt"
front:
image: revoltchat/front:latest
restart: unless-stopped
env_file: .env
labels:
- "traefik.enable=true"
- "traefik.http.routers.revolt-front.rule=Host(`${REVOlt_DOMAIN}`)"
- "traefik.http.routers.revolt-front.entrypoints=websecure"
- "traefik.http.routers.revolt-front.tls.certresolver=letsencrypt"
# Database (PostgreSQL) omitted for brevity – same as upstream template
Start everything:
docker compose up -d
Verify with docker ps; you should see api, front, and db containers.
8. Automated Backups (Community‑tested Cron) #
Create a backup script /home/revolt/backup.sh:
#!/usr/bin/env bash
TIMESTAMP=$(date +%F_%H-%M)
BACKUP_DIR="/var/backups/revolt"
mkdir -p "$BACKUP_DIR"
# Dump PostgreSQL
docker exec -t revolt-db pg_dump -U revolt -Fc revolt > "$BACKUP_DIR/revolt_$TIMESTAMP.dump"
# Archive uploads (media)
tar -czf "$BACKUP_DIR/uploads_$TIMESTAMP.tar.gz" -C /home/revolt/uploads .
# Optional: upload to remote S3 bucket
# aws s3 cp "$BACKUP_DIR" s3://my-revolt-backups/ --recursive
# Prune older than 30 days
find "$BACKUP_DIR" -type f -mtime +30 -delete
chmod +x /home/revolt/backup.sh
# Add to root's crontab (runs at 02:30 daily)
sudo crontab -e
# ──> 30 2 * * * /home/revolt/backup.sh >> /var/log/revolt_backup.log 2>&1
9. Monitoring & Alerts (Prometheus + Grafana Lite) #
The Reddit community recommended a lightweight Prometheus node‑exporter for early warning on CPU/memory spikes.
docker run -d \
--name node-exporter \
--restart unless-stopped \
-p 9100:9100 \
--pid="host" \
--net="host" \
quay.io/prometheus/node-exporter:latest
Then add a Grafana dashboard (import ID 1860 – “Docker Host Overview”) and set alerts for >80 % CPU or RAM usage.
10. Migration Checklist (From Discord) #
- Export – Use Discord’s Server Settings → Overview → Export Server Data (JSON + media zip).
- Transform – Run the community‑maintained Python script
discord2revolt.py(found in r/selfhosted’s wiki) to convert channel structures and user IDs. - Import – Place the transformed JSON into
/home/revolt/import/and executedocker exec revolt-api npm run import. - Parallel Run – Keep Discord alive for 48 h while users test Revolt; gather feedback via a dedicated “#migration‑feedback” channel.
- Cut‑over – Disable invites on Discord, announce the final switch, and archive the old server.
Following this checklist saved ≈30 % of migration time for the most active community (≈1 k members) according to the thread’s author, u/ChronoMason.
Pros & Cons / Comparative Table of Popular Discord Alternatives #
| Solution | UI Familiarity | Voice Support | Federation | Bot Ecosystem | Typical VPS Specs (2026) | Ease of Maintenance |
|---|---|---|---|---|---|---|
| Discord (official) | ★★★★★ (native) | ★★★★★ (low‑latency) | ✖ | ★★★★★ (official API) | N/A (cloud) | ✔ (no ops) |
| Revolt | ★★★★☆ (Discord‑like) | ✖ (text only) – add Jitsi for voice | ✖ | ★★★★☆ (Node.js & Python bots) | 2 vCPU / 4 GB RAM / 50 GB SSD | ✔ (Docker) |
| Matrix + Element | ★★★☆☆ (different UI) | ★★☆☆ (needs Jitsi/Mumble) | ★★★★★ (federated) | ★★★★☆ (many bridges) | 2 vCPU / 6 GB RAM / 80 GB SSD | ✖ (Synapse tuning) |
| Zulip | ★★☆☆ (threaded) | ✖ | ✖ | ★★☆☆ (limited) | 1 vCPU / 2 GB RAM / 30 GB SSD | ✔ (simple) |
| **Mumble + Rocket |