Teams that rely on Slack or Microsoft Teams are one pricing change away from a disruption. Rocket.Chat is the leading open-source team communication platform — supporting channels, threads, direct messages, voice and video calls, bots, and REST/WebSocket APIs — and running it on your own infrastructure gives you full control over data residency, compliance policies, and integrations. This guide walks through a production-ready deployment of Rocket.Chat using Docker Compose for container orchestration, Caddy as the TLS-terminating reverse proxy, and MongoDB as the persistent backend.
You will end up with a hardened, publicly accessible Rocket.Chat instance with automatic HTTPS, persistent data volumes, systemd process supervision, and the operational hygiene needed for a real team deployment.
Architecture and flow overview
The stack has three layers. Caddy sits at the edge, listening on ports 80 and 443. It provisions a Let's Encrypt certificate automatically, strips TLS, and forwards plain HTTP to the Rocket.Chat container on the internal Docker network. Rocket.Chat itself is the application tier: it manages all chat state, user accounts, integrations, and real-time WebSocket connections. MongoDB is the persistence tier, running as a replica set (even with one node) because Rocket.Chat's change streams and oplog tailing require replica-set mode.
All three services run in a shared Docker Compose network. Caddy is the only container that binds ports on the host (80/443). MongoDB and Rocket.Chat are fully internal. Volumes are named Docker volumes, making snapshot and migration straightforward.
Prerequisites
- Ubuntu 22.04 LTS (or 24.04) VPS with at least 2 vCPU and 2 GB RAM (4 GB recommended for teams over 25 users)
- A domain name pointed at your server's public IP via an A record (e.g.,
chat.example.com) - Docker Engine 24+ and Docker Compose v2 installed (
apt install docker.io docker-compose-v2) - UFW configured to allow ports 22, 80, and 443
- A non-root sudo user for operations
Step-by-step deployment
1. Create the project directory and environment file
mkdir -p /opt/rocketchat && cd /opt/rocketchat
cat > .env << 'EOF'
ROOT_URL=https://chat.example.com
MONGO_URL=mongodb://mongo:27017/rocketchat?replicaSet=rs0
MONGO_OPLOG_URL=mongodb://mongo:27017/local?replicaSet=rs0
PORT=3000
DEPLOY_METHOD=docker
EOFReplace chat.example.com with your actual domain. The MONGO_URL and MONGO_OPLOG_URL use the Docker network service name mongo — no host-level port exposure needed.
2. Write the Docker Compose file
version: "3.8"
services:
mongo:
image: mongo:6.0
restart: unless-stopped
volumes:
- mongo_data:/data/db
- mongo_config:/data/configdb
command: >
mongod
--replSet rs0
--oplogSize 128
networks:
- internal
mongo-init-replica:
image: mongo:6.0
restart: on-failure
depends_on:
- mongo
command: >
bash -c "sleep 5 && mongosh --host mongo:27017 --eval
'rs.initiate({_id:\"rs0\",members:[{_id:0,host:\"mongo:27017\"}]})
.then(() => quit(0)).catch(() => quit(0))'"
networks:
- internal
rocketchat:
image: registry.rocket.chat/rocketchat/rocket.chat:7.4
restart: unless-stopped
env_file: .env
depends_on:
- mongo
volumes:
- rocketchat_uploads:/app/uploads
networks:
- internal
- web
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- web
volumes:
mongo_data:
mongo_config:
rocketchat_uploads:
caddy_data:
caddy_config:
networks:
internal:
web:3. Write the Caddyfile
chat.example.com {
reverse_proxy rocketchat:3000 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
-Server
}
log {
output file /data/logs/access.log {
roll_size 50mb
roll_keep 5
}
}
}4. Start the stack
cd /opt/rocketchat
docker compose up -d
# Watch startup logs
docker compose logs -f rocketchatOn first boot, MongoDB initialises the replica set via the mongo-init-replica one-shot container. Rocket.Chat then connects and runs its database migrations. The first boot usually takes 60–90 seconds.
5. Create the admin account
Navigate to https://chat.example.com in a browser. The setup wizard will prompt you to create the first admin user. Complete the wizard — you can skip federation and cloud registration for self-hosted deployments.
Configuration and secrets handling
Sensitive values should not live in the Compose file. Keep them in the .env file with restricted permissions and exclude it from version control:
chmod 600 /opt/rocketchat/.env
echo ".env" >> /opt/rocketchat/.gitignoreFor production teams, rotate the MongoDB connection string by updating .env and running docker compose up -d --force-recreate rocketchat. If you add a MongoDB username and password later, update both MONGO_URL and MONGO_OPLOG_URL to include credentials: mongodb://rcuser:strongpass@mongo:27017/rocketchat?replicaSet=rs0&authSource=rocketchat.
For SMTP (email notifications), set these additional variables in .env:
MAIL_URL=smtp://user:[email protected]:587All admin-configurable options (LDAP, OAuth, push notifications, file storage providers) live under Administration → Settings in the Rocket.Chat UI and are stored in MongoDB — no config-file editing required after initial deployment.
Verification
# All containers running
docker compose ps
# MongoDB replica set confirmed
docker compose exec mongo mongosh --eval "rs.status().ok"
# Expected: 1
# Rocket.Chat health endpoint
curl -sf https://chat.example.com/health | python3 -m json.tool
# Expected: {"status":"healthy",...}
# TLS certificate valid
curl -sv --head https://chat.example.com 2>&1 | grep -E "(SSL|HTTP)"Log in as the admin user, send a test message in the #general channel, and confirm the message persists across a container restart (docker compose restart rocketchat).
Common issues and fixes
MongoDB not in replica set mode: Rocket.Chat refuses to start and logs MongoError: Change Stream requires the 'majority' read concern. Confirm rs.status().ok === 1 from inside the mongo container. If the init container exited too early, re-run it: docker compose run --rm mongo-init-replica.
Caddy certificate provisioning fails: Caddy requires ports 80 and 443 to be reachable from the internet for the ACME challenge. Check UFW (ufw status), verify your domain A record propagated (dig +short chat.example.com), and check Caddy logs (docker compose logs caddy). Caddy rate-limits are per Let's Encrypt — if you exceeded them during testing, add tls internal temporarily to use a self-signed cert.
WebSocket connections dropping after a load balancer/proxy: Caddy handles WebSocket upgrade automatically, but some upstream proxies strip Upgrade headers. Add header_up Connection "Upgrade" and header_up Upgrade {http.request.header.Upgrade} to the reverse_proxy block if users see "real-time connection lost" banners.
File uploads fail or return 413: Caddy's default max request body is generous, but Rocket.Chat also enforces its own limit under Administration → File Upload → Maximum File Size. Increase it there and add request_body { max_size 100MB } to the Caddy site block if needed.
Container memory pressure: MongoDB and Rocket.Chat together consume roughly 800 MB at idle. If you see OOM kills, add memory limits to the Compose services or upgrade to a 4 GB instance. You can also tune WiredTiger cache: --wiredTigerCacheSizeGB 0.5 in the MongoDB command.
FAQ
Can I migrate an existing Rocket.Chat instance to this deployment?
Yes. Export your existing MongoDB data with mongodump --archive=rc_backup.gz --gzip, copy the archive to the new host, and restore it with mongorestore --archive=rc_backup.gz --gzip --drop after the new stack is up but before creating admin. Match the Rocket.Chat version between old and new instances to avoid migration errors.
How do I enable LDAP or Active Directory authentication?
Navigate to Administration → LDAP and enable the integration. Fill in your LDAP server address, bind DN, bind password, and user search base. Rocket.Chat supports both LDAP and SAML 2.0 (available under Administration → SAML). You do not need to modify the Docker Compose file — all auth configuration is stored in MongoDB and managed through the UI.
How do I upgrade Rocket.Chat?
Change the image tag in docker-compose.yml (e.g., 7.4 to 7.5), pull the new image, and recreate the container: docker compose pull rocketchat && docker compose up -d rocketchat. Rocket.Chat auto-runs database migrations on startup. Always take a mongodump backup before upgrading.
Can multiple instances share the same MongoDB for high availability?
Yes, but you need at minimum a 3-node MongoDB replica set and a load balancer in front of your Rocket.Chat containers. For teams under 500 users, a single-node deployment with daily backups and a restart policy is typically sufficient. Scale horizontally only when you observe sustained >80% CPU on the Rocket.Chat container.
How do I set up push notifications for mobile apps?
Rocket.Chat Cloud provides a free push notification gateway (15,000 pushes/month). Register your workspace under Administration → Connectivity Services → Connect to Cloud, then enable push notifications under Administration → Push. Self-hosted push delivery requires setting up your own Firebase (Android) and APNs (iOS) credentials, which is complex — the Cloud gateway is the practical choice for most deployments.
How do I back up Rocket.Chat data?
Back up two things: the MongoDB data volume and the uploads volume. For MongoDB: docker compose exec mongo mongodump --archive=/tmp/rc_backup.gz --gzip && docker compose cp mongo:/tmp/rc_backup.gz ./rc_backup.gz. For uploads: docker run --rm -v rocketchat_uploads:/uploads -v $(pwd):/backup busybox tar czf /backup/uploads.tar.gz /uploads. Store both archives off-site (S3, Backblaze B2). Automate with a daily cron job.
Internal links
- Production Guide: Deploy Mattermost with Docker Compose + Caddy + PostgreSQL on Ubuntu
- Production Guide: Deploy Chatwoot with Docker Compose + Caddy + PostgreSQL + Redis on Ubuntu
- Production Guide: Deploy Authentik with Docker Compose + Caddy + PostgreSQL + Redis on Ubuntu
Talk to us
If you want this deployed with hardened access controls, monitoring standards, and production runbooks tailored to your environment, our team can help end-to-end.