Skip to content

How to Deploy Rocket.Chat on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Rocket.Chat on your own VPS with the official rocketchat-compose repo — MongoDB replica set, NATS, bundled Traefik with Let's Encrypt, a pinned release, and the setup wizard that creates your admin.

Before you start
  • A VPS with 4 vCPU / 8 GB RAM for a production team (upstream sizes the app and MongoDB at 4 GB each)
  • A fresh Ubuntu 24.04 server with root/sudo SSH access (see the MongoDB note on 26.04 below)
  • A domain you can point at the server, e.g. chat.example.com
  • Docker Engine + Compose installed (see the base guide below)
  • git on the server — the official deployment is a repository you clone
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Rocket.Chat is

Rocket.Chat is an MIT-licensed team chat platform: channels, direct messages, threads, and an omnichannel inbox for customer conversations, with voice and video added through marketplace apps. It is a Node.js application backed by MongoDB, and it is the most extensible of the self-hosted Slack alternatives — which is also why its official deployment is bigger than most chat apps.

Upstream's supported Docker path is the rocketchat-compose repository. It is not one compose file but several you stack together:

  • compose.yml — Rocket.Chat itself
  • compose.database.yml — MongoDB (official mongodb-community-server image) as a single-node replica set, plus an exporter
  • compose.nats.yml — NATS, the message bus Rocket.Chat uses between instances
  • compose.traefik.yml — Traefik as the reverse proxy, with Let's Encrypt
  • compose.monitoring.yml — Prometheus, Grafana, Loki and a log collector
  • docker.yml — Docker-specific overrides (health check, log collection)

This guide follows that path as written, because it's what upstream tests and what their update notes assume. If you're choosing between chat servers first, Mattermost vs Rocket.Chat covers the trade-offs, and Mattermost and Zulip have their own guides.

Server sizing

Upstream's system requirements for the smallest tier (up to 500 concurrent users) list 2 vCPU / 4 GiB RAM / 20 GiB disk for Rocket.Chat and 2 vCPU / 4 GiB RAM / 10 GiB disk for MongoDB. Put both on one box and that is an 8 GB RAM server — which is why we list 8 GB as the minimum.

For reference, the whole stack (app, MongoDB, NATS, Traefik and the monitoring containers) measured ~1,290 MB of RAM at idle on our test box, with ~5.7 GB of disk used after install. Idle is not load: MongoDB grows its cache as the message history grows, and file uploads land in the database by default (GridFS). Give it the headroom.

A note on Ubuntu 26.04: Rocket.Chat's docs warn that MongoDB 8.x may fail to start on Ubuntu 26.04 because MongoDB 8.0+ is incompatible with Linux kernel 6.19. Rocket.Chat 8.x requires MongoDB 8.0 or later, so you cannot sidestep it with an older MongoDB. Upstream's advice is Ubuntu 24.04 LTS for now; if you are on 26.04, check the kernel (uname -r) before you start.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed, along with a non-root user and a ufw firewall. If not, work through Docker & Compose on Ubuntu first.

Open SSH and the web ports only:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose

One caveat worth knowing before the install: ports that Docker publishes bypass ufw. Upstream's compose.yml publishes Rocket.Chat's port 3000 (and its metrics port 9458) on 0.0.0.0 by default. The config below binds them to loopback instead, so Traefik is the only public way in.

Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
DigitalOceanalso works on
1 vCPU · 1 GB RAM · 25 GB SSD · $6.00/mo
Deploy on DigitalOcean → (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Rocket.Chat

Clone the official repository and create your .env from the example:

sudo apt-get install -y git
cd ~
[ -d rocketchat-compose ] || git clone --depth 1 https://github.com/RocketChat/rocketchat-compose.git
cd ~/rocketchat-compose
[ -f .env ] || cp .env.example .env

Now edit .env. Four changes before the first start:

  • RELEASE — pin an exact version. The example ships an older default (8.0.1); upstream is explicit that production should use fixed versions, never latest. At the time of writing the current release is 8.8.1.
  • BIND_IP=127.0.0.1 — keeps ports 3000 and 9458 off the public interface.
  • GRAFANA_ADMIN_PASSWORD — the example ships rc-admin. Replace it with a generated one. Grafana only reads it on first start, so do it now.
  • COMPOSE_FILE — a standard Docker Compose variable that lists the files to stack. Setting it means later commands (docker compose ps, pull, logs) see the whole stack without the six -f flags.
cd ~/rocketchat-compose
setenv() { if grep -q "^$1=" .env; then sed -i "s|^$1=.*|$1=$2|" .env; else echo "$1=$2" >> .env; fi; }
setenv RELEASE 8.8.1
setenv BIND_IP 127.0.0.1
grep -q '^GRAFANA_ADMIN_PASSWORD=rc-admin$' .env && setenv GRAFANA_ADMIN_PASSWORD "$(openssl rand -hex 24)"
setenv COMPOSE_FILE compose.monitoring.yml:compose.traefik.yml:compose.database.yml:compose.yml:compose.nats.yml:docker.yml
chmod 600 .env
grep -E '^(RELEASE|BIND_IP|DOMAIN|ROOT_URL|LETSENCRYPT_ENABLED|TRAEFIK_PROTOCOL)=' .env

Leave DOMAIN=localhost, TRAEFIK_PROTOCOL=http and LETSENCRYPT_ENABLED=false for this first start. Leave LETSENCRYPT_EMAIL filled in, too: Traefik refuses to start with it empty, even when Let's Encrypt is off.

Start the stack with upstream's command:

cd ~/rocketchat-compose
docker compose -f compose.monitoring.yml -f compose.traefik.yml -f compose.database.yml -f compose.yml -f compose.nats.yml -f docker.yml up -d

The first start pulls a dozen images, starts MongoDB, and an init container runs rs.initiate to create the replica set Rocket.Chat needs. Rocket.Chat then creates its database on first connect. Expect a few minutes before it answers. Poll until it does:

cd ~/rocketchat-compose
for i in $(seq 1 60); do curl -fsS http://127.0.0.1:3000/api/info && break; sleep 10; done
echo
docker compose ps

A JSON response from /api/info means the server is up. It is only reachable from the box itself: port 3000 is on loopback, and Traefik only routes requests whose Host matches DOMAIN, which is still localhost. That's deliberate. The first person to finish the setup wizard becomes the administrator, so you don't want the wizard on a public IP before you get to it.

HTTPS + domain with the bundled Traefik

Point an A record for chat.example.com at the server's public IP and wait for it to resolve. Then switch .env to your domain and turn on Let's Encrypt. Traefik uses the TLS challenge on port 443, so that port must be reachable:

cd ~/rocketchat-compose
sed -i \
  -e 's|^DOMAIN=.*|DOMAIN=chat.example.com|' \
  -e 's|^ROOT_URL=.*|ROOT_URL=https://chat.example.com|' \
  -e 's|^LETSENCRYPT_ENABLED=.*|LETSENCRYPT_ENABLED=true|' \
  -e 's|^LETSENCRYPT_EMAIL=.*|LETSENCRYPT_EMAIL=you@example.com|' \
  -e 's|^TRAEFIK_PROTOCOL=.*|TRAEFIK_PROTOCOL=https|' \
  .env
docker compose up -d

ROOT_URL must match the address people actually use, scheme included. Rocket.Chat builds links, OAuth callbacks and email URLs from it, and a mismatch produces a warning banner and broken links. Grafana is served on the same domain under /grafana (the GRAFANA_PATH default). Log in as admin with the password you generated: grep GRAFANA_ADMIN_PASSWORD ~/rocketchat-compose/.env.

Alternative: Caddy instead of Traefik

If you already run Caddy on the box, the repo supports dropping the proxy. Upstream's README says to leave a component's compose file out of the command to exclude it, and the docs show the stack started without compose.traefik.yml for an Nginx setup. With BIND_IP already on loopback, that's a two-line change:

cd ~/rocketchat-compose
sed -i \
  -e 's|^COMPOSE_FILE=.*|COMPOSE_FILE=compose.monitoring.yml:compose.database.yml:compose.yml:compose.nats.yml:docker.yml|' \
  -e 's|^ROOT_URL=.*|ROOT_URL=https://chat.example.com|' \
  .env
docker compose up -d --remove-orphans

Then the whole Caddyfile entry is:

chat.example.com {
    reverse_proxy 127.0.0.1:3000
}

Caddy's reverse_proxy passes WebSocket upgrades through without extra config. In this setup Grafana is not proxied. It stays on 127.0.0.1:5050 (GRAFANA_BIND_IP/GRAFANA_HOST_PORT), so reach it over an SSH tunnel.

The setup wizard

Open https://chat.example.com. The first load runs a one-time wizard:

  1. Admin information: full name, username, email and password. This account is the workspace administrator. Use a real mailbox and a long, generated password.
  2. Organization information: organization name, industry, size and country.
  3. Register your workspace: Rocket.Chat asks for an email, acceptance of its terms and privacy policy, and a click on Register workspace. A confirmation link is sent to that address. This connects the workspace to Rocket.Chat Cloud.

After you confirm, you land in the workspace as the admin. The wizard appears only once, so finish it in one sitting.

Securing it

  • Keep ports 3000 and 9458 on loopback. Check with sudo ss -tlnp | grep -E ':(3000|9458)' — both should show 127.0.0.1.
  • MongoDB has no password (ALLOW_EMPTY_PASSWORD=yes in upstream's compose). It is safe only because the port is bound to 127.0.0.1 (MONGODB_BIND_IP). Never change that bind to 0.0.0.0.
  • Leave the Traefik dashboard off. Upstream publishes port 8080 for it, but the API stays disabled unless you set TRAEFIK_API_INSECURE=true. Don't.
  • Review account registration in the admin settings before you share the URL, and decide whether people can sign up themselves or only by invite.

Backups

Messages, settings, users and (by default) uploaded files all live in MongoDB, so a MongoDB dump is the backup. This is upstream's mongodump --archive, compressed and dated, plus a copy of .env:

cd ~/rocketchat-compose
mkdir -p ~/backups
docker compose exec -T mongodb sh -c 'mongodump --archive' | gzip > ~/backups/rocketchat-$(date +%F).archive.gz
cp .env ~/backups/rocketchat-env-$(date +%F)
chmod 600 ~/backups/rocketchat-env-*
ls -lh ~/backups

Copy both off the box. A backup on the same disk as the database protects you from mistakes, not from losing the server. If you moved file uploads to S3 or MinIO, back up that bucket separately.

To restore, stream the archive back in with mongorestore:

cd ~/rocketchat-compose
gunzip -c ~/backups/rocketchat-YYYY-MM-DD.archive.gz | docker compose exec -T mongodb sh -c 'mongorestore --archive'
docker compose restart rocketchat

Upgrades

Each Rocket.Chat version is supported for six months after release, so plan to upgrade regularly. Read the release notes and upstream's update guidelines before a version jump, and take a backup first. The routine is: update the compose repo, change RELEASE in .env, pull, and recreate:

cd ~/rocketchat-compose
git pull --ff-only
docker compose pull
docker compose up -d
for i in $(seq 1 60); do curl -fsS http://127.0.0.1:3000/api/info && break; sleep 10; done

As written, that re-pulls your pinned version. To move to a new release, first set it, e.g. sed -i 's|^RELEASE=.*|RELEASE=8.9.0|' .env (use the real version number from the releases page). MongoDB is upgraded the same way through MONGODB_VERSION (then docker compose up -d). Upstream documents it as a separate step from the app upgrade.

Troubleshooting

curl on port 3000 never answers. Run docker compose ps and read the state of mongodb and mongodb-init-container. If MongoDB is restarting, read docker compose logs --tail 100 mongodb. On Ubuntu 26.04 this is usually the kernel 6.19 incompatibility described above. If MongoDB is healthy but Rocket.Chat keeps restarting, read docker compose logs --tail 100 rocketchat. The replica set must be initiated before Rocket.Chat can connect.

Compose errors with need email for cert expiry notifications. Traefik's compose file refuses to start without LETSENCRYPT_EMAIL, even with Let's Encrypt disabled. Put any address back in .env.

The site loads over the IP but not the domain (404), or vice versa. Traefik routes only on Host(DOMAIN). Check that DOMAIN in .env is the bare hostname (no https://) and that you ran docker compose up -d after changing it.

No certificate / browser TLS error. LETSENCRYPT_ENABLED=true and TRAEFIK_PROTOCOL=https both need to be set, DNS must already resolve, and port 443 must be reachable from the internet for the TLS challenge. Check docker compose logs --tail 100 traefik.

Links and emails point to localhost. ROOT_URL still has the default. Set it to your public HTTPS address and recreate the stack.

To follow the app's logs live while you reproduce a problem:

cd ~/rocketchat-compose
docker compose logs -f rocketchat

Verification + next steps

You're done when https://chat.example.com loads over a valid certificate, the wizard is complete and you're logged in as admin, ss shows 3000, 9458 and 27017 on loopback only, and a dated backup archive exists somewhere other than this server.

From there, configure SMTP in the admin settings so invites and password resets work, then install the mobile apps and sign in to your server URL. If you want single sign-on, pair it with Keycloak or Authentik. For hosting picks sized for workloads like this, see Best VPS for Self-Hosting and Best VPS for Docker.

Next steps

How to self-host Rocket.Chat →More self-hosted team chat tools →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Audiobookshelf on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.