# Instale o Chatme no seu servidor

> Escolha o método que combina com a sua infraestrutura. O FZAP precisa estar rodando antes: é o conector obrigatório de WhatsApp do Chatme.

https://flouds.com.br/produtos/chatme/instalacao

## Manual: Instalação manual pelo Portainer

Use este caminho se Docker Swarm, Portainer, Traefik e uma instância do FZAP já estão preparados. Você revisa a stack e cada variável antes do deploy.

**Antes de começar** (15–25 min)

- Docker Swarm ativo com Portainer acessível
- Traefik e domínio configurados
- Uma instância do FZAP já instalada, com ADMIN_TOKEN em mãos
- PostgreSQL com pgvector (a stack já inclui um serviço pronto)

1. **Crie os volumes**  
   Crie os volumes externos usados pelo banco e pelos arquivos de mídia do Chatme.

   ```bash
   docker volume create chatme_pgdata
   docker volume create chatme_media
   ```

2. **Cole a stack no Portainer**  
   No Portainer, abra **Stacks → Add stack**, dê o nome `chatme` e cole a stack oficial abaixo. Use esse nome: a configuração de domínios próprios conta com ele.

   ```yaml
   version: "3.7"

   services:
     postgres:
       image: pgvector/pgvector:pg16

       networks:
         - ChatmeNet

       environment:
         - TZ=America/Sao_Paulo
         - POSTGRES_DB=chatme
         - POSTGRES_USER=chatme
         - POSTGRES_PASSWORD=troque_esta_senha

       volumes:
         - chatme_pgdata:/var/lib/postgresql/data

       deploy:
         mode: replicated
         replicas: 1
         placement:
           constraints:
             - node.role == manager
         resources:
           limits:
             cpus: "1"
             memory: 1024M
         labels:
           - io.portainer.accesscontrol.users=admin

     chatme:
       image: dncarbonell/chatme:latest

       networks:
         - ChatmeNet
         - proxy

       volumes:
         - chatme_media:/var/lib/chatme/storage

       environment:
         # --- Configurações Gerais ---
         - TZ=America/Sao_Paulo
         - PORT=8081
         - PUBLIC_BASE_URL=https://app.exemplo.com.br            # URL pública final da instância - sempre com "https://". O host desta URL é o domínio da licença
         #- LOG_LEVEL=info                                        # debug, info, warn, error (padrão: info)

         # --- Banco de Dados (PostgreSQL/pgvector) ---
         - DATABASE_URL=postgres://chatme:troque_esta_senha@postgres:5432/chatme?sslmode=disable

         # --- Segurança ---
         - SECURE_COOKIES=true                                    # true em produção (atrás de TLS); false só para testar login por cookie em http
         - TRUST_PROXY_HEADERS=true                               # o Traefik termina o HTTPS e sobrescreve X-Forwarded-For; o serviço não tem porta publicada
         #- SAFE_FETCH_ALLOW_PRIVATE_NETWORK=false                # webhooks de bots bloqueiam rede privada por padrão (proteção SSRF); ative só p/ endpoints internos confiáveis

         # --- Chave mestra da instalação (OBRIGATÓRIA) ---
         # Raiz da qual o app deriva, por HKDF, uma chave para cada finalidade (credenciais
         # de IA, segredos de bots, etc). Vem só do ambiente, precisa ser a MESMA em todas
         # as réplicas e nunca deve trocar depois do primeiro boot. Gere com: openssl rand -hex 32
         - CHATME_MASTER_KEY=troque_esta_chave_mestra

         # --- Licença (entregue pela Flouds) ---
         # Deixe vazio para rodar em modo "unlicensed" (funcional, com aviso, 1 tenant/1 pessoa)
         - CHATME_LICENSE_KEY=

         # --- Domínios próprios das contas (opcional, Chatme 0.7.0+) ---
         # Cada conta pode atender no domínio do cliente (ex.: atendimento.cliente.com.br),
         # cadastrado no console sem editar esta stack. Exige preparar o Traefik uma vez:
         # deploy/dominios-proprios/README.md. Descomente os 3 juntos; parcial impede o boot.
         # A licença continua no domínio de PUBLIC_BASE_URL.
         #- CUSTOM_DOMAINS_IPS=203.0.113.10                       # IP(s) público(s) da VPS, separados por vírgula
         #- CUSTOM_DOMAINS_PROXY_TOKEN=troque_este_segredo        # openssl rand -hex 32 (o mesmo vai na stack do Traefik)
         #- CUSTOM_DOMAINS_UPSTREAM_URL=http://chatme_chatme:8081 # <stack>_<serviço>; stack com outro nome muda aqui
         # A porta interna 8082 (consultada pelo Traefik) NÃO deve ser publicada.
         # Padrões, se o seu Traefik usa outros nomes:
         #- CUSTOM_DOMAINS_HTTP_ENTRYPOINT=web
         #- CUSTOM_DOMAINS_ENTRYPOINT=websecure
         #- CUSTOM_DOMAINS_CERT_RESOLVER=letsencryptresolver

         # --- Branding-base da instalação (fallback do primeiro boot) ---
         # Pode deixar em branco e configurar depois pelo próprio Chatme
         #- PRODUCT_NAME=
         #- LOGO_URL=
         #- COLOR_PRIMARY=
         #- SUPPORT_EMAIL=

         # --- fzap global (conector WhatsApp - infra interna, o cliente final não vê) ---
         - FZAP_BASE_URL=https://fzap.exemplo.com.br
         - FZAP_ADMIN_TOKEN=troque_este_token

         # --- Armazenamento de mídia (anexos das mensagens) ---
         # Config GLOBAL por instalação (não por tenant). Os bytes de mídia não ficam no
         # banco: vão para um volume (fs) ou um bucket S3-compatível (s3).
         - STORAGE_BACKEND=fs                                     # fs (volume, default) | s3 (MinIO, R2, Spaces, AWS S3)

         # -- Backend fs (volume) --
         - STORAGE_ROOT=/var/lib/chatme/storage
         # Segredo HMAC que assina as URLs temporárias de mídia de SAÍDA (a fzap baixa por
         # essa URL). Obrigatório no backend fs. Gere com: openssl rand -hex 32
         - STORAGE_SIGN_SECRET=troque_este_segredo

         # -- Backend s3 (S3-compatível) --
         #- STORAGE_ENDPOINT=                                     # host:porta; vazio = AWS S3
         #- STORAGE_REGION=us-east-1
         #- STORAGE_BUCKET=chatme-media
         #- STORAGE_ACCESS_KEY_ID=
         #- STORAGE_SECRET_ACCESS_KEY=
         #- STORAGE_FORCE_PATH_STYLE=true                         # true para MinIO e afins
         #- STORAGE_USE_SSL=true

         # -- Comuns de storage --
         #- STORAGE_SIGNED_URL_TTL=15m                             # validade das URLs assinadas de saída
         #- STORAGE_MAX_UPLOAD_BYTES=26214400                      # teto de upload de mídia de saída (bytes) - default 25 MiB

         # --- Transcrição de áudio (opcional, feita pelo próprio Chatme) ---
         # Disponibiliza o provedor para a instalação; cada tenant ainda ativa em Configurações > Recursos
         #- TRANSCRIPTION_ENABLED=false
         #- TRANSCRIPTION_PROVIDER=openai                          # openai | groq
         #- TRANSCRIPTION_API_KEY=
         #- TRANSCRIPTION_MODEL=                                   # default: whisper-1 (openai) | whisper-large-v3 (groq)
         #- TRANSCRIPTION_BASE_URL=                                # endpoint opcional; default oficial de cada provider
         #- TRANSCRIPTION_LANGUAGE=pt                               # ISO-639-1; vazio = detecção automática
         #- TRANSCRIPTION_HTTP_TIMEOUT=90s

       deploy:
         mode: replicated
         replicas: 1
         placement:
           constraints:
             - node.role == manager
         resources:
           limits:
             cpus: "1"
             memory: 512M
         labels:
           - io.portainer.accesscontrol.users=admin
           # Configuração Traefik
           - traefik.enable=true
           - traefik.swarm.network=proxy
           - traefik.http.routers.chatme.rule=Host(`app.exemplo.com.br`)
           - traefik.http.routers.chatme.entrypoints=websecure
           - traefik.http.routers.chatme.tls=true
           - traefik.http.routers.chatme.tls.certresolver=letsencryptresolver
           - traefik.http.routers.chatme.service=chatme
           - traefik.http.services.chatme.loadbalancer.server.port=8081
           - traefik.http.services.chatme.loadbalancer.passHostHeader=true

   volumes:
     chatme_pgdata:
       name: chatme_pgdata
       external: true
     chatme_media:
       name: chatme_media
       external: true

   networks:
     ChatmeNet:
       name: ChatmeNet
     proxy:
       name: proxy
       external: true
   ```

   [Abrir stack oficial no GitHub](https://github.com/flouds-dncarbonell/projeto-chatme/blob/main/stack.yml)

3. **Gere as chaves e revise as variáveis**  
   Gere `CHATME_MASTER_KEY` e `STORAGE_SIGN_SECRET` com o comando abaixo. Depois revise `PUBLIC_BASE_URL`, a senha do banco, `FZAP_BASE_URL` e `FZAP_ADMIN_TOKEN`.

   ```bash
   openssl rand -hex 32   # CHATME_MASTER_KEY
   openssl rand -hex 32   # STORAGE_SIGN_SECRET
   ```

   > **Atenção:** Guarde as duas chaves num lugar seguro antes do deploy. Elas não podem mudar depois do primeiro boot.

4. **Faça o deploy**  
   Clique em **Deploy the stack** e acompanhe o serviço `chatme` até ficar ativo.

5. **Crie o administrador**  
   Abra o domínio configurado. Na primeira visita, o Chatme mostra a tela de configuração inicial, onde você cria o admin e o primeiro tenant.

## Coolify: Instale como um recurso do Coolify

O Coolify cuida do proxy, HTTPS, rede, volumes e credenciais. Você só precisa criar o recurso, colar o Compose oficial e configurar o domínio.

**Antes de começar** (10–15 min)

- Coolify funcionando
- Domínio apontado para o servidor
- Uma instância do FZAP já instalada, com ADMIN_TOKEN em mãos

1. **Crie o recurso**  
   No projeto desejado, clique em **New Resource** e escolha **Docker Compose Empty**.

2. **Cole o Compose oficial**  
   Copie todo o `docker-compose.yml` abaixo e cole no editor do recurso.

   ```yaml
   # documentation: https://github.com/flouds-dncarbonell/projeto-chatme
   # slogan: Inbox multi-tenant de WhatsApp da Flouds, self-hosted e whitelabel
   # category: communication
   # tags: whatsapp,inbox,helpdesk
   # port: 8081

   services:
     chatme:
       image: dncarbonell/chatme:latest
       pull_policy: always
       environment:
         # --- Configurações gerais ---
         - SERVICE_URL_CHATME_8081
         - PUBLIC_BASE_URL=${SERVICE_URL_CHATME}
         - TZ=${TZ:-America/Sao_Paulo}
         - PORT=8081
         #- LOG_LEVEL=info

         # --- Banco de dados (PostgreSQL/pgvector) ---
         - DATABASE_URL=postgres://chatme:${SERVICE_PASSWORD_POSTGRES}@postgres:5432/chatme?sslmode=disable

         # --- Segurança ---
         - SECURE_COOKIES=true

         # --- Chave mestra da instalação (OBRIGATÓRIA, não muda depois do 1º boot) ---
         - CHATME_MASTER_KEY=${SERVICE_PASSWORD_64_CHATMEMASTERKEY}

         # --- Licença (entregue pela Flouds) ---
         # Deixe vazio para rodar em modo "unlicensed" (funcional, com aviso, 1 tenant/1 pessoa)
         - CHATME_LICENSE_KEY=${CHATME_LICENSE_KEY:-}

         # --- fzap (conector WhatsApp — instância própria, obrigatória) ---
         - FZAP_BASE_URL=${FZAP_BASE_URL:?informe a URL da sua instância fzap}
         - FZAP_ADMIN_TOKEN=${FZAP_ADMIN_TOKEN:?informe o ADMIN_TOKEN dessa instância fzap}

         # --- Armazenamento de mídia (volume local por padrão) ---
         - STORAGE_BACKEND=fs
         - STORAGE_ROOT=/var/lib/chatme/storage
         - STORAGE_SIGN_SECRET=${SERVICE_PASSWORD_64_STORAGESIGN}
       volumes:
         - chatme_media:/var/lib/chatme/storage
       depends_on:
         postgres:
           condition: service_healthy
       restart: unless-stopped

     postgres:
       image: pgvector/pgvector:pg16
       environment:
         - POSTGRES_DB=chatme
         - POSTGRES_USER=chatme
         - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
         - TZ=${TZ:-America/Sao_Paulo}
       volumes:
         - chatme_pgdata:/var/lib/postgresql/data
       healthcheck:
         test:
           - CMD-SHELL
           - pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}
         interval: 10s
         timeout: 5s
         retries: 10
         start_period: 20s
       restart: unless-stopped

   volumes:
     chatme_pgdata:
     chatme_media:
   ```

   [Abrir Compose oficial no GitHub](https://github.com/flouds-dncarbonell/projeto-chatme/blob/main/deploy/coolify/docker-compose.yml)

3. **Informe as variáveis do FZAP**  
   Em **Environment Variables**, informe `FZAP_BASE_URL`, `FZAP_ADMIN_TOKEN` e, se tiver, `CHATME_LICENSE_KEY`.

   > **Atenção:** O Coolify gera `CHATME_MASTER_KEY` e `STORAGE_SIGN_SECRET` no primeiro deploy. Não regenere essas duas depois: elas não podem mudar após o primeiro boot.

4. **Configure o domínio**  
   No serviço `chatme`, configure o domínio usando a porta interna `8081`.

5. **Faça o deploy**  
   Salve, faça o deploy e acompanhe o serviço `chatme` até ficar ativo.

## Easypanel: Gere o template no site da Flouds

Preencha os dados essenciais e receba um JSON pronto para importar. Senha do banco e chaves são criadas localmente no seu navegador.

**Antes de começar** (5–10 min)

- Easypanel funcionando
- Domínio apontado para o servidor
- Uma instância do FZAP já instalada, com ADMIN_TOKEN em mãos

1. **Gere o template**  
   Preencha os campos abaixo e gere o JSON. Senha do banco e chaves são criadas no seu navegador.

   O template cria o Chatme, PostgreSQL 16 com pgvector, volume de mídia e credenciais exclusivas. As credenciais são geradas neste navegador e não são enviadas à Flouds.

   https://flouds.com.br/produtos/chatme/instalacao?metodo=easypanel

   > **Atenção:** O JSON contém `CHATME_MASTER_KEY` e `STORAGE_SIGN_SECRET`. Guarde o arquivo baixado: **Gerar novas credenciais** cria chaves novas, que não servem para uma instalação já iniciada.

2. **Abra a importação**  
   No Easypanel, abra **Templates** e escolha **Import JSON**, **Create from JSON** ou **Custom Template**, conforme a sua versão.

3. **Crie o projeto**  
   Cole o JSON, dê um nome ao projeto e clique em **Create**.

4. **Adicione o domínio**  
   Abra o serviço `chatme`, adicione o domínio principal e confirme a porta de proxy `8081`.

5. **Faça o deploy**  
   Na primeira visita ao domínio, o Chatme mostra a tela de configuração inicial.

## Confirme que tudo está funcionando

1. Os serviços `chatme` e `postgres` aparecem como ativos no seu painel.
2. Você entra com o admin criado na configuração inicial.
3. Com a licença ativa, conecte um número do FZAP e envie uma mensagem de teste.

## Sem licença ou com licença, a instalação é a mesma

A chave apenas libera os limites da plataforma. Ela não muda a imagem Docker, o banco ou o processo de deploy.

### Sem licença: Modo não licenciado

Deixe `CHATME_LICENSE_KEY` vazia. O Chatme sobe com um aviso na interface e serve para conferir a instalação antes de assinar.

**Sem a chave**

- Concluir a instalação e a configuração inicial
- Entrar com 1 conta e 1 pessoa
- Conferir domínio, HTTPS e banco

**Só com a chave**

- Conectar WhatsApp, Instagram ou Messenger
- Enviar mensagens, campanhas e automações
- Criar mais contas e atendentes

### Com licença: Adicione a chave à instalação

Assine um plano do Chatme, copie a chave na sua área de membros e adicione esta variável ao serviço.

```env
CHATME_LICENSE_KEY=SUA_CHAVE_AQUI
```

**Depois de colar a chave**

1. Atualize o serviço `chatme`: a chave é lida quando ele sobe
2. O aviso some, e o plano aparece em **Console → Licença**

## Domínios próprios por conta

Opcional · Chatme 0.7.0+. Cada conta atende no domínio do próprio cliente, como `atendimento.cliente.com.br`. Você prepara o servidor uma vez e cadastra cada domínio no console.

- [Ver o guia de domínios](https://flouds.com.br/produtos/chatme/instalacao/dominios)
- [Versão em texto para IA (Markdown)](https://flouds.com.br/llms/chatme/instalacao-dominios.md)

## Precisa de ajuda?

Fale com o nosso time para dúvidas sobre a instalação ou a licença.

- [Falar com o suporte](https://flouds.com.br/contato)
- [Ver o guia no GitHub](https://github.com/flouds-dncarbonell/projeto-chatme#readme)
