How to Deploy Chatwoot - Open-Source Customer Support Platform

Updated on 04 August, 2026
Deploy Chatwoot, an open-source customer support platform, using Docker Compose with PostgreSQL, Redis, and Traefik, then configure a live chat inbox.
How to Deploy Chatwoot - Open-Source Customer Support Platform header image

Chatwoot is an open-source customer engagement platform that unifies conversations from live chat, email, social media, and messaging apps into a shared inbox. It provides real-time visitor tracking, canned responses, team collaboration features, and integrations with popular CRM and helpdesk tools.

This article explains how to deploy Chatwoot on a Linux server using Docker Compose with PostgreSQL as the database, Redis for caching and background jobs, and Traefik for reverse proxy. It covers directory setup, environment configuration, database preparation, accessing the dashboard, and demonstrating live chat functionality.

Prerequisites

Before you begin, you need to:

Set Up the Directory Structure, Configuration, and Environment Variables

Chatwoot requires a project directory with persistent storage for the database, Redis data, and uploaded files. Environment variables control the application configuration, including database connections, secret keys, and SMTP settings.

  1. Create the project directory with all the required subdirectories.

    console
    $ mkdir -p ~/chatwoot/{postgres,redis,storage,letsencrypt}
    

    This command creates the following directories:

    • postgres: Persists PostgreSQL database files.
    • redis: Stores Redis data for caching and background job queues.
    • storage: Stores file attachments and uploads.
    • letsencrypt: Stores Traefik ACME certificates for HTTPS renewal.
  2. Navigate to the project directory.

    console
    $ cd ~/chatwoot
    
  3. Generate a secret key for the application.

    console
    $ openssl rand -hex 32
    

    Save the output for use in the environment file.

  4. Create the environment file.

    console
    $ nano .env
    
  5. Add the following configuration. Replace chatwoot.example.com with your domain name, admin@example.com with your email address, STRONG_POSTGRES_PASSWORD with a secure database password, and GENERATED_SECRET_KEY with the generated secret key from the previous step.

    ini
    DOMAIN=chatwoot.example.com
    LETSENCRYPT_EMAIL=admin@example.com
    FRONTEND_URL=https://chatwoot.example.com
    
    SECRET_KEY_BASE=GENERATED_SECRET_KEY
    
    POSTGRES_HOST=postgres
    POSTGRES_PORT=5432
    POSTGRES_DATABASE=chatwoot
    POSTGRES_USERNAME=chatwoot
    POSTGRES_PASSWORD=STRONG_POSTGRES_PASSWORD
    
    REDIS_URL=redis://redis:6379
    
    RAILS_ENV=production
    NODE_ENV=production
    RAILS_LOG_TO_STDOUT=true
    
    ACTIVE_STORAGE_SERVICE=local
    
    # Optional: SMTP configuration for email
    # SMTP_ADDRESS=smtp.example.com
    # SMTP_PORT=587
    # SMTP_USERNAME=SMTP_USERNAME
    # SMTP_PASSWORD=SMTP_PASSWORD
    # SMTP_DOMAIN=chatwoot.example.com
    # SMTP_ENABLE_STARTTLS_AUTO=true
    # MAILER_SENDER_EMAIL=noreply@chatwoot.example.com
    

    If SMTP functionality for Chatwoot is required, then uncomment the Optional section in the configuration file above and replace smtp.example.com with your SMTP server address, SMTP_USERNAME with your desired username, SMTP_PASSWORD with a strong password, chatwoot.example.com with your domain name and noreply@chatwoot.example.com with your desired sender email address.

    Save and close the file.

Deploy with Docker Compose

Docker Compose orchestrates Chatwoot with PostgreSQL as the database, Redis for caching and background jobs, Sidekiq for worker processes, and Traefik as the reverse proxy. This configuration is based on the official Chatwoot Docker deployment guide.

  1. Create the Docker Compose file.

    console
    $ nano docker-compose.yml
    
  2. Add the following configuration.

    yaml
    services:
      traefik:
        image: traefik:v3.7.0
        container_name: traefik
        restart: unless-stopped
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
          - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - "./letsencrypt:/letsencrypt"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
    
      postgres:
        image: pgvector/pgvector:pg16
        container_name: chatwoot-postgres
        restart: unless-stopped
        environment:
          POSTGRES_DB: ${POSTGRES_DATABASE}
          POSTGRES_USER: ${POSTGRES_USERNAME}
          POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
        volumes:
          - "./postgres:/var/lib/postgresql/data"
        healthcheck:
          test: ["CMD", "pg_isready", "-d", "${POSTGRES_DATABASE}", "-U", "${POSTGRES_USERNAME}"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      redis:
        image: redis:alpine
        container_name: chatwoot-redis
        restart: unless-stopped
        command: ["redis-server", "--appendonly", "yes"]
        volumes:
          - "./redis:/data"
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
          interval: 10s
          timeout: 5s
          retries: 3
    
      rails:
        image: chatwoot/chatwoot:v4.14.1
        container_name: chatwoot-rails
        restart: unless-stopped
        command: bundle exec rails s -p 3000 -b 0.0.0.0
        env_file:
          - .env
        depends_on:
          postgres:
            condition: service_healthy
          redis:
            condition: service_healthy
        volumes:
          - "./storage:/app/storage"
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.chatwoot.rule=Host(`${DOMAIN}`)"
          - "traefik.http.routers.chatwoot.entrypoints=websecure"
          - "traefik.http.routers.chatwoot.tls.certresolver=letsencrypt"
          - "traefik.http.services.chatwoot.loadbalancer.server.port=3000"
    
      sidekiq:
        image: chatwoot/chatwoot:v4.14.1
        container_name: chatwoot-sidekiq
        restart: unless-stopped
        command: bundle exec sidekiq -C config/sidekiq.yml
        env_file:
          - .env
        depends_on:
          postgres:
            condition: service_healthy
          redis:
            condition: service_healthy
        volumes:
          - "./storage:/app/storage"
    

    Save and close the file.

    In the above manifest:

    • traefik: Serves as the reverse proxy and TLS termination point. It listens on ports 80 and 443, automatically redirects HTTP to HTTPS, and provisions Let's Encrypt certificates.
    • postgres: Runs PostgreSQL 16 as the primary database for storing conversations, users, and configuration.
    • redis: Runs Redis 7 for caching, session storage, and Sidekiq background job queues.
    • rails: Runs the Chatwoot web application server on port 3000, handling HTTP requests and WebSocket connections for real-time updates.
    • sidekiq: Runs background workers for processing emails, webhooks, and scheduled tasks.
  3. Prepare the database by running migrations.

    console
    $ docker compose run --rm rails bundle exec rails db:chatwoot_prepare
    

    This creates the database schema and runs all necessary migrations.

  4. Start all services in detached mode.

    console
    $ docker compose up -d
    
  5. Verify that all containers are running.

    console
    $ docker compose ps -a
    

    Verify that all containers show a STATUS of Up.

  6. View the logs for the services.

    console
    $ docker compose logs
    

    Confirm that the rails, sidekiq, and traefik services start without repeated ERROR or connection-refused entries.

    Note
    For more information on managing a Docker Compose stack, see the How To Use Docker Compose article.

Access and Configure Chatwoot

After deployment, access the Chatwoot dashboard to create the administrator account and configure the workspace.

  1. Visit your chatwoot domain name (such as https://chatwoot.example.com) in a web browser.

    Chatwoot registration screen with fields for Name, Company Name, Work Email, and Password

    If the server returns a 502 Bad Gateway error, wait a few seconds and then refresh to access the setup page.

  2. On the welcome screen, enter your Name, Company Name, Work Email, and Password.

  3. Optionally, check or uncheck the newsletter subscription checkbox to get occasional updates from Chatwoot.

  4. Click Finish Setup to create your account and access the dashboard.

Application Use Case

Chatwoot supports multiple communication channels, including website live chat, email, and social media integrations. This section demonstrates how to create a live chat inbox and test visitor conversations.

Create a Website Live Chat Inbox

An inbox connects a communication channel, such as a website widget, to your Chatwoot workspace.

  1. On the welcome dashboard, select Click here to create an inbox under the All your conversations in one place section.

  2. Select Website from the channel options to create a live-chat widget.

  3. Enter a Website Name (for example, My Website) and your Website Domain.

  4. Configure the widget appearance by selecting a Widget Color, entering a Welcome Heading, and adding a Welcome Tagline.

  5. Optionally, select Enable channel greeting to auto-send messages when customers start a conversation.

  6. Click Create inbox.

  7. On the Add Agents screen, select agents from the dropdown or click Add agents to proceed without adding any.

  8. On the confirmation screen that appears after creating the inbox, click Copy to copy the JavaScript snippet for embedding the chat widget on your website.

  9. Click Take me there to open the inbox settings, or More settings to configure additional options.

Test the Live Chat Widget

Embedding the widget in a live preview confirms that visitor messages reach the Chatwoot dashboard in real time.

  1. In the left sidebar, click Settings and then click Inboxes.

  2. Click the settings icon next to the inbox you created.

  3. Click Script at the top of the page to view the embed code.

  4. Click Open in CodePen to open an interactive preview of the chat widget in a new browser tab.

  5. Click the chat bubble in the corner of the CodePen page, enter a test message (for example, Hello, I need help), and send it.

  6. Return to the Chatwoot dashboard and click Conversations in the left sidebar. The test message appears in the conversation list.

  7. Click the new conversation in the Conversations list.

  8. Type a response in the message input field at the bottom.

  9. Click the Send button to send the reply. The conversation history is saved and accessible to any team member assigned to the inbox.

Conclusion

You have deployed Chatwoot on a Linux server using Docker Compose with PostgreSQL for data storage, Redis for caching and background jobs, and Traefik as a reverse proxy. Your self-hosted instance provides a unified customer engagement platform with live chat, team collaboration, and conversation management while keeping full control of your data. For advanced configuration, including email channels, social media integrations, and API access, refer to the official Chatwoot documentation.

Comments