Rocket.Chat HTTPS Configuration: Running the Team Chat Platform Behind a TLS Reverse Proxy

Rocket.Chat is a self-hosted Slack alternative that handles real-time messages, file uploads, and video calls. Without TLS, all of that is visible on the network. Rocket.Chat is a Node.js application that does not handle TLS natively in most deployment configurations — TLS is the responsibility of a reverse proxy in front of it. This article covers configuring nginx with TLS for Rocket.Chat, updating the ROOT_URL, enabling WebSocket proxying, and setting up Snap-based deployments.

Rocket.Chat deployment types

DeploymentTLS approach
Snap (rocketchat-server)Caddy bundled in Snap handles TLS automatically
Docker / Docker Composenginx or Traefik as a sidecar
Manual Node.js installnginx reverse proxy
Kubernetes (Helm)Ingress controller with cert-manager

The nginx approach covers both Docker and manual installs. The Snap approach is covered separately below.

Option A: nginx reverse proxy (manual / Docker install)

Step 1: Obtain a certificate

certbot certonly --standalone -d chat.example.com

Or if nginx is already running:

certbot certonly --webroot -w /var/www/html -d chat.example.com

Step 2: Configure nginx

Create /etc/nginx/sites-available/rocketchat:

upstream rocketchat {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    listen 80;
    server_name chat.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name chat.example.com;

    ssl_certificate     /etc/letsencrypt/live/chat.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/chat.example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_stapling        on;
    ssl_stapling_verify on;

    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    add_header X-Frame-Options SAMEORIGIN always;
    add_header X-Content-Type-Options nosniff always;

    # Rocket.Chat uses long-polling and WebSockets
    location / {
        proxy_pass         http://rocketchat;
        proxy_http_version 1.1;
        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;

        # Required for long-polling (DDP / SockJS)
        proxy_buffering off;
        proxy_read_timeout 120s;
        proxy_connect_timeout 15s;
        proxy_send_timeout 120s;
        proxy_cache off;
    }

    # Increase upload size limit
    client_max_body_size 200M;
}

Enable and reload:

sudo ln -s /etc/nginx/sites-available/rocketchat /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Step 3: Set the ROOT_URL environment variable

Rocket.Chat uses the ROOT_URL environment variable (or ROCKETCHAT_URL in some Docker deployments) to generate all internal URLs. It must be the HTTPS URL.

For systemd / manual installs, edit the service file:

sudo systemctl edit rocketchat
[Service]
Environment=ROOT_URL=https://chat.example.com
Environment=PORT=3000
Environment=MONGO_URL=mongodb://localhost:27017/rocketchat

For Docker Compose, set in docker-compose.yml:

services:
  rocketchat:
    image: rocket.chat:latest
    environment:
      ROOT_URL: https://chat.example.com
      PORT: "3000"
      MONGO_URL: mongodb://mongo:27017/rocketchat
    ports:
      - "127.0.0.1:3000:3000"

Restart Rocket.Chat:

sudo systemctl restart rocketchat
# or
docker compose up -d rocketchat

Step 4: Update ROOT_URL via the admin panel

Rocket.Chat also stores ROOT_URL in its database. Update it via the admin panel:

  1. Log in as admin.
  2. Go to Administration → Settings → General.
  3. Update Site URL to https://chat.example.com.
  4. Click Save Changes.

If you cannot log in (URL mismatch preventing the UI from loading), update via MongoDB directly:

mongo rocketchat
db.rocketchat_settings.update({_id: 'Site_Url'}, {$set: {value: 'https://chat.example.com'}})

Or with mongosh:

mongosh rocketchat --eval 'db.rocketchat_settings.updateOne({_id: "Site_Url"}, {$set: {value: "https://chat.example.com"}})'

Option B: Snap deployment with automatic TLS

The Rocket.Chat Snap package includes Caddy as a reverse proxy and can obtain Let’s Encrypt certificates automatically.

Enable Caddy and Let’s Encrypt

# Set the domain
sudo rocketchat-server.caddy domains set chat.example.com

# Enable Caddy
sudo rocketchat-server.enable caddy
sudo systemctl restart snap.rocketchat-server.rocketchat-server

# Check Caddy logs
sudo journalctl -u snap.rocketchat-server.caddy -n 50

Caddy in the Snap will automatically request a Let’s Encrypt certificate for the domain and renew it without any additional configuration.

Update ROOT_URL for Snap

sudo snap set rocketchat-server siteurl=https://chat.example.com
sudo snap restart rocketchat-server

Docker Compose with Traefik

For Docker-based deployments, Traefik is a popular alternative to nginx:

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    command:
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=admin@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik_letsencrypt:/letsencrypt

  rocketchat:
    image: rocket.chat:latest
    environment:
      ROOT_URL: https://chat.example.com
      PORT: "3000"
      MONGO_URL: mongodb://mongo:27017/rocketchat
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.rocketchat.rule=Host(`chat.example.com`)"
      - "traefik.http.routers.rocketchat.entrypoints=websecure"
      - "traefik.http.routers.rocketchat.tls.certresolver=myresolver"
      - "traefik.http.routers.rocketchat-http.rule=Host(`chat.example.com`)"
      - "traefik.http.routers.rocketchat-http.entrypoints=web"
      - "traefik.http.routers.rocketchat-http.middlewares=https-redirect"
      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
      - "traefik.http.services.rocketchat.loadbalancer.server.port=3000"

  mongo:
    image: mongo:6.0
    command: mongod --replSet rs0

volumes:
  traefik_letsencrypt:

WebSocket and long-polling configuration

Rocket.Chat uses DDP (Distributed Data Protocol) over WebSocket for real-time messaging. The nginx proxy must handle WebSocket upgrades correctly.

The critical nginx settings for Rocket.Chat:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffering off;
proxy_read_timeout 120s;

Without proxy_buffering off and proper WebSocket headers, users will experience frequent disconnections and “Rocket.Chat is not connected” banners.


Certificate renewal

sudo nano /etc/letsencrypt/renewal-hooks/deploy/rocketchat.sh
#!/bin/bash
# Reload nginx (Rocket.Chat itself does not need restarting)
systemctl reload nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/rocketchat.sh

Verifying TLS and WebSocket connectivity

# Check HTTPS
curl -I https://chat.example.com

# Check certificate
openssl s_client -connect chat.example.com:443 -servername chat.example.com </dev/null 2>&1 \
  | openssl x509 -noout -dates

# Test WebSocket upgrade
curl -I -H "Upgrade: websocket" -H "Connection: Upgrade" \
  -H "Sec-WebSocket-Key: test" -H "Sec-WebSocket-Version: 13" \
  https://chat.example.com/websocket
# Expected: HTTP/1.1 101 Switching Protocols

Troubleshooting

ProblemCauseFix
“Rocket.Chat is not connected” bannerWebSocket not proxied correctlyAdd proxy_set_header Upgrade $http_upgrade to nginx
Login loop after TLS enabledROOT_URL still set to http://Update ROOT_URL env var and database Site_Url setting
File uploads failclient_max_body_size too small in nginxSet client_max_body_size 200M
Video calls not workingTURN/STUN behind TLS not configuredConfigure WebRTC settings in Administration → Settings → Video Conference
OAuth callbacks failExternal auth callback URL uses http://Update OAuth application redirect URI to https://

Summary

Rocket.Chat HTTPS is configured entirely through a reverse proxy. Set ROOT_URL=https://chat.example.com in the environment and update the Site URL in the admin panel to match. The nginx configuration must enable WebSocket proxying (Upgrade header and proxy_buffering off) or users will constantly disconnect. For Snap deployments, Caddy handles TLS automatically with rocketchat-server.caddy domains set. Traefik with Docker Compose provides automatic Let’s Encrypt certificate management using container labels.

Scroll to Top