Back to blog
Blog

Deploy Chatwoot on a VPS for Website Live Chat

Deploy Chatwoot on a VPS with Docker Compose, HTTPS reverse proxy, updates, and backups for Intercom-style live chat.

By Anurag Singh
Updated on Nov 02, 2026
Category: Blog
Share article
Deploy Chatwoot on a VPS for Website Live Chat

Live chat usually starts small. You add a widget to your marketing site, route messages into a shared inbox, and set up a few automations. Then the bill shows up.

Per-seat pricing turns “add one more teammate” into a budget meeting. If you want an Intercom-style setup without per-agent fees, a practical move in 2026 is to deploy Chatwoot on a VPS you control.

Chatwoot is an open-source customer support platform (AGPL-3.0). It covers live chat, a shared inbox, light automation, and team collaboration.

You run it on your own infrastructure. You choose retention and decide where customer data lives.

The tradeoff is ownership. Updates, backups, and TLS are on you.

The upside is predictable costs and a repeatable install. Docker Compose makes that easier.

Chatwoot, in plain terms: what you get and who it fits

Chatwoot sits between a basic “chat bubble” plugin and a full helpdesk suite. It’s built for teams that need a shared inbox and real-time conversations.

It’s also a good fit if you don’t want to hand customer messages to a hosted SaaS. It’s a fit if you don’t want to pay per seat, either.

  • Best fit: SaaS founders, agencies, e-commerce stores, and ops teams that want a team inbox + live chat on their own domain.
  • Not ideal: teams that need deep ITSM workflows, complex ticket SLAs, or heavy CRM features out of the box.

Operationally, Chatwoot is a familiar three-piece stack: the web app, PostgreSQL, and Redis. That maps cleanly to a single VPS today.

You can scale later by splitting services out.

How Chatwoot compares to Intercom-style hosted chat

Hosted chat wins on convenience. You sign up, paste a snippet, and you’re done.

Self-hosting wins on predictable cost and tighter control of data.

  • Cost model: Intercom-style tools commonly scale with seats and contacts. Chatwoot scales with your server resources and your time.
  • Data and retention: with Chatwoot, your messages, contacts, and attachments stay on your infrastructure (or your chosen object storage).
  • Customization: you control domain, branding, headers, and proxy rules. You can also place it behind private networking if needed.
  • Operational responsibility: you patch it, monitor it, and back it up. If you want less of that burden, managed hosting becomes attractive.

If the main pain is per-seat pricing, self-hosted Chatwoot is usually the clean fix.

If the main pain is “I don’t want to run servers,” a hosted product will feel easier day to day.

Resource planning before you deploy Chatwoot on a VPS

The most common failure mode is a too-small VPS. Low RAM and slow disk quickly turn into “the app is laggy” complaints.

Chatwoot itself isn’t huge. PostgreSQL and background jobs still need steady memory and fast storage.

  • Small team (1–5 agents): 2 vCPU, 4 GB RAM, 50+ GB NVMe storage.
  • Medium team (5–20 agents): 4 vCPU, 8 GB RAM, 80–160 GB NVMe.
  • Busy inbox + long retention: prioritize disk and PostgreSQL tuning; consider 8+ GB RAM and a dedicated database host later.

For networking, keep it simple. Expose 80/443 and lock down everything else.

If you’re hosting multiple apps on one VPS, plan a reverse proxy from day one. It prevents routing sprawl later.

If you’d rather spend time on support workflows instead of OS maintenance, managed VPS hosting keeps the server baseline handled while you still control the application.

Deployment approach: Docker Compose on Ubuntu or Debian

Chatwoot supports containerized deployment. For most teams, Docker Compose hits the right balance.

You get a repeatable setup and readable config. Updates are also straightforward.

The steps below assume Ubuntu or Debian on a VPS, plus a real domain pointed at the server.

If you still need to point DNS at your VPS, this HostMyCode guide walks through changes without avoidable downtime: migrate a domain to Cloudflare DNS without downtime.

Prerequisites (quick checklist)

  • A VPS (Ubuntu or Debian recommended)
  • A domain/subdomain like chat.example.com pointing to your VPS IP
  • Docker + Docker Compose plugin installed
  • A plan for TLS termination (Caddy or Nginx)

Create a minimal Compose stack

Create a working directory, for example:

sudo mkdir -p /opt/chatwoot
sudo chown -R $USER:$USER /opt/chatwoot
cd /opt/chatwoot

Then create docker-compose.yml. This is a solid starting point for a single-host install with Postgres and Redis on the same VPS:

services:
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: chatwoot
      POSTGRES_USER: chatwoot
      POSTGRES_PASSWORD: change-this-password
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    restart: unless-stopped

  redis:
    image: redis:7
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - ./data/redis:/data
    restart: unless-stopped

  chatwoot:
    image: chatwoot/chatwoot:latest
    depends_on:
      - postgres
      - redis
    environment:
      RAILS_ENV: production
      NODE_ENV: production
      SECRET_KEY_BASE: replace-with-a-long-random-string
      FRONTEND_URL: https://chat.example.com
      POSTGRES_HOST: postgres
      POSTGRES_DATABASE: chatwoot
      POSTGRES_USERNAME: chatwoot
      POSTGRES_PASSWORD: change-this-password
      REDIS_URL: redis://redis:6379
      ENABLE_ACCOUNT_SIGNUP: "false"
    volumes:
      - ./data/storage:/app/storage
    restart: unless-stopped

A few operator notes:

  • Pin major versions for databases (Postgres 16, Redis 7) so upgrades are intentional.
  • Keep storage on a real disk volume. Chat attachments and avatar uploads live under /app/storage.
  • Disable public signups once your admin account exists. You don’t want random registrations.

Boot it once, then create your first admin

Bring the stack up:

docker compose up -d

Next, create an admin user. Chatwoot provides Rails tasks, but the exact task name can vary by image tag.

The safe approach is to exec into the container first. Then list tasks and look for the admin-related one:

docker compose exec chatwoot bash -lc "bundle exec rails -T | grep -i admin"

After you create the admin, keep ENABLE_ACCOUNT_SIGNUP set to false (as shown). Then restart:

docker compose up -d

Reverse proxy + HTTPS: Caddy (simple) or Nginx (familiar)

A reverse proxy keeps your container network private. It also handles TLS, HSTS, and sensible request limits.

Nginx and Caddy both work. If you want fewer moving parts, Caddy’s automatic Let’s Encrypt setup is usually the fastest route.

Option A: Caddy with automatic TLS

If you want a step-by-step setup, HostMyCode’s walkthrough is straightforward: Set Up Let’s Encrypt With Caddy for a VPS Site.

Example /etc/caddy/Caddyfile:

chat.example.com {
  encode gzip zstd

  reverse_proxy 127.0.0.1:3000

  header {
    Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    X-Content-Type-Options "nosniff"
    X-Frame-Options "SAMEORIGIN"
    Referrer-Policy "strict-origin-when-cross-origin"
  }
}

This assumes Chatwoot is listening on localhost port 3000.

If your container only exposes an internal port, publish it explicitly in Compose. For example: ports: - "127.0.0.1:3000:3000". That keeps it off the public internet.

Option B: Nginx with Let’s Encrypt

If you already standardize on Nginx across your VPS fleet, stick with it. These two troubleshooting posts tend to come in handy sooner or later:

Don’t ignore upload limits. Live chat conversations routinely include screenshots and small files.

Operational basics: mail delivery, DNS, and firewall

Chatwoot sends invites, password resets, and notifications. If email deliverability is shaky, people will blame the chat tool.

Sort SMTP early. It prevents a lot of avoidable noise.

  • SMTP: use a reputable transactional SMTP provider or your own relay.
  • Domain auth: publish SPF and DKIM, then add DMARC. This reduces spam-folder delivery.

If you need a clean refresher on domain authentication, this guide stays practical: Set Up DKIM, SPF, And DMARC For A Domain.

On the firewall side, keep it boring and strict:

  • Allow 22/tcp (or your SSH port), 80/tcp, and 443/tcp.
  • Block direct database access from the internet. Postgres should not be listening on a public interface.
  • If you publish Chatwoot’s app port for the reverse proxy, bind it to 127.0.0.1 only.

Backups that actually help: Postgres + uploads + config

“We back up the VPS” isn’t a recovery plan. For Chatwoot, you need three things: the Postgres database, the persistent uploads directory, and the config that defines your stack.

What to back up

  • Database: conversations, contacts, inbox configs, user accounts.
  • Uploads: attachments and stored assets under /opt/chatwoot/data/storage (or your chosen path).
  • Config: docker-compose.yml, environment variables, reverse proxy config.

A practical backup routine (example)

Create a backup folder:

sudo mkdir -p /var/backups/chatwoot
sudo chown -R root:root /var/backups/chatwoot
sudo chmod 700 /var/backups/chatwoot

Database dump (run from the VPS):

cd /opt/chatwoot
docker compose exec -T postgres pg_dump -U chatwoot chatwoot | gzip > /var/backups/chatwoot/chatwoot.sql.gz

Archive uploads + Compose files:

tar -C /opt/chatwoot -czf /var/backups/chatwoot/chatwoot-files.tgz docker-compose.yml data/storage

Then ship those backups offsite (object storage, another VPS, or a backup provider). Offsite is the whole point.

Local copies help with small mistakes. They won’t save you from a dead disk, a compromised server, or a broken snapshot chain.

Test restores, not just backups

Once a month, restore to a scratch VM or a second VPS. Log in and confirm recent conversations show up.

If you can’t restore on demand, you don’t have backups—you have archives.

Updating Chatwoot safely (without breaking your inbox)

Self-hosting feels easy until update day. You want a routine you can repeat, roll back from, and run without surprises.

  • Read release notes: especially for database migrations.
  • Back up first: DB dump + storage archive.
  • Pull images and restart: keep downtime predictable.

Typical update flow:

cd /opt/chatwoot
docker compose pull
docker compose up -d
docker image prune -f

If a migration is required, Chatwoot will usually run it during startup.

Still, watch logs on the first boot after an update:

docker compose logs -f --tail=200 chatwoot

Keep the OS patched as well. If you want automated security updates on Ubuntu, HostMyCode lays out a sensible baseline here: Set Up Automated Security Updates on Ubuntu VPS.

Common pitfalls (and how to avoid them)

  • Uploads fail with 413 errors: raise client_max_body_size in Nginx or your proxy equivalent. See the HostMyCode fix guide linked above.
  • Random “bad gateway” after reboot: your reverse proxy starts before containers or points to the wrong upstream. Confirm ports and container health.
  • Email doesn’t arrive: missing SPF/DKIM, blocked outbound SMTP, or bad SMTP credentials. Test with a single password reset email and check logs.
  • Public signups left enabled: bots will find it. Turn off account signup after initial setup.
  • No offsite backups: a VPS snapshot is not enough if the account is compromised or the snapshot chain breaks.

Where Chatwoot fits in a real hosting stack

Chatwoot works fine as a one-VPS app. It also fits nicely into a small internal tooling set:

If you host multiple customer sites (agency or reseller model), consider isolating Chatwoot on its own VPS.

That way, a noisy neighbor can’t drag down your client sites.

Summary: a predictable-cost live chat stack you control

Chatwoot is a strong replacement for hosted live chat when pricing scales faster than your headcount. You get a shared inbox, live chat, and ownership of customer conversations.

In return, you take on the basics: TLS, updates, backups, and monitoring.

If you want to run it on clean, fast infrastructure, start with a HostMyCode VPS. If you’d rather not spend your week on patching and service restarts, choose managed VPS hosting and keep the operational baseline tight while you focus on support.

If you’re rolling out Chatwoot for customer support, put it on a VPS with enough RAM for Postgres, Redis, and peak chat traffic. HostMyCode offers VPS plans that fit small teams and managed VPS hosting when you want the OS maintenance handled for you.

FAQ: Chatwoot self-hosting questions that come up early

Does Chatwoot replace Intercom completely?

It covers the core “website chat + shared inbox” workflow well. If you depend on a deep CRM, advanced outbound campaigns, or complex product tours, you may still keep separate tools.

Can I run Chatwoot on shared hosting?

Not realistically. Chatwoot needs background jobs, Redis, and a database you control. A VPS or dedicated server is the right fit.

What’s the minimum VPS size that won’t feel slow?

For a real team inbox, aim for 2 vCPU and 4 GB RAM. It’ll run on less, but PostgreSQL and background jobs will feel constrained under load.

Do I need a separate database server?

No for most small and medium teams. Start with Postgres on the same VPS, keep daily dumps, and move it out later if disk I/O or RAM becomes tight.

How do I keep Chatwoot secure?

Use HTTPS only, disable public signups after setup, keep your OS updated, restrict ports with a firewall, and store backups offsite. Treat it like any production web app.