Como atualizar o Chatwoot V4

Nesta aula vamos instalar o Chatwoot v4.13.0 do zero na sua VPS, usando Portainer, Docker Swarm e Traefik, com banco de dados isolado no PostgreSQL, cache dedicado no Redis e envio de e-mails via SMTP. Diferente de tutoriais genéricos, aqui cada passo existe para evitar que o Sidekiq fique preso em fila ou que o primeiro acesso trave por falta de usuário administrador. Siga estritamente na ordem.

Pré-requisitos

Antes de começar, seu ambiente já precisa ter rodando:

  • Portainer (gerenciador do Docker Swarm).
  • Traefik (proxy reverso, com rede traefik_public e resolver de SSL le configurado).
  • PostgreSQL (acessível na rede digital_network pelo hostname postgres).
  • Redis (acessível na rede digital_network pelo hostname redis).
  • Servidor SMTP configurado (ex: Poste.io) com usuário e senha de envio.
  • DNS configurado: aponte o subdomínio do Chatwoot (ex: chatwoot.seudominio.com.br) para o IP do seu servidor.

Link das aulas pré-requisitas abaixo:

Passo a Passo

Passo 1: Autenticar no Docker Hub (evita erro toomanyrequests)

Faça login no Docker Hub direto no terminal do servidor:

docker login

Passo 2: Baixar a imagem manualmente antes do deploy

Baixe a imagem da versão 4.13.0:

docker pull chatwoot/chatwoot:v4.13.0

Passo 3: Criar o banco de dados no PostgreSQL

O Chatwoot precisa de um banco dedicado. Acesse o container do seu Postgres:

PG=$(docker ps -qf name=postgres)
docker exec -i $PG psql -U postgres -c "CREATE DATABASE chatwoot;"
Se o seu Postgres global tiver outro hostname na rede (ex: pgvector), ajuste POSTGRES_HOST na stack antes do deploy.

Passo 4: Preparar as variáveis de ambiente

Gere uma chave forte para o SECRET_KEY_BASE:

openssl rand -hex 64

Monte o bloco de Environment Variables com domínio, chave secreta, senha do Postgres e credenciais SMTP:

# ==========================================
# DOMÍNIO
# ==========================================
DOMINIO_BASE=seudominio.com.br

# ==========================================
# SEGURANÇA
# ==========================================
SECRET_KEY_BASE=gere_com_openssl_rand_hex_64

# ==========================================
# BANCO DE DADOS (POSTGRESQL)
# ==========================================
POSTGRES_PASSWORD=sua_senha_do_banco_aqui

# ==========================================
# SMTP (SERVIDOR DE E-MAIL)
# ==========================================
SMTP_ADDRESS=email.seudominio.com.br
SMTP_USERNAME=contato@seudominio.com.br
SMTP_PASSWORD=sua_senha_smtp_aqui

Passo 5: Ajustar e colar a stack no Portainer

Vá em Stacks → Add stack, dê o nome de chatwoot e cole o código docker-compose.yml da stack (ela já sobe os serviços chatwoot_app e chatwoot_sidekiq juntos). Abaixo do editor, ative Environment variables, clique em Advanced mode e cole o bloco do Passo 4. Clique em Deploy the stack.

⬇️ Ver e copiar a stack completa

Passo 6: Acompanhar o boot e as migrations

O entrypoint padrão do Chatwoot (docker/entrypoints/rails.sh) roda as migrations do banco automaticamente antes de subir o Rails. Acompanhe os logs do serviço principal:

docker service logs chatwoot_chatwoot_app --tail 50 -f
Se a migration travar ou falhar: troque temporariamente o entrypoint do serviço chatwoot_app para ["sh", "-c", "sleep infinity"], faça o redeploy da stack, entre no container e rode a migration manualmente com bundle exec rails db:chatwoot_prepare. Depois de concluído, volte o entrypoint original e faça o redeploy de novo.

Passo 7: Criar o primeiro usuário administrador

Como a stack sobe com ENABLE_ACCOUNT_SIGNUP=false, não existe tela pública de cadastro — o primeiro admin precisa ser criado via console do Rails:

docker exec -it $(docker ps -qf name=chatwoot_chatwoot_app) bundle exec rails c

Dentro do console, crie a conta e o usuário administrador (ajuste nome, e-mail e senha):

account = Account.create!(name: "Minha Empresa")
User.create!(name: "Admin", email: "admin@seudominio.com.br", password: "SenhaForte123", account: account, role: :administrator)

Passo 8: Primeiro acesso

Quando os dois serviços estiverem com status Running (em verde) no Portainer:

  • Acesse o domínio configurado: https://chatwoot.seudominio.com.br.
  • Faça login com o e-mail e senha criados no Passo 7.

Resolução de Problemas Comuns no Chatwoot

SintomaCausaSolução
Erro 500 logo no primeiro bootSECRET_KEY_BASE ausente ou inválidoConfirme se a variável foi gerada e colada corretamente no Advanced mode do Portainer
Sidekiq não processa filas (mensagens/e-mails presos)Serviço chatwoot_sidekiq não subiu ou perdeu conexão com RedisVerifique os logs do serviço chatwoot_sidekiq e se REDIS_URL aponta para o banco correto
Migrations não rodam / app não iniciaConflito no entrypoint ou banco chatwoot ainda não existeConfirme se o banco foi criado no Passo 3 e use o truque do sleep infinity para rodar a migration manualmente
E-mails não chegamCredenciais SMTP incorretas ou porta 587 bloqueadaRevise SMTP_ADDRESS, SMTP_USERNAME e SMTP_PASSWORD nas variáveis de ambiente
Tela de login não abre / 502 Bad GatewayTraefik não encontra a rota ou o domínio não aponta para o servidorConfirme o DNS do subdomínio e se o serviço está na rede traefik_public

Stack Completa – Chatwoot v4.13.0

Copie o código abaixo e cole direto no editor da sua stack no Portainer.

version: "3.8"

services:
  chatwoot_app:
    image: chatwoot/chatwoot:v4.13.0
    entrypoint: docker/entrypoints/rails.sh
    command: bundle exec rails s -p 3000 -b 0.0.0.0

    volumes:
      - chatwoot_data:/app/storage
    networks:
      - traefik_public
      - digital_network

    environment:
      - CHATWOOT_HUB_URL=https://chatwoot.${DOMINIO_BASE}
      - FRONTEND_URL=https://chatwoot.${DOMINIO_BASE}

      - INSTALLATION_NAME=Chatwoot
      - NODE_ENV=production
      - RAILS_ENV=production
      - INSTALLATION_ENV=docker

      - SECRET_KEY_BASE=${SECRET_KEY_BASE}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - SMTP_PASSWORD=${SMTP_PASSWORD}

      - DEFAULT_LOCALE=pt_BR
      - FORCE_SSL=true
      - ENABLE_ACCOUNT_SIGNUP=false

      - REDIS_URL=redis://redis:6379/2

      - POSTGRES_HOST=postgres
      - POSTGRES_USERNAME=postgres
      - POSTGRES_DATABASE=chatwoot

      - ACTIVE_STORAGE_SERVICE=local
      - RAILS_LOG_TO_STDOUT=true
      - USE_INBOX_AVATAR_FOR_BOT=true

      - SIDEKIQ_CONCURRENCY=10
      - RACK_TIMEOUT_SERVICE_TIMEOUT=25
      - RAILS_MAX_THREADS=5
      - WEB_CONCURRENCY=2
      - ENABLE_RACK_ATTACK=false
      - WEBHOOKS_TRIGGER_TIMEOUT=10

      - MAILER_SENDER_EMAIL=Atendimento <${SMTP_USERNAME}>
      - SMTP_DOMAIN=${DOMINIO_BASE}
      - SMTP_ADDRESS=${SMTP_ADDRESS}
      - SMTP_PORT=587
      - SMTP_USERNAME=${SMTP_USERNAME}
      - SMTP_AUTHENTICATION=login
      - SMTP_ENABLE_STARTTLS_AUTO=true
      - SMTP_OPENSSL_VERIFY_MODE=none
      - MAILER_INBOUND_EMAIL_DOMAIN=${DOMINIO_BASE}

    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      resources:
        limits:
          cpus: "2"
          memory: 4096M

      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik_public
        - traefik.http.routers.chatwoot_app.rule=Host(`chatwoot.${DOMINIO_BASE}`)
        - traefik.http.routers.chatwoot_app.entrypoints=websecure
        - traefik.http.routers.chatwoot_app.tls=true
        - traefik.http.routers.chatwoot_app.tls.certresolver=le
        - traefik.http.routers.chatwoot_app.priority=1
        - traefik.http.services.chatwoot_app.loadbalancer.server.port=3000
        - traefik.http.services.chatwoot_app.loadbalancer.passhostheader=true
        - traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https
        - traefik.http.routers.chatwoot_app.middlewares=sslheader@docker

  chatwoot_sidekiq:
    image: chatwoot/chatwoot:v4.13.0
    entrypoint: docker/entrypoints/rails.sh
    command: bundle exec sidekiq -C config/sidekiq.yml

    volumes:
      - chatwoot_data:/app/storage
    networks:
      - traefik_public
      - digital_network

    environment:
      - CHATWOOT_HUB_URL=https://chatwoot.${DOMINIO_BASE}
      - FRONTEND_URL=https://chatwoot.${DOMINIO_BASE}

      - INSTALLATION_NAME=Chatwoot
      - NODE_ENV=production
      - RAILS_ENV=production
      - INSTALLATION_ENV=docker

      - SECRET_KEY_BASE=${SECRET_KEY_BASE}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
      - SMTP_PASSWORD=${SMTP_PASSWORD}

      - DEFAULT_LOCALE=pt_BR
      - FORCE_SSL=true
      - ENABLE_ACCOUNT_SIGNUP=false

      - REDIS_URL=redis://redis:6379/2

      - POSTGRES_HOST=postgres
      - POSTGRES_USERNAME=postgres
      - POSTGRES_DATABASE=chatwoot

      - ACTIVE_STORAGE_SERVICE=local
      - RAILS_LOG_TO_STDOUT=true
      - USE_INBOX_AVATAR_FOR_BOT=true

      - SIDEKIQ_CONCURRENCY=10
      - RACK_TIMEOUT_SERVICE_TIMEOUT=25
      - RAILS_MAX_THREADS=5
      - WEB_CONCURRENCY=2
      - ENABLE_RACK_ATTACK=false
      - WEBHOOKS_TRIGGER_TIMEOUT=10

      - MAILER_SENDER_EMAIL=Atendimento <${SMTP_USERNAME}>
      - SMTP_DOMAIN=${DOMINIO_BASE}
      - SMTP_ADDRESS=${SMTP_ADDRESS}
      - SMTP_PORT=587
      - SMTP_USERNAME=${SMTP_USERNAME}
      - SMTP_AUTHENTICATION=login
      - SMTP_ENABLE_STARTTLS_AUTO=true
      - SMTP_OPENSSL_VERIFY_MODE=none
      - MAILER_INBOUND_EMAIL_DOMAIN=${DOMINIO_BASE}

    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints:
          - node.role == manager
      resources:
        limits:
          cpus: "2"
          memory: 4096M

volumes:
  chatwoot_data:
    name: chatwoot_data
  chatwoot_public:
    name: chatwoot_public

networks:
  traefik_public:
    external: true
  digital_network:
    external: true

Menu Interativo

~/digitalinterativo/trilhas.sh — aulas
/
#!/usr/bin/trilha --interativa --self-hosted
🔓 aberto🔐 exclusivo aluno⏳ em breve
COMPARTILHAR