# Instala Chatme en tu servidor

> Elige el método que encaja con tu infraestructura. FZAP debe estar funcionando antes: es el conector obligatorio de WhatsApp de Chatme.

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

## Manual: Instalación manual con Portainer

Usa este camino si Docker Swarm, Portainer, Traefik y una instancia de FZAP ya están preparados. Podrás revisar el stack y cada variable antes del deploy.

**Antes de empezar** (15–25 min)

- Docker Swarm activo con Portainer accesible
- Traefik y dominio configurados
- Una instancia de FZAP ya instalada, con ADMIN_TOKEN a mano
- PostgreSQL con pgvector (el stack ya incluye un servicio listo)

1. **Crea los volúmenes**  
   Crea los volúmenes externos usados por la base de datos y los archivos de medios de Chatme.

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

2. **Pega el stack en Portainer**  
   En Portainer, abre **Stacks → Add stack**, usa el nombre `chatme` y pega el stack oficial de abajo. Usa ese nombre: la configuración de dominios propios cuenta con él.

   ```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 en GitHub](https://github.com/flouds-dncarbonell/projeto-chatme/blob/main/stack.yml)

3. **Genera las claves y revisa las variables**  
   Genera `CHATME_MASTER_KEY` y `STORAGE_SIGN_SECRET` con el comando de abajo. Después revisa `PUBLIC_BASE_URL`, la contraseña de la base, `FZAP_BASE_URL` y `FZAP_ADMIN_TOKEN`.

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

   > **Atención:** Guarda las dos claves en un lugar seguro antes del deploy. No pueden cambiar después del primer arranque.

4. **Haz el deploy**  
   Haz clic en **Deploy the stack** y espera hasta que el servicio `chatme` esté activo.

5. **Crea el administrador**  
   Abre el dominio configurado. En la primera visita, Chatme muestra la pantalla de configuración inicial, donde creas el admin y el primer tenant.

## Coolify: Instálalo como un recurso de Coolify

Coolify se encarga del proxy, HTTPS, red, volúmenes y credenciales. Solo necesitas crear el recurso, pegar el Compose oficial y configurar el dominio.

**Antes de empezar** (10–15 min)

- Coolify funcionando
- Dominio apuntado al servidor
- Una instancia de FZAP ya instalada, con ADMIN_TOKEN a mano

1. **Crea el recurso**  
   En el proyecto deseado, haz clic en **New Resource** y elige **Docker Compose Empty**.

2. **Pega el Compose oficial**  
   Copia todo el `docker-compose.yml` de abajo y pégalo en el editor del 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 en GitHub](https://github.com/flouds-dncarbonell/projeto-chatme/blob/main/deploy/coolify/docker-compose.yml)

3. **Indica las variables de FZAP**  
   En **Environment Variables**, indica `FZAP_BASE_URL`, `FZAP_ADMIN_TOKEN` y, si tienes, `CHATME_LICENSE_KEY`.

   > **Atención:** Coolify genera `CHATME_MASTER_KEY` y `STORAGE_SIGN_SECRET` en el primer deploy. No las regeneres después: no pueden cambiar tras el primer arranque.

4. **Configura el dominio**  
   En el servicio `chatme`, configura el dominio usando el puerto interno `8081`.

5. **Haz el deploy**  
   Guarda, haz el deploy y espera hasta que el servicio `chatme` esté activo.

## Easypanel: Genera la plantilla en el sitio de Flouds

Completa los datos esenciales y recibe un JSON listo para importar. La contraseña de la base y las claves se crean localmente en tu navegador.

**Antes de empezar** (5–10 min)

- Easypanel funcionando
- Dominio apuntado al servidor
- Una instancia de FZAP ya instalada, con ADMIN_TOKEN a mano

1. **Genera la plantilla**  
   Completa los campos de abajo y genera el JSON. La contraseña de la base y las claves se crean en tu navegador.

   La plantilla crea Chatme, PostgreSQL 16 con pgvector, un volumen de medios y credenciales exclusivas. Las credenciales se generan en este navegador y no se envían a Flouds.

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

   > **Atención:** El JSON contiene `CHATME_MASTER_KEY` y `STORAGE_SIGN_SECRET`. Guarda el archivo descargado: **Generar nuevas credenciales** crea claves nuevas, que no sirven para una instalación ya iniciada.

2. **Abre la importación**  
   En Easypanel, abre **Templates** y elige **Import JSON**, **Create from JSON** o **Custom Template**, según tu versión.

3. **Crea el proyecto**  
   Pega el JSON, ponle un nombre al proyecto y haz clic en **Create**.

4. **Agrega el dominio**  
   Abre el servicio `chatme`, agrega el dominio principal y confirma el puerto de proxy `8081`.

5. **Haz el deploy**  
   En la primera visita al dominio, Chatme muestra la pantalla de configuración inicial.

## Confirma que todo funciona

1. Los servicios `chatme` y `postgres` aparecen activos en tu panel.
2. Entras con el admin creado en la configuración inicial.
3. Con la licencia activa, conecta un número de FZAP y envía un mensaje de prueba.

## Con o sin licencia, la instalación es la misma

La clave solo libera los límites de la plataforma. No cambia la imagen Docker, la base de datos ni el proceso de deploy.

### Sin licencia: Modo sin licencia

Deja `CHATME_LICENSE_KEY` vacía. Chatme arranca con un aviso en la interfaz y sirve para revisar la instalación antes de suscribirte.

**Sin la clave**

- Completar la instalación y la configuración inicial
- Entrar con 1 cuenta y 1 persona
- Revisar dominio, HTTPS y base de datos

**Solo con la clave**

- Conectar WhatsApp, Instagram o Messenger
- Enviar mensajes, campañas y automatizaciones
- Crear más cuentas y agentes

### Con licencia: Agrega la clave a la instalación

Suscríbete a un plan de Chatme, copia la clave en tu área de miembros y agrega esta variable al servicio.

```env
CHATME_LICENSE_KEY=SUA_CHAVE_AQUI
```

**Después de pegar la clave**

1. Actualiza el servicio `chatme`: la clave se lee al arrancar
2. El aviso desaparece y el plan aparece en **Consola → Licencia**

## Dominios propios por cuenta

Opcional · Chatme 0.7.0+. Cada cuenta atiende en el dominio del propio cliente, como `atencion.cliente.com`. Preparas el servidor una vez y registras cada dominio en la consola.

- [Ver la guía de dominios](https://flouds.com.br/es/produtos/chatme/instalacao/dominios)
- [Versión en texto para IA (Markdown)](https://flouds.com.br/llms/es/chatme/instalacao-dominios.md)

## ¿Necesitas ayuda?

Habla con nuestro equipo si tienes dudas sobre la instalación o la licencia.

- [Hablar con soporte](https://flouds.com.br/es/contacto)
- [Ver la guía en GitHub](https://github.com/flouds-dncarbonell/projeto-chatme#readme)
