Deployment guide

Self-Host Chatwoot on a VPS: Open-Source Omnichannel Support

Deploy on a VPS Cloud →

Tutorial

Self-Host Chatwoot on a VPS: Open-Source Omnichannel Support

Self-hosting12 min read10 steps

Intercom and Zendesk charge per agent, lock you out of your own data and scale costs with your team. Chatwoot (MIT, 34 k+ stars, v4.17.1) offers a radical alternative: an open-source omnichannel customer support platform you host on your own VPS. Live chat on your site, email threads, WhatsApp Business, Telegram, Facebook Messenger and Twitter/X DMs — all your customer conversations in one shared inbox, with no per-agent fees and no data leaving your infrastructure.

Contents· Why self-host your customer support1/12
  1. 01Why self-host your customer support
  2. 02What you get with a self-hosted Chatwoot
  3. 03Prerequisites
  4. 04Deploy Chatwoot on a VPS in 6 steps
  5. 05Managing multiple inboxes
  6. 06Chatwoot integrations: webhooks, Slack, REST API
  7. 07Updating Chatwoot
  8. 08Migrating from Chatwoot v3 to v4
  9. 09v3 → v4 migration procedure
  10. 10Troubleshooting: common errors
  11. 11Chatwoot vs Crisp vs Intercom: which tool for which situation
  12. 12Official documentation

Why self-host your customer support

SaaS customer support solutions have a simple business model: you pay per agent and per channel, and your customer data is stored on their servers. For a web agency or an SME, this can quickly amount to several hundred dollars per month once the team exceeds two or three people. Chatwoot reverses this equation: you deploy the platform on your own VPS, invite as many agents as needed, and connect all your channels at no extra cost. Your customer exchanges stay on your infrastructure — a compelling argument for GDPR compliance, customer trust and data sovereignty.

What you get with a self-hosted Chatwoot

  • Shared omnichannel inbox: livechat, email, WhatsApp, Telegram, Facebook Messenger and Twitter/X DMs in a single dashboard.
  • Embeddable livechat widget: a customisable widget to add to any website with two lines of JavaScript.
  • Canned responses and automation rules: automatic assignment, first-contact reply and routing by language or keyword.
  • Team collaboration: internal notes, conversation assignment, mentions and team queues visible to all agents.
  • Integrated CRM: contact profiles with conversation history, custom attributes and labels.
  • REST API and webhooks: integration with n8n, Activepieces or your own backend.
  • MIT licence — no per-agent pricing, no data sent to a third party, full sovereignty.

Prerequisites

Chatwoot runs on a Ruby on Rails + Sidekiq + PostgreSQL 15 + Redis 7 stack — four Docker containers. Plan for a VPS with at least 2 GB of RAM (4 GB recommended for teams of more than 10 agents). Ubuntu 24.04 with Docker is the fastest path. On the network side, prepare a subdomain — support.your-domain.com for example — and a reverse proxy (Nginx or Caddy) to enable HTTPS. Chatwoot requires a FRONTEND_URL over HTTPS for OAuth redirects, email links and the livechat widget script to work correctly.

Before you start, verify that Docker Compose v2 is installed (docker compose version): Chatwoot v4 uses the docker compose syntax (with a space) rather than the legacy docker-compose command.

Deploy Chatwoot on a VPS in 6 steps

  1. One-click deployment from the ServOrbit marketplace

    Open your ServOrbit control panel, go to Marketplace → Collaboration and productivity → Chatwoot, then click Deploy. Docker pulls chatwoot/chatwoot:latest and starts four containers: PostgreSQL, Redis, the Rails web server and the Sidekiq worker. On first start, the database migration runs automatically — wait 60 to 90 seconds before the interface becomes available.

    For a manual installation, clone the official docker-compose.yml, copy .env.example to .env, set SECRET_KEY_BASE (generate it with openssl rand -hex 64) and run:

    docker compose up -d
    docker compose exec rails bundle exec rails db:chatwoot_prepare
  2. Create the administrator account

    Go to http://<your-vps-ip>:3000. Chatwoot displays a first-configuration wizard: enter your name, email address and a strong password. This account becomes the super-administrator. You can then invite additional agents and create teams from the Settings panel.

    If the page stays blank after 90 seconds, check the web container logs: docker compose logs web --tail=50. A SECRET_KEY_BASE not set or PG::ConnectionBad error points to a misconfiguration in .env.

  3. Configure FRONTEND_URL and enable HTTPS

    Point your domain to the VPS (A record → VPS IP). Install Caddy (apt install -y caddy) and create /etc/caddy/Caddyfile: support.your-domain.com { reverse_proxy localhost:3000 }. Reload Caddy (systemctl reload caddy). Then set FRONTEND_URL=https://support.your-domain.com in your .env file and restart the web container: docker compose restart web. Chatwoot uses this URL for OAuth redirects, email links and the widget script.

    Also enable FORCE_SSL=true in .env so Rails redirects HTTP connections to HTTPS and sets Secure cookies.

  4. Add your first inbox

    In Chatwoot, go to Settings → Inboxes → Add Inbox. Choose Website for livechat, Email for SMTP/IMAP exchanges, or a messaging channel like WhatsApp Cloud API or Telegram. For livechat, copy the generated JavaScript snippet and paste it into the <head> of your website. Visitors immediately see the chat bubble.

  5. Invite agents and configure automation

    Go to Settings → Agents and send email invitations. In Settings → Automation, create rules to automatically assign conversations (for example, WhatsApp → sales team, email → billing) and send first-contact messages outside business hours. The Sidekiq worker handles all asynchronous tasks: sending emails, triggering webhooks and push notifications.

  6. Connect WhatsApp Business (optional)

    Create a Meta for Developers app and enable the WhatsApp Business Cloud API. In Chatwoot → Settings → Inboxes → Add → WhatsApp, enter your WhatsApp Business phone number, WhatsApp Business account ID, access token and Webhook verification token. Incoming WhatsApp messages now appear in the shared inbox alongside livechat and emails.

Set up canned responses (Settings → Canned Responses) on day one: contact acknowledgement, order confirmation, processing times. Your agents save several minutes per conversation — and tone consistency is maintained regardless of who replies. Combine with automation rules to automatically send the first-contact reply at night and on weekends.

Managing multiple inboxes

Chatwoot lets you centralise multiple channels in a single interface. Each channel creates an independent inbox, visible in the sidebar and assignable to a dedicated team.

Email (SMTP/IMAP): in Settings → Inboxes → Email, enter your inbound address and IMAP credentials. Chatwoot polls the mailbox every two minutes and creates one conversation per thread. Replies are sent via SMTP while preserving the same thread.

Twitter/X DMs: connect an account via the Twitter v2 API (API key + secret + access token). Incoming direct messages appear in real time via webhook. Note: Twitter v2 API access requires a Basic or higher developer subscription.

Phone and WebRTC: Chatwoot v4.17 migrated its video call integration from Dyte to Cloudflare RealtimeKit. If you use video calls, reconfigure the integration under Settings → Integrations → Cloudflare Calls with your App ID and App Token.

API channel: for custom integrations (chatbot, in-house CRM), create an API-type inbox. It exposes a REST endpoint to receive messages and you send replies via POST /api/v1/accounts/{id}/conversations/{conv_id}/messages. This is the entry point for connecting any external source.

Chatwoot integrations: webhooks, Slack, REST API

Chatwoot offers several levels of integration to fit into your existing stack.

Webhooks: in Settings → Integrations → Webhooks, add your endpoint URL. Chatwoot fires a JSON event on every conversation created, message received or status changed. Useful for syncing tickets to a CRM, triggering an n8n workflow or logging conversations to your database.

Slack notifications: connect a Slack workspace via OAuth under Settings → Integrations → Slack. New conversations and mentions in Chatwoot generate a notification in the Slack channel of your choice. Agents never miss a message even when outside the interface.

REST API: all Chatwoot resources (conversations, contacts, messages, teams, labels) are exposed by a documented v1 REST API at /swagger. Authentication via token (user_access_token or agent API key). Common use cases: importing contacts from a CRM, reporting on resolved conversations, automatically updating contact attributes.

Zapier / Make (ex-Integromat): Chatwoot has native connectors on Zapier and Make to trigger no-code actions. Example: new Chatwoot conversation → create an opportunity in your CRM → notify the sales team by email.

Updating Chatwoot

Minor updates (patch releases like v4.17.0 → v4.17.1) are safe and often contain security fixes: plan them within 48 hours of publication.

For a patch update:

docker compose pull
docker compose down
docker compose up -d
docker compose exec rails bundle exec rails db:migrate

Then check the logs (docker compose logs web --tail=30) and test sending a message on each channel.

For a major upgrade (v3 → v4), the process is more delicate: v4 introduces blocking PostgreSQL schema migrations (restructured mentions and conversation_participants tables). Never run docker compose pull && docker compose up -d without a prior backup on a major version.

Best practice: always pin a specific version in docker-compose.yml (chatwoot/chatwoot:v4.17.1 rather than latest) so you control exactly what runs in production and avoid silent updates.

Migrating from Chatwoot v3 to v4

Chatwoot v4, released in June 2026, introduces the new 'Nova UI' interface and several blocking PostgreSQL schema migrations. An in-place upgrade from v3 will consistently break the instance if done without preparation — this is the subject of official issue #12088, which catalogues the most common failure cases.

The main reason for breakage: v4 renames the mentions table and restructures the conversation_participants table. A docker compose pull && docker compose up -d without a prior backup triggers the migrations automatically; if a migration fails mid-way (timeout, unsatisfied FK constraint), the database is left in an intermediate state and Chatwoot no longer starts.

In practice, three categories of instances are at risk: those running v3 with more than 50,000 conversations (bulk migrations are slow and may exceed Rails' 30-second timeout), those with undocumented custom columns in the contacts table, and those using Sidekiq Pro (removed from Community Edition in v4 — jobs queued at migration time are lost).

v3 → v4 migration procedure

  1. Back up the database and volumes

    Before any action, save the full state: docker compose exec postgres pg_dumpall -U postgres > /tmp/chatwoot-v3-dump-$(date +%F).sql. Also copy the Docker volumes linked to PostgreSQL and Rails Storage. This backup is your only safety net: if the migration fails, restoration is the only clean exit.

  2. Pin the image tag to v4

    In your docker-compose.yml, replace chatwoot/chatwoot:latest with chatwoot/chatwoot:v4.17.1 (or the latest v4 patch release). Avoid latest in production: this tag tracks HEAD and can introduce regressions without warning. Check the changelog for each version on the GitHub repository before targeting a tag.

  3. Run migrations manually

    Rather than letting Rails launch migrations when the web container starts, run them explicitly in the foreground to monitor progress: docker compose run --rm web bundle exec rails db:migrate. If an error occurs, the message is immediately visible — it identifies the failing migration and lets you fix it or skip it with db:migrate:up VERSION=... before re-running.

  4. Start and verify

    Once the migrations complete without error, start the stack: docker compose up -d. Log in to the Nova UI and verify that existing inboxes, contacts and conversations are present. Test sending and receiving a message on each connected channel. If Sidekiq shows failed jobs, use the Sidekiq Web interface (mounted at /sidekiq if enabled) to retry them.

Troubleshooting: common errors

Sidekiq workers blocked. If outgoing emails no longer send or webhooks stop firing, Sidekiq is likely stalled or its workers are exhausted. Check via the Sidekiq Web interface (/sidekiq) or logs: docker compose logs sidekiq --tail=50. The most common cause is a saturated mailers queue. Restart the worker: docker compose restart sidekiq. If the issue persists, verify the Redis connection (docker compose exec redis redis-cli ping should return PONG).

Redis connection refused. If Rails and Sidekiq fail to start with Redis::CannotConnectError, the Redis container is not ready. Check its state: docker compose ps redis. A container in Restarting state indicates a volume or permission issue. Remove the Redis volume and restart if the Redis data is transient (queued jobs will be lost).

ActionCable WebSocket not connecting. The livechat widget shows 'connection lost' or agents don't receive messages in real time. Likely cause: the reverse proxy is not forwarding WebSocket headers. With Nginx, add to your location block:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

With Caddy, the reverse_proxy localhost:3000 configuration handles WebSockets automatically.

Migration stuck mid-way. If rails db:migrate stops with an error, do not retry immediately. Identify the failing migration in the error message, fix it manually or skip it (rails db:migrate:up VERSION=<timestamp>), then re-run. As a last resort, restore the backup taken before the migration.

Chatwoot vs Crisp vs Intercom: which tool for which situation

Scroll the table

CriterionChatwoot (self-hosted)CrispIntercom
Pricing modelFree (VPS infra cost only)Free limited, then ~€25/monthFrom ~$74/agent/month
HostingOn your own VPSSaaS onlySaaS only
Customer dataOn your infrastructureCrisp serversIntercom servers
GDPR / sovereigntyTotal — no third partyDPA availableDPA available
Supported channelsLive chat, email, WhatsApp, Telegram, FB, Twitter/X, APILive chat, email, MessengerLive chat, email, SMS, WhatsApp (higher plan)
No agent capYesNo (plan limited)No (per-agent billing)
AutomationNative rules + APINative rulesAdvanced workflows
Deployment complexityMedium (Docker required)NoneNone

Official documentation

For advanced configuration (SMTP, LDAP SSO, S3 storage, multi-accounts) and Chatwoot-specific options, refer to the official Chatwoot self-hosted documentation. This guide covers deployment on VPS; the vendor documentation remains the reference for fine-tuning and major upgrades.

Deploy Chatwoot on your own server

Self-host Chatwoot on a ServOrbit VPS — open source, no per-agent fees, all your customer conversations on your infrastructure.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab