Skip to main content

Self-Hosting Chatwoot: Customer Support 2026

·OSSAlt Team
chatwootcustomer-supportself-hostingdockerguide
Share:

Chatwoot is the open source Intercom and Zendesk alternative. Self-hosting gives you unlimited agents, unlimited conversations, and omnichannel support — website live chat, email, WhatsApp, Facebook, Twitter, Telegram, and more.

Why Self-Host Chatwoot

Intercom's pricing has become a running joke in the startup community. Their Starter plan at $74/month covers only 1 seat with basic features. The Pro plan — required for automation and multiple inboxes — starts at $395/month and scales per seat. For a 10-person support team using Intercom Pro, expect to spend $4,000-8,000 annually. Zendesk Suite Professional runs $115/agent/month, making a 5-agent team $6,900/year.

Self-hosting Chatwoot on a €8/month Hetzner server costs approximately $96/year total — regardless of how many agents you add or how many conversations you handle. The math is stark: a 10-agent team saves upward of $4,000-7,000 annually compared to Intercom or Zendesk.

Omnichannel without per-channel fees. Intercom and Zendesk charge extra for WhatsApp, Twitter, and other channels. Chatwoot includes all channel types in the core product. Website live chat, email inboxes, WhatsApp Business via 360dialog, Facebook Messenger, Twitter DMs, Telegram, Line, and SMS via Twilio — all configurable from a single Chatwoot instance at no additional license cost.

Conversation data belongs to you. Customer support conversations often contain your most sensitive business data — complaints, billing disputes, user credentials in screenshots, private product roadmap discussions. Hosting on your infrastructure means that data never touches a third-party SaaS provider's servers. This is particularly important for companies with enterprise customers who have data processing agreements in their contracts.

Customization at the code level. Because Chatwoot is open source (MIT licensed), you can fork it and customize the agent interface, add custom integrations with internal tools, or modify the conversation routing logic. This level of customization is impossible with SaaS products regardless of plan tier.

When NOT to self-host Chatwoot: Chatwoot is a Ruby on Rails application with multiple services (Sidekiq for background jobs, PostgreSQL, Redis). It requires more maintenance than simpler tools. If your support team needs reliable on-call coverage and lacks engineering resources to handle incidents, the guaranteed uptime of Intercom or Zendesk may justify the cost. Also, some enterprise integrations (Salesforce, Zendesk ticket sync) are more polished in commercial products.

Prerequisites

Chatwoot requires 4 GB RAM minimum due to Ruby on Rails memory usage, plus PostgreSQL and Redis running alongside it. Server selection significantly impacts performance. Review VPS options for self-hosters with these constraints in mind.

Server specs: 4 GB RAM is the floor for Chatwoot in production. With 1-5 agents, 4 GB works. For 5-20 agents with active conversation volume, 8 GB RAM prevents Sidekiq from competing with the Rails app for memory. Ruby processes are notoriously memory-hungry — monitor memory usage after the first week of production use and scale up if needed.

Operating system: Ubuntu 22.04 LTS. Chatwoot's official Docker setup and community documentation assume Ubuntu. The official install script targets Ubuntu specifically.

Sidekiq for background jobs: Chatwoot runs a separate Sidekiq process that handles email sending, webhook delivery, automation triggers, and notification processing. Both the main app container and the Sidekiq container must be running for Chatwoot to function fully — a common source of confusion when email notifications stop working.

SMTP configuration: Email channel integration and notification delivery require working SMTP. Configure this before inviting agents — their account activation emails and conversation notifications depend on it.

Object storage for scale: By default, Chatwoot stores attachments locally. For a team receiving file attachments in conversations (screenshots, documents), local storage fills up quickly. Plan to migrate to S3-compatible object storage (Cloudflare R2 or AWS S3) before you hit storage limits.

Skills required: Comfortable with multi-service Docker Compose, Rails console commands for initial setup, and basic understanding of background job queues. The initial setup requires running a Rails console command to create the first admin account.

Requirements

  • VPS with 4 GB RAM minimum (8 GB recommended)
  • Docker and Docker Compose
  • Domain name (e.g., support.yourdomain.com)
  • 20+ GB disk
  • SMTP service for email

Step 1: Clone and Configure

# Download Chatwoot Docker setup
git clone https://github.com/chatwoot/chatwoot.git
cd chatwoot

# Copy environment file
cp .env.example .env

Step 2: Configure Environment

Edit .env:

# App
SECRET_KEY_BASE=your-random-secret-key-here
FRONTEND_URL=https://support.yourdomain.com
DEFAULT_LOCALE=en

# Database
POSTGRES_HOST=postgres
POSTGRES_USERNAME=chatwoot
POSTGRES_PASSWORD=your-strong-password
POSTGRES_DATABASE=chatwoot

# Redis
REDIS_URL=redis://redis:6379

# SMTP
MAILER_SENDER_EMAIL=support@yourdomain.com
SMTP_ADDRESS=smtp.resend.com
SMTP_PORT=587
SMTP_USERNAME=resend
SMTP_PASSWORD=re_your_api_key
SMTP_AUTHENTICATION=plain
SMTP_ENABLE_STARTTLS_AUTO=true

# Storage (local or S3)
ACTIVE_STORAGE_SERVICE=local

Generate secret key:

openssl rand -hex 64

Step 3: Docker Compose Setup

# docker-compose.yml
services:
  chatwoot:
    image: chatwoot/chatwoot:latest
    container_name: chatwoot
    restart: unless-stopped
    ports:
      - "3000:3000"
    env_file: .env
    environment:
      - RAILS_ENV=production
      - NODE_ENV=production
    volumes:
      - chatwoot_storage:/app/storage
    depends_on:
      - postgres
      - redis
    command: bundle exec rails s -p 3000 -b 0.0.0.0

  sidekiq:
    image: chatwoot/chatwoot:latest
    container_name: chatwoot-sidekiq
    restart: unless-stopped
    env_file: .env
    environment:
      - RAILS_ENV=production
    volumes:
      - chatwoot_storage:/app/storage
    depends_on:
      - postgres
      - redis
    command: bundle exec sidekiq -C config/sidekiq.yml

  postgres:
    image: postgres:16-alpine
    container_name: chatwoot-db
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=chatwoot
      - POSTGRES_USER=chatwoot
      - POSTGRES_PASSWORD=your-strong-password

  redis:
    image: redis:7-alpine
    container_name: chatwoot-redis
    restart: unless-stopped
    volumes:
      - redis_data:/data

volumes:
  chatwoot_storage:
  postgres_data:
  redis_data:

Step 4: Initialize and Start

# Start services
docker compose up -d

# Run database migrations
docker exec chatwoot bundle exec rails db:chatwoot_prepare

# Create admin account
docker exec -it chatwoot bundle exec rails console
# In console:
# SuperAdmin.create!(email: 'admin@yourdomain.com', password: 'your-password')
# exit

Step 5: Reverse Proxy (Caddy)

# /etc/caddy/Caddyfile
support.yourdomain.com {
    reverse_proxy localhost:3000
}
sudo systemctl restart caddy

Step 6: Set Up Channels

Website Live Chat:

  1. SettingsInboxesAdd InboxWebsite
  2. Set your website domain
  3. Customize widget appearance
  4. Copy the widget script:
<script>
  (function(d,t) {
    var BASE_URL="https://support.yourdomain.com";
    var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
    g.src=BASE_URL+"/packs/js/sdk.js";
    g.defer = true;
    g.async = true;
    s.parentNode.insertBefore(g,s);
    g.onload=function(){
      window.chatwootSDK.run({
        websiteToken: 'YOUR_WEBSITE_TOKEN',
        baseUrl: BASE_URL
      })
    }
  })(document,"script");
</script>

Email Channel:

  1. SettingsInboxesAdd InboxEmail
  2. Configure IMAP for receiving emails
  3. Configure SMTP for sending replies

WhatsApp (via 360dialog or Twilio):

  1. SettingsInboxesAdd InboxWhatsApp
  2. Enter API key from your WhatsApp Business provider

Additional channels: Facebook, Twitter, Telegram, Line, SMS (via Twilio)

Step 7: Configure Team

  1. SettingsAgents → invite team members
  2. SettingsTeams → create teams (Sales, Support, Billing)
  3. SettingsAutomation → set up auto-assignment rules

Useful automations:

TriggerAction
New conversationAuto-assign to available agent
Message contains "billing"Assign to Billing team
No response in 1 hourSend reminder to agent
Conversation resolvedSend satisfaction survey

Step 8: Canned Responses

Set up quick responses for common questions:

  1. SettingsCanned Responses
  2. Create shortcuts like /greeting, /pricing, /hours
  3. Agents type the shortcut to insert the full response

Production Hardening

S3 Storage (for file attachments at scale):

ACTIVE_STORAGE_SERVICE=amazon
S3_BUCKET_NAME=your-bucket
AWS_ACCESS_KEY_ID=your-key
AWS_SECRET_ACCESS_KEY=your-secret
AWS_REGION=us-east-1

Backups:

# Database backup (daily cron)
docker exec chatwoot-db pg_dump -U chatwoot chatwoot > /backups/chatwoot-$(date +%Y%m%d).sql

# File storage backup
docker cp chatwoot:/app/storage /backups/chatwoot-storage-$(date +%Y%m%d)

For offsite backups, pair local pg_dump with automated server backups using restic. Customer conversation history is critical business data — daily backups pushed to Backblaze B2 give you a reliable recovery path.

Updates:

docker compose pull
docker compose up -d
docker exec chatwoot bundle exec rails db:chatwoot_prepare

Monitoring:

  • Monitor port 3000 with Uptime Kuma
  • Monitor Sidekiq queue depth (Redis)
  • Set up disk space alerts

Resource Usage

AgentsRAMCPUDisk
1-54 GB2 cores20 GB
5-208 GB4 cores50 GB
20-5016 GB8 cores100 GB

VPS Recommendations

ProviderSpec (10 agents)Price
Hetzner4 vCPU, 8 GB RAM€8/month
DigitalOcean4 vCPU, 8 GB RAM$48/month
Linode4 vCPU, 8 GB RAM$48/month

Production Security Hardening

Customer support software handles some of the most sensitive data in your business — user complaints, billing information, private communications. The self-hosting security checklist covers foundational server security; here are Chatwoot-specific priorities.

UFW firewall: Block all direct service access; only expose Caddy's ports.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 3000/tcp   # Block direct Chatwoot app access
sudo ufw enable

Fail2ban for SSH protection:

sudo apt install fail2ban -y

/etc/fail2ban/jail.local:

[sshd]
enabled = true
maxretry = 5
bantime = 3600
findtime = 600

Protect the .env file: Your .env contains the SECRET_KEY_BASE and SMTP credentials. If this key changes, all existing sessions become invalid and users must log in again.

chmod 600 .env
echo ".env" >> .gitignore

Disable SSH password authentication: Edit /etc/ssh/sshd_config:

PasswordAuthentication no
PermitRootLogin no

Restart: sudo systemctl restart sshd

Automatic security updates:

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

Chatwoot-specific: Lock down access to the admin panel by IP address if your support team works from fixed office IPs. Use Caddy's remote_ip matcher to restrict access. Regularly rotate agent credentials and disable accounts immediately when agents leave the team.

Troubleshooting Common Issues

Live chat widget loads but conversations don't appear in the inbox

The most common cause is a mismatch between the FRONTEND_URL environment variable and the actual URL. Chatwoot uses this URL to validate WebSocket connections from the widget. Verify FRONTEND_URL=https://support.yourdomain.com exactly (no trailing slash) and restart the chatwoot container.

Emails not being delivered from email inboxes

Chatwoot's email sending runs through Sidekiq, not the main Rails process. If Sidekiq isn't running, emails queue up indefinitely. Check: docker ps to confirm chatwoot-sidekiq is running and docker logs chatwoot-sidekiq for errors. Sidekiq and the main app must share the same Redis instance and the same .env file.

WhatsApp integration shows "Webhook verification failed"

WhatsApp webhooks require HTTPS with a valid SSL certificate. Verify Caddy has issued a certificate: curl -I https://support.yourdomain.com should return a valid cert. Also, the webhook URL registered in your 360dialog or Twilio account must exactly match your Chatwoot installation's webhook URL. Check the Chatwoot docs for the exact path format.

"500 Internal Server Error" after updating

After pulling a new Chatwoot image, database migrations must run: docker exec chatwoot bundle exec rails db:chatwoot_prepare. If you skip this step after updates, new features that depend on schema changes fail with 500 errors. Always run migrations after docker compose up -d following an update.

File attachments not saving after switching to S3

After changing ACTIVE_STORAGE_SERVICE to amazon, existing local attachments are no longer accessible. There's no automatic migration. If switching mid-deployment, either migrate existing files manually to S3 (using the Rails console to re-attach blobs) or accept that old attachments will be inaccessible and only new ones go to S3. Plan storage backend choice before going live.

Ongoing Maintenance and Operations

A self-hosted customer support platform requires more operational attention than most tools because it's customer-facing — downtime directly impacts your customers' ability to reach you.

Uptime is critical. Unlike internal tools where brief downtime is inconvenient, a customer support chat being down means customers can't get help. Monitor with multi-location uptime checks (Uptime Kuma or Better Uptime) and configure alerts to go to multiple channels — your own Mattermost or Slack, email, and SMS. Set up automatic restart on failure: restart: unless-stopped in Docker Compose handles most cases, but a systemd watchdog for the entire Docker Compose stack provides an additional recovery layer.

Conversation assignment workflows. Effective Chatwoot usage depends on keeping conversations from falling through the cracks. Configure automation rules that auto-assign conversations to specific agents or teams based on inbox, keywords, or time of day. For round-robin assignment, install the Auto Assignment feature in your team settings. Review unassigned conversations in your daily standup — any open conversation without an assignee is a customer waiting for a response.

CSAT (Customer Satisfaction) surveys. Enable satisfaction surveys in SettingsAccount SettingsIntegrationsCSAT. Chatwoot sends a satisfaction survey via email after conversations are resolved. Track your weekly CSAT score and use low scores as a signal to review how specific conversations were handled. This data is only available in self-hosted Chatwoot — you own the full dataset.

Agent performance reporting. Chatwoot's reports section shows first response time, resolution time, and conversation volume per agent. Review these metrics weekly with your support team. Long first response times indicate staffing gaps; high re-open rates suggest resolutions are too quick without fully addressing the issue.

Webhook integrations. Chatwoot can post conversation events (new conversation, message created, resolved) to external webhooks. Use this to sync support data to your CRM, create internal tickets in Jira or Linear when SLA thresholds are breached, or build custom reporting dashboards. Configure webhooks in SettingsIntegrationsWebhooks.

Archiving old conversations. PostgreSQL performance can degrade as the conversation table grows to millions of rows without proper maintenance. Add a partial index on frequently-queried columns (inbox_id, status, assignee_id) to maintain query performance. Chatwoot's development team has acknowledged performance issues at high conversation volumes — monitor query times using docker exec chatwoot-db psql -U chatwoot -c "SELECT pid, query, state FROM pg_stat_activity WHERE state != 'idle';" if you notice dashboard slowness.

Team onboarding. Chatwoot's agent interface is intuitive but benefits from a brief orientation. Create a written guide covering: keyboard shortcuts (J/K to navigate conversations, R to reply), how canned responses work, and your team's escalation process. This reduces the time new agents spend figuring out the tool and gets them handling conversations faster.


Compare customer support platforms on OSSAlt — channels, features, and pricing side by side.

See open source alternatives to Chatwoot on OSSAlt.

The SaaS-to-Self-Hosted Migration Guide (Free PDF)

Step-by-step: infrastructure setup, data migration, backups, and security for 15+ common SaaS replacements. Used by 300+ developers.

Join 300+ self-hosters. Unsubscribe in one click.