Como instalar o Chatwoot em uma VPS

Atualizado em 21/09/2026 30 min Intermediário

O Chatwoot junta os canais de atendimento numa caixa de entrada só: o chat do site, o e-mail, o WhatsApp. A equipe responde tudo de um lugar, e o histórico da conversa fica no seu banco, não no de terceiros.

É uma aplicação Rails com processamento em segundo plano, então são quatro peças: web, Sidekiq (filas), PostgreSQL e Redis.

Antes de começar

  • VPS com Docker — veja o guia de Docker.
  • Subdomínio apontado para o IP, por exemplo chat.seudominio.com.br.
  • 4 GB de RAM. Rails com Sidekiq não cabe confortavelmente em 2 GB, e o processo de fila é o primeiro a morrer quando falta memória.
  • SMTP para notificações e convites de agente.

Prepare o ambiente

O SECRET_KEY_BASE assina as sessões: troque-o depois e todo mundo é deslogado.

terminal
mkdir -p /opt/chatwoot && cd /opt/chatwoot

cat > .env <<EOF
DOMINIO=chat.seudominio.com.br
[email protected]

SECRET_KEY_BASE=$(openssl rand -hex 64)
POSTGRES_PASSWORD=$(openssl rand -hex 24)

SMTP_ADDRESS=smtp.seudominio.com.br
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=troque-aqui
[email protected]
EOF

chmod 600 .env

Escreva o docker-compose.yml

Repare que web e sidekiq usam a mesma imagem com comandos diferentes: um atende requisição, o outro processa fila.

terminal
cat > /opt/chatwoot/docker-compose.yml <<'EOF'
x-base: &base
  image: chatwoot/chatwoot:v3.16.0
  restart: unless-stopped
  env_file: .env
  environment:
    RAILS_ENV: production
    NODE_ENV: production
    INSTALLATION_ENV: docker
    FRONTEND_URL: https://${DOMINIO}
    POSTGRES_HOST: postgres
    POSTGRES_USERNAME: chatwoot
    POSTGRES_DATABASE: chatwoot
    REDIS_URL: redis://redis:6379
    ACTIVE_STORAGE_SERVICE: local
    RAILS_LOG_TO_STDOUT: "true"
    TZ: America/Sao_Paulo
  volumes:
    - storage_data:/app/storage

services:
  postgres:
    image: pgvector/pgvector:pg16
    restart: unless-stopped
    environment:
      POSTGRES_DB: chatwoot
      POSTGRES_USER: chatwoot
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U chatwoot"]
      interval: 10s
      retries: 5

  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data

  web:
    <<: *base
    command: bundle exec rails s -b 0.0.0.0 -p 3000
    depends_on:
      postgres:
        condition: service_healthy

  sidekiq:
    <<: *base
    command: bundle exec sidekiq -C config/sidekiq.yml
    depends_on:
      postgres:
        condition: service_healthy

  caddy:
    image: caddy:2-alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      DOMINIO: ${DOMINIO}
      EMAIL: ${EMAIL}
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config

volumes:
  postgres_data:
  redis_data:
  storage_data:
  caddy_data:
  caddy_config:
EOF

cat > /opt/chatwoot/Caddyfile <<'EOF'
{$DOMINIO} {
	tls {$EMAIL}
	reverse_proxy web:3000
}
EOF

O banco é a imagem pgvector, não o PostgreSQL comum: versões recentes do Chatwoot usam essa extensão para busca. Com a imagem padrão, a migração falha.

Prepare o banco antes de subir

O Chatwoot precisa rodar as migrações uma vez antes do primeiro acesso.

terminal
cd /opt/chatwoot
docker compose up -d postgres redis
sleep 15
docker compose run --rm web bundle exec rails db:chatwoot_prepare

Suba tudo e crie a conta

terminal
docker compose up -d
docker compose ps
docker compose logs -f web

Abra https://chat.seudominio.com.br. A primeira visita mostra o cadastro do administrador e da conta.

Crie a conta assim que subir. Enquanto ninguém se cadastrar, quem abrir o endereço vira o dono da instalação.

Coloque o chat no seu site

Em Settings → Inboxes → Add Inbox → Website, informe o endereço do site. O Chatwoot gera um trecho de script para colar antes do </body> das suas páginas.

Para ligar o WhatsApp, o caminho usual é uma API intermediária — veja o guia da Evolution API.

Backup

terminal
cat > /opt/chatwoot/backup.sh <<'EOF'
#!/bin/bash
set -e
cd /opt/chatwoot
DESTINO=/opt/chatwoot/backups
mkdir -p $DESTINO
DATA=$(date +%Y%m%d-%H%M)
docker compose exec -T postgres pg_dump -U chatwoot chatwoot | gzip > "$DESTINO/chatwoot-$DATA.sql.gz"
docker run --rm -v chatwoot_storage_data:/dados -v "$DESTINO":/backup alpine tar czf "/backup/anexos-$DATA.tar.gz" -C /dados .
find "$DESTINO" -name '*.gz' -mtime +7 -delete
EOF
chmod +x /opt/chatwoot/backup.sh
(crontab -l 2>/dev/null; echo '0 3 * * * /opt/chatwoot/backup.sh') | crontab -

Se algo não funcionar

Erro de extensão vector durante a migração

A imagem do banco precisa ser a pgvector/pgvector:pg16. Se você subiu com o postgres comum, troque no compose, apague o volume do banco e refaça a preparação.

A interface abre mas nada acontece ao enviar mensagem

É o Sidekiq. Confirme que o contêiner está de pé — sem ele nada sai da fila:

terminal
docker compose ps sidekiq
docker compose logs --tail 40 sidekiq

O contêiner reinicia sozinho, sem erro claro

Falta de memória. Rails e Sidekiq juntos passam de 1,5 GB com facilidade:

terminal
free -h
docker stats --no-stream
VPS de 4 GB ou mais para o Chatwoot

Memória reservada, sem disputa com vizinho de nó. Ativação automática depois do pagamento.

Ver planos de VPS

Perguntas frequentes

O Chatwoot roda em 2 GB?

Na prática, não com folga. São dois processos Rails, PostgreSQL e Redis. Ele sobe, mas o Sidekiq é o primeiro a ser morto quando falta memória — e aí as mensagens param de sair sem erro aparente. 4 GB é o mínimo sensato.

Dá para conectar o WhatsApp?

O Chatwoot suporta a API Cloud oficial da Meta de forma nativa. Para a rota não oficial, o caminho é uma API intermediária, como a Evolution, com um conector no meio.

Como atualizo sem perder as conversas?

Rode o backup, troque a tag da imagem no compose, aplique as migrações com docker compose run --rm web bundle exec rails db:migrate e suba. Os dados vivem nos volumes. Leia as notas da versão antes de pular versões maiores.

Continue por aqui