How to Install Rocket.Chat on Ubuntu 24.04 — Self-Hosted Team Chat That You Own
Rocket.Chat is the most mature open-source team chat platform available today. It gives you Slack-style channels, threaded conversations, voice and video calls, livechat widgets, and omnichannel customer support — all running on your own VPS, with every message, file, and user identity stored on infrastructure you control. This tutorial walks you through a production-ready deployment on Ubuntu 24.04 using Docker Compose, a proper MongoDB replica set, Nginx reverse proxy with WebSocket support, TLS from Let's Encrypt, SMTP for transactional email, and integration with enterprise identity providers.
Need a VPS with the right specs? Rocket.Chat's real-time engine is I/O and memory hungry once you pass a few dozen active users. Our Professional VPS plan gives you 6 vCPU, 12 GB RAM, and NVMe storage — the sweet spot for workspaces up to about 500 users.
Table of Contents
What is Rocket.Chat?
Rocket.Chat is an open-source team collaboration platform written in TypeScript on top of the Meteor framework, with MongoDB as its primary data store. It has been developed openly on GitHub since 2015 and is used by organizations that need Slack-style chat but cannot — or will not — put their conversations on someone else's servers. The community edition is released under the MIT license and can be deployed on any Linux host with no seat limits and no feature gating on the core messaging experience.
At its core Rocket.Chat gives you persistent channels (public and private), direct messages, threads, reactions, message pinning, quoting, file uploads, full-text search, and read receipts. On top of that it adds a voice/video calling module powered by Jitsi or a built-in conference server, screen sharing, outgoing and incoming webhooks, a REST API, a real-time API over WebSockets, and a full apps framework for building custom integrations. The Omnichannel module turns the same platform into a customer support console that unifies livechat, WhatsApp, Telegram, Facebook Messenger, and SMS into a single queue.
For reference documentation beyond this tutorial, the official project docs at docs.rocket.chat are kept up to date by the Rocket.Chat team and cover every configuration flag, admin setting, and integration.
Why Self-Host Instead of Using Slack?
Running your own chat server is a deliberate trade-off. You take on maintenance in exchange for three things that hosted SaaS chat will never give you.
Cost at scale. Slack's Business+ plan is roughly USD 15 per user per month. A 100-person team pays Slack about USD 18,000 per year just to talk to each other. The same team on a self-hosted Rocket.Chat instance runs on a single VPS that costs under EUR 250 per year. Even factoring in a few hours of admin time per month, self-hosting is an order of magnitude cheaper once you pass about 20 users.
Data ownership and sovereignty. When you use Slack, every message, file, and DM is copied into Salesforce-owned infrastructure in the United States. Your legal team cannot guarantee where that data lives, who has subpoenaed it, or how long it is retained. A self-hosted Rocket.Chat instance on a VPS in Frankfurt keeps every byte under your control and under the jurisdiction you choose. For companies subject to GDPR, HIPAA, or sector-specific data protection rules (finance, defense, healthcare, government), self-hosting is often not optional — it is the only legally viable option.
No per-seat pricing, no message history limits. Slack's free tier caps message history at 90 days and gates search, integrations, and retention policies behind paid plans. Rocket.Chat's community edition has no such caps. Every message is searchable forever (subject to your retention policy), every integration is available, and adding users costs you nothing beyond the marginal RAM they consume.
Full customization and extensibility. The Rocket.Chat codebase is yours to read, patch, and extend. You can build custom apps against its SDK, change the UI theme to match your brand, embed it inside an existing portal with iframes, or run it entirely air-gapped behind a corporate firewall.
Other self-hosted alternatives worth considering in the same space include Mattermost (Go-based, developer-focused, stricter on resource usage) and Zulip (unique threaded-topic model, excellent for high-volume async discussion). Rocket.Chat sits between them as the most feature-complete option, with the strongest omnichannel and livechat story.
Prerequisites
Before you begin, make sure you have:
- An Ubuntu 24.04 LTS VPS with root or sudo access and at least 6 vCPU and 12 GB RAM. Rocket.Chat's Meteor runtime plus MongoDB plus Nginx comfortably fits in 8 GB for small teams, but headroom matters when the oplog grows.
- At least 100 GB of disk space (NVMe strongly preferred — MongoDB is latency-sensitive).
- A registered domain name with an A record pointed at your VPS IP (for example
chat.yourdomain.com). - Port 80 and 443 open in your firewall for HTTP/HTTPS.
- SMTP credentials from a transactional email provider (Postmark, Amazon SES, Mailgun, Brevo) or an authoritative mail server you control.
Recommended plan: Professional VPS (EUR 19.99/month)>
- 6 vCPU cores
- 12 GB RAM
- 200 GB NVMe SSD
- Unmetered bandwidth>
Order the Professional VPS
Connect to your server:
ssh root@your-server-ipStep 1: Prepare the Ubuntu 24.04 Server
Update the package index and upgrade everything:
apt update && apt upgrade -yInstall a minimal set of utilities you will need during the rest of the tutorial:
apt install -y curl ca-certificates gnupg lsb-release ufwEnable the firewall with SSH, HTTP, and HTTPS open:
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enableSet the hostname so MongoDB's replica set configuration is stable across reboots:
hostnamectl set-hostname chatStep 2: Install Docker Engine and Compose
Add the official Docker APT repository so you get the latest stable engine and the Compose v2 plugin:
install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.ascecho "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ > /etc/apt/sources.list.d/docker.list
apt update apt install -y docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin
Verify the installation:
docker --version
docker compose versionExpected output:
Docker version 27.x.x, build abcdef0
Docker Compose version v2.29.xStep 3: Create the Project Layout
Create a dedicated directory for the Rocket.Chat stack:
mkdir -p /opt/rocketchat
cd /opt/rocketchat
mkdir -p data/mongo data/mongo-config uploadsThe data/mongo directory holds MongoDB data files, data/mongo-config holds replica set metadata, and uploads holds Rocket.Chat file attachments (if you do not offload them to S3).
Step 4: Write the .env File
Create /opt/rocketchat/.env with the following content. Replace the placeholders marked with CHANGEME before saving.
# Public URL — must match the domain you will point at the server
ROOT_URL=https://chat.yourdomain.comPort Rocket.Chat listens on inside the Docker network
PORT=3000MongoDB connection strings — the replica set name must match on both sides
MONGO_URL=mongodb://mongodb:27017/rocketchat?replicaSet=rs0
MONGO_OPLOG_URL=mongodb://mongodb:27017/local?replicaSet=rs0Pin specific versions for reproducibility
ROCKETCHAT_VERSION=6.11.0
MONGODB_VERSION=6.0Deployment platform identifier (shown in admin UI)
DEPLOY_METHOD=docker
DEPLOY_PLATFORM=selfhostedFirst admin credentials — Rocket.Chat creates this account on first boot
ADMIN_USERNAME=admin
ADMIN_PASS=CHANGEME_use_a_long_random_password
[email protected]Lock down the file — it contains the admin bootstrap password:
chmod 600 /opt/rocketchat/.envWhy two MongoDB URLs? Rocket.Chat uses Meteor's real-time engine, which tails MongoDB's oplog to push updates to every connected client the instant a message is written. MONGO_URL is the application's database connection. MONGO_OPLOG_URL points at the special local database where the replica set oplog lives. Both are required, and both require a replica set — which is why we initialize one even for a single-node deployment.
Step 5: Write the docker-compose.yml
Create /opt/rocketchat/docker-compose.yml:
services: mongodb: image: mongo:${MONGODB_VERSION} restart: unless-stopped command: > mongod --oplogSize 128 --replSet rs0 --storageEngine wiredTiger --bind_ip_all volumes: - ./data/mongo:/data/db - ./data/mongo-config:/data/configdb healthcheck: test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"] interval: 10s timeout: 5s retries: 10
rocketchat: image: rocketchat/rocket.chat:${ROCKETCHAT_VERSION} restart: unless-stopped depends_on: mongodb: condition: service_healthy environment: ROOT_URL: ${ROOT_URL} PORT: ${PORT} MONGO_URL: ${MONGO_URL} MONGO_OPLOG_URL: ${MONGO_OPLOG_URL} DEPLOY_METHOD: ${DEPLOY_METHOD} DEPLOY_PLATFORM: ${DEPLOY_PLATFORM} OVERWRITE_SETTING_Show_Setup_Wizard: pending ADMIN_USERNAME: ${ADMIN_USERNAME} ADMIN_PASS: ${ADMIN_PASS} ADMIN_EMAIL: ${ADMIN_EMAIL} ports: - "127.0.0.1:3000:3000" volumes: - ./uploads:/app/uploads
Notes on this configuration:
--replSet rs0starts MongoDB with replica set support. Thers0name is referenced in bothMONGO_URLandMONGO_OPLOG_URL.--oplogSize 128caps the oplog at 128 MB, which is plenty for a single-node workspace.- We bind Rocket.Chat only to
127.0.0.1:3000. Public traffic will arrive through Nginx on ports 80/443 — the app container is never directly exposed. - The
depends_oncondition waits for MongoDB's healthcheck to pass before starting Rocket.Chat.
Step 6: Initialize the MongoDB Replica Set
Start MongoDB alone first:
cd /opt/rocketchat
docker compose up -d mongodbWait about 15 seconds for the server to be ready, then initiate the replica set:
docker compose exec mongodb mongosh --eval '
rs.initiate({
_id: "rs0",
members: [ { _id: 0, host: "mongodb:27017" } ]
})
'Expected output:
{ ok: 1 }Confirm the replica set is healthy:
docker compose exec mongodb mongosh --eval "rs.status().members[0].stateStr"Expected output:
PRIMARYIf you see SECONDARY or STARTUP, wait another 10 seconds and check again — election takes a moment.
Step 7: Start Rocket.Chat
Now bring up the Rocket.Chat service:
docker compose up -d rocketchatFollow the logs while the application boots. First boot builds the Meteor indexes and takes 30-60 seconds:
docker compose logs -f rocketchatYou are ready to move on once you see:
SERVER RUNNING
Rocket.Chat Version: 6.11.0
Meteor Version: 2.x
MongoDB Version: 6.0.x (oplogEnabled: true)
Site URL: https://chat.yourdomain.comThe oplogEnabled: true line is the proof that the replica set is working — without it, real-time updates would fall back to polling and the whole app would feel sluggish.
Press Ctrl+C to detach from the logs.
Step 8: Configure Nginx Reverse Proxy and TLS
Install Nginx and Certbot on the host:
apt install -y nginx certbot python3-certbot-nginxCreate /etc/nginx/sites-available/rocketchat:
upstream rocketchat_backend { server 127.0.0.1:3000; keepalive 64; }server { listen 80; server_name chat.yourdomain.com; return 301 https://$host$request_uri; }
server { listen 443 ssl http2; server_name chat.yourdomain.com;
# Filled in by Certbot in the next step ssl_certificate /etc/letsencrypt/live/chat.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/chat.yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
# Large file uploads — bump this to match your target upload size client_max_body_size 200m;
add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; add_header Referrer-Policy strict-origin-when-cross-origin;
location / { proxy_pass http://rocketchat_backend; proxy_http_version 1.1;
# WebSocket upgrade — critical for real-time message delivery proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forward-Proto $scheme; proxy_set_header X-Nginx-Proxy true;
proxy_redirect off;
# Long-lived WebSocket connections proxy_read_timeout 3600s; proxy_send_timeout 3600s; } }
Enable the site and obtain a certificate:
ln -s /etc/nginx/sites-available/rocketchat /etc/nginx/sites-enabled/ rm -f /etc/nginx/sites-enabled/default nginx -t systemctl reload nginx
certbot --nginx -d chat.yourdomain.com \ --agree-tos --redirect -m [email protected] --non-interactive
Certbot edits the Nginx config to point at the freshly issued certificate and installs a systemd timer that renews automatically every 60 days. Visit https://chat.yourdomain.com in your browser — you should see the Rocket.Chat login screen with a valid TLS padlock.
Why the WebSocket headers matter. Rocket.Chat's real-time UI depends on a persistent WebSocket connection upgraded from HTTP. Without the Upgrade and Connection headers and long proxy_read_timeout, messages would only appear after a page refresh and typing indicators would never arrive.
Step 9: Complete the Admin Setup Wizard
Log in with the admin credentials you set in .env. Rocket.Chat walks you through a three-step setup wizard:
Once the wizard completes you land in the admin area. Open Admin → Settings → General and set the Site URL to your full HTTPS URL — this is what Rocket.Chat uses for outbound email links and OAuth callbacks.
Step 10: Configure SMTP for Email
Rocket.Chat sends transactional email for invitations, password resets, mentions you missed while offline, and digest notifications. Without SMTP configured, none of these will work.
Open Admin → Settings → Email → SMTP and fill in:
- Host: your SMTP server (e.g.
smtp.postmarkapp.com) - Port: 587 for STARTTLS, 465 for implicit TLS
- Username / Password: provided by your email service
- From Email: a verified sender address on your domain
- Protocol:
smtps(port 465) or leave blank for STARTTLS
Step 11: Connect LDAP or SAML Identity Providers
For teams larger than a handful of people, you do not want to manage Rocket.Chat user accounts manually. Connect an identity provider so accounts are created and deactivated automatically.
LDAP / Active Directory
Admin → Settings → LDAP:
- Enable: On
- Host: your directory server (e.g.
ldap.corp.example.com) - Port: 389 (StartTLS) or 636 (LDAPS)
- Base DN:
dc=corp,dc=example,dc=com - User Search Field:
sAMAccountNamefor Active Directory,uidfor OpenLDAP - Bind DN and Bind Password: a read-only service account
SAML 2.0 / OpenID Connect
For SSO via Keycloak, Okta, Azure AD, or Google Workspace:
Admin → Settings → SAML (or OAuth for OIDC). Point it at your provider's metadata URL and paste the signing certificate. Enable JIT Provisioning so accounts are created on first login.
For a full self-hosted SSO setup, see our guide on installing Keycloak — it makes an excellent identity broker in front of Rocket.Chat, your wiki, and any other self-hosted apps.
Step 12: Enable Livechat and Omnichannel
Rocket.Chat's Omnichannel module turns the same platform into a customer support console.
Admin → Omnichannel → Enable: On. This unlocks:
- A livechat widget you embed on any website with a two-line script snippet.
- Departments and routing rules so incoming chats reach the right agent.
- Channel integrations for WhatsApp Business API, Telegram, Facebook Messenger, Twilio SMS, and email-to-chat.
- Canned responses, visitor tags, and CRM webhooks for Salesforce, HubSpot, and custom backends.
<script>
(function(w, d, s, u) {
w.RocketChat = function(c) { w.RocketChat._.push(c) };
w.RocketChat._ = [];
w.RocketChat.url = u;
var h = d.getElementsByTagName(s)[0],
j = d.createElement(s);
j.async = true;
j.src = 'https://chat.yourdomain.com/livechat/rocketchat-livechat.min.js?_=201903270000';
h.parentNode.insertBefore(j, h);
})(window, document, 'script', 'https://chat.yourdomain.com/livechat');
</script>Drop that in your site's footer and the floating chat bubble appears immediately.
Step 13: Install Apps from the Marketplace
Admin → Apps → Marketplace lists community and premium apps that extend Rocket.Chat. Popular picks:
- GitHub — PR and issue notifications in channels.
- Jira — ticket creation from
/jiraslash commands. - Jitsi — embedded video calls without leaving the chat.
- OpenAI / Claude — AI assistants that respond to
@aimentions in any channel. - Zapier — connect Rocket.Chat to 5,000+ third-party services.
You can also build your own apps with the Rocket.Chat Apps Engine SDK in TypeScript — the full developer reference is at docs.rocket.chat.
Step 14: Mobile Apps and Push Notifications
The official Rocket.Chat apps for iOS and Android are on the App Store and Google Play. Users connect them to your workspace by scanning a QR code from Profile → Account on the web client, or by typing the workspace URL manually.
Push notifications are the one area where a pure self-hosted setup gets complicated. Apple's APNs and Google's FCM only accept push traffic signed with developer keys that belong to the app on the store. Since your users are installing the official Rocket.Chat app, push notifications must flow through Rocket.Chat's hosted Push Gateway, which relays notifications on behalf of all self-hosted workspaces.
To enable the gateway:
The gateway is free for community edition workspaces. If you object to relaying notification metadata (workspace ID, user ID, a short preview) through Rocket.Chat's infrastructure, you have two options: build and self-distribute the mobile apps with your own Firebase keys, or accept that mobile users will only see new messages when the app is open.
Hardening and Backups
Fail2ban for login brute-force protection
apt install -y fail2banRocket.Chat logs failed logins to stdout, which Docker writes to the journal. A jail that watches the container logs blocks IPs that attempt more than five failed logins in 10 minutes.
MongoDB authentication
The Compose file above runs MongoDB without auth because the container is bound only to the Docker network. If you ever expose MongoDB on the host network, enable --auth and create a rocketchat user with read/write on both the rocketchat and local databases.
Automated backups
Create /opt/rocketchat/backup.sh:
#!/bin/bash set -euo pipefail TS=$(date +%Y%m%d-%H%M%S) BACKUP_DIR=/var/backups/rocketchat mkdir -p "$BACKUP_DIR"docker compose -f /opt/rocketchat/docker-compose.yml exec -T mongodb \ mongodump --archive --gzip --db=rocketchat \ > "$BACKUP_DIR/rocketchat-$TS.archive.gz"
tar -czf "$BACKUP_DIR/uploads-$TS.tar.gz" -C /opt/rocketchat uploads
find "$BACKUP_DIR" -type f -mtime +14 -delete
Make it executable and schedule nightly via cron:
chmod +x /opt/rocketchat/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * /opt/rocketchat/backup.sh") | crontab -Ship the archive off-site (rsync to another VPS, rclone to S3/B2, etc.) — a backup on the same disk as the primary is not a backup.
Troubleshooting
| Problem | Likely cause | Fix |
|---|---|---|
MongoError: no replica set members available on boot | Replica set not initiated | Run rs.initiate() as shown in Step 6 |
| Real-time updates lag, messages appear only after reload | MONGO_OPLOG_URL wrong, or MongoDB not in replica set mode | Check rs.status(); confirm oplogEnabled: true in Rocket.Chat logs |
Uploads fail with 413 Request Entity Too Large | Nginx client_max_body_size too small | Raise to match your target upload size, reload Nginx |
| WebSocket connection drops every minute | proxy_read_timeout too low | Set to 3600s as shown in the Nginx config |
| Push notifications never arrive | Workspace not registered with Rocket.Chat Cloud | Register under Admin → Connectivity Services, enable the gateway |
Invalid credentials despite correct password | LDAP search filter not returning user | Test with ldapsearch, verify the User Search Field matches your directory |
| Container eats 100% CPU at idle | Missing oplog — Meteor is polling | Same fix as "Real-time updates lag" above |
cd /opt/rocketchat
docker compose logs -f --tail=200 rocketchat
docker compose logs -f --tail=200 mongodbFAQ
Why does Rocket.Chat require a MongoDB replica set even on a single server?
Rocket.Chat uses Meteor's oplog tailing to push real-time updates to every connected client. The oplog — the MongoDB operations log — only exists on replica set members, not on standalone mongod instances. Even a single-node deployment must start with --replSet rs0 and run rs.initiate() once. Without the oplog Meteor falls back to polling the database every few seconds, which is slow, CPU-heavy, and defeats the point of a real-time chat app.
Is Rocket.Chat really free for self-hosters?
Yes. The community edition is released under the MIT license and runs with unlimited users, unlimited message history, unlimited channels, and no feature gating on core messaging. Paid editions (Pro, Enterprise) add things like high-availability clustering, premium marketplace apps, priority support, auto-scaling, and compliance add-ons. For a single-VPS workspace of any size, community is genuinely free and fully functional.
Do I need the Rocket.Chat push notification gateway?
If your users install the official iOS/Android apps from the public stores, yes. Apple APNs and Google FCM only accept push traffic signed with the app's developer keys — and those keys belong to Rocket.Chat, not you. The workaround is to register your workspace with Rocket.Chat Cloud (free) and let the hosted gateway relay notifications. The alternative is to fork and self-publish the mobile apps with your own Firebase credentials, which is a significant ongoing maintenance burden.
How do I integrate Rocket.Chat with an existing identity provider?
Rocket.Chat supports LDAP/Active Directory, SAML 2.0, OAuth 2.0, and OpenID Connect out of the box. Most organizations point it at Keycloak, Okta, Azure AD, or Google Workspace, enable just-in-time user provisioning, and map group memberships to Rocket.Chat roles. A self-hosted Keycloak sitting in front of Rocket.Chat is a common pattern that lets you reuse the same SSO across every self-hosted app you run.
How much disk space does Rocket.Chat use?
The application containers are under 2 GB combined. Long-term disk usage is dominated by message history, avatars, and file uploads stored in MongoDB's GridFS. A rough planning number is 5-10 GB per 100 active users per year in a typical team. If uploads grow beyond what your VPS disk can hold, point Rocket.Chat at S3-compatible object storage (Backblaze B2, Wasabi, MinIO) via Admin → Settings → File Upload → Storage Type: AmazonS3 — the MongoDB volume then stays small and cheap.
Can I migrate from Slack to Rocket.Chat?
Yes. Rocket.Chat ships with a built-in Slack import tool. Export your Slack workspace as a ZIP from https://{workspace}.slack.com/services/export, upload it under Admin → Import → Slack, and Rocket.Chat recreates channels, users, and message history. Private channels and DMs are included if the Slack export includes them (which requires a Plus or Enterprise Slack plan). Plan for the import to take anywhere from minutes to several hours depending on message volume.
Does Rocket.Chat support livechat and omnichannel customer support?
Yes. The built-in Omnichannel module provides a livechat widget you embed on any website, plus channel integrations for WhatsApp Business API, Telegram, Facebook Messenger, Twilio SMS, and email-to-chat. All conversations land in the same agent inbox as internal team chat, so your support team uses one tool instead of five. Routing rules, departments, canned responses, SLA timers, and CRM webhooks are all included in the community edition.
Next Steps
You now have a production-ready Rocket.Chat deployment. Good follow-ups:
- Stand up a Keycloak SSO broker — unify login across Rocket.Chat, your wiki, monitoring tools, and admin panels. See our Keycloak install guide.
- Compare Rocket.Chat with alternatives — if your team is mostly developers who live in terminal and care about ultra-low resource usage, try Mattermost. If you have high-volume async discussion that should not live in noisy channels, try Zulip.
- Add Jitsi for video calls — the Rocket.Chat Jitsi app gives you embedded conferences without screen-share size limits. Pair it with a self-hosted Jitsi Meet server for full ownership of call media.
- Enable message retention policies — Admin → Retention Policy lets you set per-channel TTLs so compliance requirements for "we don't keep chat more than 90 days" are enforced automatically.
- Hook up observability — Rocket.Chat exposes a Prometheus
/metricsendpoint (Admin → Settings → Logs → Prometheus). Scrape it from a Grafana Agent or Prometheus server to alert on high oplog lag, dropped WebSocket connections, or slow message delivery.
Want the right VPS for Rocket.Chat without overthinking sizing?>
Our Professional VPS is tuned for exactly this workload: 6 vCPU, 12 GB RAM, 200 GB NVMe, unmetered bandwidth, and EU data centers for GDPR-friendly hosting — all for EUR 19.99/month.>
Deploy a Professional VPS now