---
title: "Hospedar o HitKeep com Docker Compose | HitKeep"
description: "Hospede o HitKeep com Docker Compose, armazenamento persistente, rede pré-configurada e exemplos de proxy reverso para Caddy, nginx e Traefik."
canonical: "https://hitkeep.com/pt/guides/installation/docker-compose/"
---

# Hospedar o HitKeep com Docker Compose

O Docker Compose oferece uma implantação reproduzível e versionada com volumes de armazenamento persistente. Seus dados analíticos permanecem em um volume Docker nomeado no servidor, incluindo o `hitkeep.db` compartilhado e os bancos locais de tenants em `tenants/*/hitkeep.db`.

Esta página ensina a executar o HitKeep como serviço self-hosted. Para o ambiente de contribuição com hot reload, Go, Air, Angular, Mailpit e dados de demonstração no Docker, consulte o [guia de contribuição](https://hitkeep.com/guides/contributing/).

As imagens do HitKeep são publicadas em dois registros a cada versão:

| Registro | Imagem |
| --- | --- |
| Docker Hub | pascalebeier/hitkeep |
| GitHub Container Registry | ghcr.io/pascalebeier/hitkeep |

Os dois registros contêm as mesmas imagens multiplataforma (`linux/amd64`, `linux/arm64`), com attestations de procedência assinadas. Use o registro mais adequado à sua rede ou aos limites de download.

Não coloque segredos nos arquivos do Compose

Passe valores sensíveis (`HITKEEP_JWT_SECRET`, senhas SMTP) por variáveis de ambiente, arquivo `.env` ou Docker secrets, nunca diretamente em `compose.yml` ou em parâmetros de comando. Não versione o `.env`. Para um controle mais rigoroso, use Docker secrets.

## Início rápido

A implantação usa dois arquivos no mesmo diretório: `compose.yml` (copie sem alterar) e `.env` (onde ficam os seus valores). Ao iniciar, o Compose substitui cada `${VARIABLE}` de `compose.yml` pela linha correspondente de `.env`.

### 1. Criar compose.yml

Crie um diretório e adicione este `compose.yml`. A configuração base mantém dados ativos, arquivos de retenção e snapshots automáticos em volumes nomeados separados. O mesmo arquivo é mantido no repositório como [`examples/compose.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.yml), junto de [`examples/.env.example`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/.env.example).

```
services:
  hitkeep:
    image: pascalebeier/hitkeep:latest
    container_name: hitkeep
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - hitkeep_data:/var/lib/hitkeep/data
      - hitkeep_archive:/var/lib/hitkeep/archive
      - hitkeep_backups:/var/lib/hitkeep/backups
    environment:
      # Public URL must match the browser-visible origin, including any path prefix.
      HITKEEP_PUBLIC_URL: ${HITKEEP_PUBLIC_URL:-http://localhost:8080}
      # Required for stable sessions. Generate with: openssl rand -hex 32
      HITKEEP_JWT_SECRET: ${HITKEEP_JWT_SECRET:?set HITKEEP_JWT_SECRET in .env}
      # Behind a reverse proxy, set to the proxy network CIDR so real client IPs are used.
      HITKEEP_TRUSTED_PROXIES: ${HITKEEP_TRUSTED_PROXIES:-} # config-default-override: require an explicit trusted proxy network
      # Keep live data, retention archives, and backup snapshots on persistent volumes.
      HITKEEP_DB_PATH: /var/lib/hitkeep/data/hitkeep.db
      HITKEEP_DATA_PATH: /var/lib/hitkeep/data
      HITKEEP_ARCHIVE_PATH: /var/lib/hitkeep/archive
      HITKEEP_BACKUP_PATH: /var/lib/hitkeep/backups
      HITKEEP_BACKUP_INTERVAL: ${HITKEEP_BACKUP_INTERVAL:-60}
      HITKEEP_BACKUP_RETENTION: ${HITKEEP_BACKUP_RETENTION:-24}
      # Optional OSS spam-list refresh. Disable for fully offline/air-gapped installs.
      HITKEEP_SPAM_FILTER_AUTO_UPDATE: "true"
      HITKEEP_SPAM_FILTER_UPDATE_INTERVAL: ${HITKEEP_SPAM_FILTER_UPDATE_INTERVAL:-1440}
      HITKEEP_SPAM_FILTER_PATH: /var/lib/hitkeep/data/spam-filter.json
      # Optional read-only MCP endpoint for governed assistant/reporting access.
      HITKEEP_MCP_ENABLED: "true"
      HITKEEP_MCP_PATH: /mcp
      HITKEEP_MCP_MAX_RANGE_DAYS: ${HITKEEP_MCP_MAX_RANGE_DAYS:-366}
      # Optional AI model route for Opportunity enrichment. Provider credentials
      # use the selected goAI provider's own env vars, such as OPENAI_API_KEY.
      HITKEEP_AI_ENABLED: ${HITKEEP_AI_ENABLED:-false}
      HITKEEP_AI_PROVIDER: ${HITKEEP_AI_PROVIDER:-}
      HITKEEP_AI_MODEL: ${HITKEEP_AI_MODEL:-}
      HITKEEP_AI_BASE_URL: ${HITKEEP_AI_BASE_URL:-}
      HITKEEP_AI_REGION: ${HITKEEP_AI_REGION:-}
      HITKEEP_AI_API_KEY: ${HITKEEP_AI_API_KEY:-}
      HITKEEP_AI_REQUEST_LIMIT: ${HITKEEP_AI_REQUEST_LIMIT:-100}
      HITKEEP_AI_TOKEN_LIMIT: ${HITKEEP_AI_TOKEN_LIMIT:-100000}
      HITKEEP_AI_BUDGET_WINDOW: ${HITKEEP_AI_BUDGET_WINDOW:-1440}
      # Optional Google Search Console OAuth integration.
      HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID:-}
      HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET:-}
      HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL:-}
      # Optional Google, GitHub, and Microsoft social sign-in.
      HITKEEP_SOCIAL_GOOGLE_CLIENT_ID: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_ID:-}
      HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET:-}
      HITKEEP_SOCIAL_GITHUB_CLIENT_ID: ${HITKEEP_SOCIAL_GITHUB_CLIENT_ID:-}
      HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET: ${HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET:-}
      HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID:-}
      HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET:-}
      HITKEEP_SOCIAL_MICROSOFT_TENANT: ${HITKEEP_SOCIAL_MICROSOFT_TENANT:-common}
      # SMTP powers invites, password reset, email reports, and security mail.
      HITKEEP_MAIL_HOST: ${HITKEEP_MAIL_HOST:-}
      HITKEEP_MAIL_PORT: ${HITKEEP_MAIL_PORT:-587}
      HITKEEP_MAIL_USERNAME: ${HITKEEP_MAIL_USERNAME:-}
      HITKEEP_MAIL_PASSWORD: ${HITKEEP_MAIL_PASSWORD:-}
      HITKEEP_MAIL_ENCRYPTION: ${HITKEEP_MAIL_ENCRYPTION:-tls}
      HITKEEP_MAIL_FROM_ADDRESS: ${HITKEEP_MAIL_FROM_ADDRESS:-hitkeep@localhost}
      HITKEEP_MAIL_FROM_NAME: ${HITKEEP_MAIL_FROM_NAME:-HitKeep}

volumes:
  hitkeep_data: {}
  hitkeep_archive: {}
  hitkeep_backups: {}
```

### 2. Criar .env

Primeiro, gere a chave de assinatura da sessão no terminal e copie o resultado:

```
openssl rand -hex 32
```

Se `openssl` não estiver instalado, `head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'; echo` gera um valor equivalente em qualquer máquina Linux.

Em seguida, crie no editor um arquivo `.env` ao lado de `compose.yml` e preencha os valores:

```
# Required. Paste the generated 64-character hex string here.
HITKEEP_JWT_SECRET=paste-the-generated-value-here
# Required. The exact URL you open in the browser. Behind a reverse proxy
# this is your public domain, e.g. https://analytics.example.com
HITKEEP_PUBLIC_URL=http://localhost:8080
# Optional social sign-in. Set both values for each provider you enable.
HITKEEP_SOCIAL_GOOGLE_CLIENT_ID=
HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET=
HITKEEP_SOCIAL_GITHUB_CLIENT_ID=
HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET=
HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID=
HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET=
HITKEEP_SOCIAL_MICROSOFT_TENANT=common
# Optional SMTP. Powers invites, password resets, and email reports.
# Leave the values empty to run without outbound mail.
HITKEEP_MAIL_HOST=
HITKEEP_MAIL_PORT=587
HITKEEP_MAIL_USERNAME=
HITKEEP_MAIL_PASSWORD=
HITKEEP_MAIL_FROM_ADDRESS=hitkeep@localhost
HITKEEP_MAIL_FROM_NAME=HitKeep
```

.env não é um script de shell

O `.env` contém linhas simples `KEY=value`: sem `echo`, chaves ou substituição `$(command)`. O Docker Compose lê o conteúdo literalmente; comandos colados no arquivo chegam como texto. Aspas são desnecessárias. Não versione esse arquivo; adicione-o a `.gitignore`.

Os dois arquivos usam sintaxes diferentes de propósito: `compose.yml` é YAML, portanto usa `KEY: value`; `.env` usa o formato dotenv, `KEY=value`.

### 3. Iniciar o HitKeep

```
docker compose up -d
docker compose logs -f hitkeep
```

As linhas `Starting HitKeep` e `HTTP server starting` indicam que o serviço está no ar.

### 4. Entrar

Abra `HITKEEP_PUBLIC_URL` no navegador. O assistente cria a primeira conta, que se torna automaticamente proprietária da instância, e orienta você a adicionar o primeiro site.

O banco fica no volume `hitkeep_data`. O diretório padrão de recuperação automática, `/var/lib/hitkeep/data/recovery`, também é persistente. Arquivos de retenção ficam em `hitkeep_archive`, e snapshots automáticos em `hitkeep_backups`. Pacotes de recuperação contêm material do banco, não seguem a retenção dos backups e devem ser protegidos e removidos separadamente. O MCP é exposto em `/mcp`, mas clientes ainda precisam de tokens bearer de API com escopo.

O MCP é opcional no produto e está ativado neste exemplo para equipes que desejam acesso somente leitura por assistentes e relatórios. Remova `HITKEEP_MCP_ENABLED`, `HITKEEP_MCP_PATH` e `HITKEEP_MCP_MAX_RANGE_DAYS` se não for publicar um endpoint MCP.

O enriquecimento por provedor de IA é opcional e fica desativado por padrão. Mantenha `HITKEEP_AI_ENABLED=false` até escolher provedor e modelo, configurar credenciais e limites locais de orçamento. Consulte [Recomendações de oportunidades](https://hitkeep.com/guides/analytics/opportunities/) e o [guia de configuração do modelo de IA](https://hitkeep.com/guides/admin/ai-model-configuration/).

O login social é opcional. Defina o ID e o segredo de cada provedor desejado e registre a callback exata derivada de `HITKEEP_PUBLIC_URL`. O [guia de login social](https://hitkeep.com/guides/security/social-sign-in/) cobre cadastro dos provedores, callbacks, verificação de e-mail, convites, MFA e vinculação de contas. `HITKEEP_SOCIAL_SIGNUP_ENABLED` não abre cadastro público em uma instância self-hosted.

Dados de cidade, provedor e ASN estão incorporados às imagens. Implantações Compose não precisam de `IP2LOCATION_DOWNLOAD_TOKEN` em execução.

## Verificar

Confirme que o serviço está em execução e que as duas sondas respondem:

```
docker compose ps
curl --fail http://localhost:8080/healthz
curl --fail http://localhost:8080/readyz
docker compose logs --since=5m hitkeep
```

`/healthz` confirma que o processo está ativo. `/readyz` confirma que o banco compartilhado e todos os bancos de tenants abertos estão prontos. Se o HitKeep só estiver acessível pelo proxy reverso, use a URL visível no navegador.

## Atualizar

Leia as [notas da versão mais recente](https://github.com/PascaleBeier/hitkeep/releases/latest) e confirme que existe um backup atual. Baixe a imagem estável e recrie apenas o serviço do HitKeep:

```
docker compose pull hitkeep
docker compose up -d hitkeep
docker compose ps
curl --fail http://localhost:8080/readyz
```

O Compose mantém os volumes de dados, arquivos e backups ao substituir o contêiner. Não execute `docker compose down -v` durante a atualização: `-v` exclui esses volumes.

## Configurações de proxy reverso

Em produção, execute o HitKeep atrás de um proxy reverso com HTTPS. Configure os [proxies confiáveis](https://hitkeep.com/guides/installation/trusted-proxies/) para usar os IPs reais nas análises e nos limites de requisições.

`HITKEEP_PUBLIC_URL` pode conter um prefixo. Por exemplo, use `HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/` para montar o HitKeep abaixo de outro site. O proxy deve publicar o mesmo prefixo, como `/hitkeep/*`, e encaminhá-lo ao contêiner. Assim, base do painel, API, `hk.js`, `hk-vitals.js` e endpoints de ingestão permanecem nesse prefixo.

- Caddy
- nginx
- Traefik

O `caddy-docker-proxy` oferece HTTPS automático (Let’s Encrypt) e gera a configuração do Caddy a partir dos labels do Docker. A prática recomendada é usar uma rede de ingress dedicada e confiar somente no CIDR dessa rede.

```
services:
caddy:
  image: lucaslorentz/caddy-docker-proxy:2.9-alpine
  container_name: caddy-proxy
  restart: unless-stopped
  ports:
    - "80:80"
    - "443:443"
    - "443:443/udp"
  environment:
    CADDY_INGRESS_NETWORKS: caddy
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock:ro
    - caddy_data:/data
    - caddy_config:/config
  networks:
    - caddy
  labels:
    caddy.email: ${CADDY_EMAIL:?set in .env}

hitkeep:
  image: pascalebeier/hitkeep:latest
  container_name: hitkeep
  restart: unless-stopped
  networks:
    - caddy
  volumes:
    - hitkeep_data:/var/lib/hitkeep/data
    - hitkeep_archive:/var/lib/hitkeep/archive
    - hitkeep_backups:/var/lib/hitkeep/backups
  environment:
    HITKEEP_NODE_NAME: leader
    # Public URL must match the HTTPS origin served by Caddy, including any path prefix.
    HITKEEP_PUBLIC_URL: ${HITKEEP_PUBLIC_URL:?set in .env}
    # Required for stable sessions. Generate with: openssl rand -hex 32
    HITKEEP_JWT_SECRET: ${HITKEEP_JWT_SECRET:?set in .env}
    # Must be the Caddy network CIDR. This controls real visitor IP, geo/network metadata,
    # country exclusions, rate limiting, and spam checks.
    HITKEEP_TRUSTED_PROXIES: ${HITKEEP_TRUSTED_PROXIES:?set to your caddy network CIDR}
    # Keep live data, retention archives, and backup snapshots on persistent volumes.
    HITKEEP_DB_PATH: /var/lib/hitkeep/data/hitkeep.db
    HITKEEP_DATA_PATH: /var/lib/hitkeep/data
    HITKEEP_ARCHIVE_PATH: /var/lib/hitkeep/archive
    HITKEEP_BACKUP_PATH: /var/lib/hitkeep/backups
    HITKEEP_BACKUP_INTERVAL: ${HITKEEP_BACKUP_INTERVAL:-60}
    HITKEEP_BACKUP_RETENTION: ${HITKEEP_BACKUP_RETENTION:-24}
    # Optional OSS spam-list refresh. Disable for fully offline/air-gapped installs.
    HITKEEP_SPAM_FILTER_AUTO_UPDATE: "true"
    HITKEEP_SPAM_FILTER_UPDATE_INTERVAL: ${HITKEEP_SPAM_FILTER_UPDATE_INTERVAL:-1440}
    HITKEEP_SPAM_FILTER_PATH: /var/lib/hitkeep/data/spam-filter.json
    # Optional read-only MCP endpoint for governed assistant/reporting access.
    HITKEEP_MCP_ENABLED: "true"
    HITKEEP_MCP_PATH: /mcp
    HITKEEP_MCP_MAX_RANGE_DAYS: ${HITKEEP_MCP_MAX_RANGE_DAYS:-366}
    # Optional AI model route for Opportunity enrichment. Leave disabled until a provider is configured.
    HITKEEP_AI_ENABLED: ${HITKEEP_AI_ENABLED:-false}
    HITKEEP_AI_PROVIDER: ${HITKEEP_AI_PROVIDER:-}
    HITKEEP_AI_MODEL: ${HITKEEP_AI_MODEL:-}
    HITKEEP_AI_BASE_URL: ${HITKEEP_AI_BASE_URL:-}
    HITKEEP_AI_REGION: ${HITKEEP_AI_REGION:-}
    HITKEEP_AI_API_KEY: ${HITKEEP_AI_API_KEY:-}
    HITKEEP_AI_REQUEST_LIMIT: ${HITKEEP_AI_REQUEST_LIMIT:-100}
    HITKEEP_AI_TOKEN_LIMIT: ${HITKEEP_AI_TOKEN_LIMIT:-100000}
    HITKEEP_AI_BUDGET_WINDOW: ${HITKEEP_AI_BUDGET_WINDOW:-1440}
    # Optional Google Search Console OAuth integration.
    HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID:-}
    HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET:-}
    HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL:-}
    # Optional Google, GitHub, and Microsoft social sign-in.
    HITKEEP_SOCIAL_GOOGLE_CLIENT_ID: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_ID:-}
    HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_GITHUB_CLIENT_ID: ${HITKEEP_SOCIAL_GITHUB_CLIENT_ID:-}
    HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET: ${HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID:-}
    HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_MICROSOFT_TENANT: ${HITKEEP_SOCIAL_MICROSOFT_TENANT:-common}
    # SMTP powers invites, password reset, email reports, and security mail.
    HITKEEP_MAIL_HOST: ${HITKEEP_MAIL_HOST:-}
    HITKEEP_MAIL_PORT: ${HITKEEP_MAIL_PORT:-587}
    HITKEEP_MAIL_USERNAME: ${HITKEEP_MAIL_USERNAME:-}
    HITKEEP_MAIL_PASSWORD: ${HITKEEP_MAIL_PASSWORD:-}
    HITKEEP_MAIL_ENCRYPTION: ${HITKEEP_MAIL_ENCRYPTION:-tls}
    HITKEEP_MAIL_FROM_ADDRESS: ${HITKEEP_MAIL_FROM_ADDRESS:-hitkeep@localhost}
    HITKEEP_MAIL_FROM_NAME: ${HITKEEP_MAIL_FROM_NAME:-HitKeep}
  labels:
    caddy: ${HITKEEP_HOSTNAME:?set in .env}
    caddy.reverse_proxy: "{{upstreams 8080}}"
    caddy.encode: "zstd gzip"

volumes:
caddy_data: {}
caddy_config: {}
hitkeep_data: {}
hitkeep_archive: {}
hitkeep_backups: {}

networks:
caddy:
  external: true
```

Dois valores vêm do terminal: o segredo da sessão e o CIDR da rede do Caddy:

```
openssl rand -hex 32
docker network inspect caddy --format '{{(index .IPAM.Config 0).Subnet}}'
```

Depois, crie o arquivo `.env` no editor:

```
# Required. Paste the generated 64-character hex string here.
HITKEEP_JWT_SECRET=paste-the-generated-value-here
HITKEEP_PUBLIC_URL=https://analytics.example.com
HITKEEP_HOSTNAME=analytics.example.com
CADDY_EMAIL=ops@example.com
# Paste the Caddy network subnet from the docker network inspect command.
HITKEEP_TRUSTED_PROXIES=paste-the-caddy-subnet-here
# Optional social sign-in. Set both values for each provider you enable.
HITKEEP_SOCIAL_GOOGLE_CLIENT_ID=
HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET=
HITKEEP_SOCIAL_GITHUB_CLIENT_ID=
HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET=
HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID=
HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET=
HITKEEP_SOCIAL_MICROSOFT_TENANT=common
HITKEEP_MAIL_HOST=smtp.example.com
HITKEEP_MAIL_PORT=587
HITKEEP_MAIL_USERNAME=postmaster@example.com
HITKEEP_MAIL_PASSWORD=change-me
HITKEEP_MAIL_FROM_ADDRESS=analytics@example.com
HITKEEP_MAIL_FROM_NAME=HitKeep
```

`HITKEEP_TRUSTED_PROXIES` deve ser o CIDR da rede do proxy reverso, não `0.0.0.0/0`.

Para uma montagem em subdiretório, mantenha `HITKEEP_PUBLIC_URL` e o prefixo da rota do proxy alinhados. A rota equivalente no Caddy é:

```
HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/
HITKEEP_HOSTNAME=www.example.net
```

```
www.example.net {
handle /hitkeep* {
  reverse_proxy hitkeep:8080
}
encode zstd gzip
}
```

Para um nginx existente no host, que administra seus próprios certificados (por exemplo, via certbot), mantenha o `compose.yml` do início rápido e aponte o nginx para a porta publicada.

Faça dois ajustes nos arquivos:

1. Em `compose.yml`, vincule a porta ao loopback para que apenas o nginx local alcance o contêiner:

```
    ports:
    - "127.0.0.1:8080:8080"
```

1. Em `.env`, defina a URL pública com o domínio do nginx e confie na rede Docker. O tráfego do host chega pelo gateway Docker, na faixa `172.16.0.0/12`:

```
HITKEEP_PUBLIC_URL=https://analytics.example.com
HITKEEP_TRUSTED_PROXIES=172.16.0.0/12
```

Depois, adicione um bloco de servidor ao nginx:

```
server {
  listen 443 ssl;
  http2 on;
  server_name analytics.example.com;

  # ssl_certificate / ssl_certificate_key as issued by certbot or your CA.

  location / {
      proxy_pass http://127.0.0.1:8080;
      proxy_http_version 1.1;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      # Live dashboard updates stream over server-sent events.
      proxy_set_header Connection "";
      proxy_buffering off;
      proxy_read_timeout 300s;
  }
}
```

Recarregue o nginx (`nginx -t && systemctl reload nginx`) e abra `https://analytics.example.com`. Se todos os visitantes aparecerem com o mesmo IP privado, reveja [Proxies confiáveis](https://hitkeep.com/guides/installation/trusted-proxies/).

Em stacks existentes com Traefik, exponha o HitKeep com labels:

```
services:
hitkeep:
  image: pascalebeier/hitkeep:latest
  restart: unless-stopped
  volumes:
    - hitkeep_data:/var/lib/hitkeep/data
    - hitkeep_archive:/var/lib/hitkeep/archive
    - hitkeep_backups:/var/lib/hitkeep/backups
  environment:
    # Public URL must match the HTTPS origin served by Traefik, including any path prefix.
    HITKEEP_PUBLIC_URL: ${HITKEEP_PUBLIC_URL:?set in .env}
    # Required for stable sessions. Generate with: openssl rand -hex 32
    HITKEEP_JWT_SECRET: ${HITKEEP_JWT_SECRET:?set in .env}
    # Must be the Traefik network CIDR. This controls real visitor IP, geo/network metadata,
    # country exclusions, rate limiting, and spam checks.
    HITKEEP_TRUSTED_PROXIES: ${HITKEEP_TRUSTED_PROXIES:?set to your traefik network CIDR}
    # Keep live data, retention archives, and backup snapshots on persistent volumes.
    HITKEEP_DB_PATH: /var/lib/hitkeep/data/hitkeep.db
    HITKEEP_DATA_PATH: /var/lib/hitkeep/data
    HITKEEP_ARCHIVE_PATH: /var/lib/hitkeep/archive
    HITKEEP_BACKUP_PATH: /var/lib/hitkeep/backups
    HITKEEP_BACKUP_INTERVAL: ${HITKEEP_BACKUP_INTERVAL:-60}
    HITKEEP_BACKUP_RETENTION: ${HITKEEP_BACKUP_RETENTION:-24}
    # Optional OSS spam-list refresh. Disable for fully offline/air-gapped installs.
    HITKEEP_SPAM_FILTER_AUTO_UPDATE: "true"
    HITKEEP_SPAM_FILTER_UPDATE_INTERVAL: ${HITKEEP_SPAM_FILTER_UPDATE_INTERVAL:-1440}
    HITKEEP_SPAM_FILTER_PATH: /var/lib/hitkeep/data/spam-filter.json
    # Optional read-only MCP endpoint for governed assistant/reporting access.
    HITKEEP_MCP_ENABLED: "true"
    HITKEEP_MCP_PATH: /mcp
    HITKEEP_MCP_MAX_RANGE_DAYS: ${HITKEEP_MCP_MAX_RANGE_DAYS:-366}
    # Optional AI model route for Opportunity enrichment. Leave disabled until a provider is configured.
    HITKEEP_AI_ENABLED: ${HITKEEP_AI_ENABLED:-false}
    HITKEEP_AI_PROVIDER: ${HITKEEP_AI_PROVIDER:-}
    HITKEEP_AI_MODEL: ${HITKEEP_AI_MODEL:-}
    HITKEEP_AI_BASE_URL: ${HITKEEP_AI_BASE_URL:-}
    HITKEEP_AI_REGION: ${HITKEEP_AI_REGION:-}
    HITKEEP_AI_API_KEY: ${HITKEEP_AI_API_KEY:-}
    HITKEEP_AI_REQUEST_LIMIT: ${HITKEEP_AI_REQUEST_LIMIT:-100}
    HITKEEP_AI_TOKEN_LIMIT: ${HITKEEP_AI_TOKEN_LIMIT:-100000}
    HITKEEP_AI_BUDGET_WINDOW: ${HITKEEP_AI_BUDGET_WINDOW:-1440}
    # Optional Google Search Console OAuth integration.
    HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_ID:-}
    HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_CLIENT_SECRET:-}
    HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL: ${HITKEEP_GOOGLE_SEARCH_CONSOLE_REDIRECT_URL:-}
    # Optional Google, GitHub, and Microsoft social sign-in.
    HITKEEP_SOCIAL_GOOGLE_CLIENT_ID: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_ID:-}
    HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET: ${HITKEEP_SOCIAL_GOOGLE_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_GITHUB_CLIENT_ID: ${HITKEEP_SOCIAL_GITHUB_CLIENT_ID:-}
    HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET: ${HITKEEP_SOCIAL_GITHUB_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_ID:-}
    HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET: ${HITKEEP_SOCIAL_MICROSOFT_CLIENT_SECRET:-}
    HITKEEP_SOCIAL_MICROSOFT_TENANT: ${HITKEEP_SOCIAL_MICROSOFT_TENANT:-common}
    # SMTP powers invites, password reset, email reports, and security mail.
    HITKEEP_MAIL_HOST: ${HITKEEP_MAIL_HOST:-}
    HITKEEP_MAIL_PORT: ${HITKEEP_MAIL_PORT:-587}
    HITKEEP_MAIL_USERNAME: ${HITKEEP_MAIL_USERNAME:-}
    HITKEEP_MAIL_PASSWORD: ${HITKEEP_MAIL_PASSWORD:-}
    HITKEEP_MAIL_ENCRYPTION: ${HITKEEP_MAIL_ENCRYPTION:-tls}
    HITKEEP_MAIL_FROM_ADDRESS: ${HITKEEP_MAIL_FROM_ADDRESS:-hitkeep@localhost}
    HITKEEP_MAIL_FROM_NAME: ${HITKEEP_MAIL_FROM_NAME:-HitKeep}
  labels:
    - "traefik.enable=true"
    - "traefik.http.routers.hitkeep.rule=Host(`analytics.example.com`)"
    - "traefik.http.routers.hitkeep.entrypoints=websecure"
    - "traefik.http.routers.hitkeep.tls.certresolver=myresolver"
    - "traefik.http.services.hitkeep.loadbalancer.server.port=8080"

volumes:
hitkeep_data: {}
hitkeep_archive: {}
hitkeep_backups: {}
```

## Domínios de rastreamento personalizados

Equipes self-hosted podem usar [Domínios de rastreamento personalizados](https://hitkeep.com/guides/tracking/custom-tracking-domains/) com qualquer proxy reverso que encerre TLS e preserve o cabeçalho `Host` original. Use o modo TLS externo quando os certificados forem administrados por nginx, Traefik, balanceador ou outro processo ACME. Use o perfil do Caddy apenas para provisionamento pelo painel com certificados sob demanda.

### TLS externo com nginx ou Traefik

Adicione esta configuração quando o proxy já administra os certificados:

```
HITKEEP_CUSTOM_TRACKING_TLS_MODE: external
```

No modo externo, adicione cada hostname ao proxy antes de clicar em **Verificar** no HitKeep. A sonda exige que `https://<hostname>/hk.js` retorne o tracker com um certificado válido.

O repositório inclui exemplos sem Caddy:

- [`examples/nginx.custom-tracking.conf`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/nginx.custom-tracking.conf)
- [`examples/compose.nginx-custom-tracking.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.nginx-custom-tracking.yml)
- [`examples/traefik.custom-tracking.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/traefik.custom-tracking.yml)
- [`examples/compose.traefik-custom-tracking.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.traefik-custom-tracking.yml)

O exemplo nginx restringe hosts de rastreamento aos assets do tracker e às rotas de ingestão. O Traefik usa entradas `Host(...)` exatas; não as substitua por uma regra genérica, a menos que queira aceitar hostnames arbitrários.

### TLS sob demanda com Caddy

Adicione ao serviço `hitkeep`:

```
HITKEEP_CUSTOM_TRACKING_TLS_MODE: caddy-on-demand
HITKEEP_CADDY_TLS_ASK_TOKEN: ${HITKEEP_CADDY_TLS_ASK_TOKEN:?set in .env}
# Optional. Use only when tracker hostnames point somewhere other than
# the host in HITKEEP_PUBLIC_URL.
HITKEEP_CUSTOM_TRACKING_DNS_TARGET: ${HITKEEP_CUSTOM_TRACKING_DNS_TARGET:-}
```

Gere o token no terminal (`openssl rand -hex 32`) e adicione-o ao `.env`:

```
HITKEEP_CADDY_TLS_ASK_TOKEN=paste-the-generated-value-here
```

Use um Caddyfile com armazenamento persistente e endpoint ask restrito:

```
{
email ops@example.com
storage file_system {
  root /data
}
on_demand_tls {
  ask http://hitkeep:8080/internal/caddy/on-demand-tls/{$HITKEEP_CADDY_TLS_ASK_TOKEN}
}
}

{$HITKEEP_HOSTNAME} {
reverse_proxy hitkeep:8080
encode zstd gzip
}

https:// {
tls {
  on_demand
}

reverse_proxy hitkeep:8080 {
  header_up Host {host}
  header_up X-Forwarded-Host {host}
  header_up X-Forwarded-Proto {scheme}
}

encode zstd gzip
}
```

O Caddy envia `?domain=` ao endpoint ask antes de emitir o certificado. O HitKeep retorna `204` somente quando o token coincide e o hostname solicitado é um domínio de rastreamento ativado e verificado por DNS. Nunca use TLS sob demanda sem `ask`; qualquer hostname que alcance o listener poderia tentar emitir um certificado.

O repositório contém um perfil opcional completo:

- [`examples/Caddyfile.custom-tracking`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/Caddyfile.custom-tracking)
- [`examples/compose.caddy-on-demand.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.caddy-on-demand.yml)

## Backup

O início rápido ativa o worker de backup com checkpoints e salva snapshots no volume persistente `hitkeep_backups`. Teste uma restauração, copie os backups para fora do host Docker e consulte [Backups e restauração](https://hitkeep.com/guides/data/backups-and-restore/) para o conjunto de dados completo.

### Usar backups ou arquivos compatíveis com S3

Para gravar snapshots ou arquivos de retenção em armazenamento de objetos, troque os caminhos locais por URLs `s3://` e adicione ao `.env`:

```
# Local or S3 backup snapshots. Empty HITKEEP_BACKUP_PATH disables automatic backups.
HITKEEP_BACKUP_PATH=s3://my-analytics-bucket/hitkeep/backups
# Retention archives can use local paths or S3-compatible URLs.
HITKEEP_ARCHIVE_PATH=s3://my-analytics-bucket/hitkeep/archive
HITKEEP_S3_REGION=eu-central-1
# Static credentials are optional when your container runtime provides an AWS credential chain.
HITKEEP_S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
HITKEEP_S3_SECRET_ACCESS_KEY=change-me
```

Para MinIO, Cloudflare R2, Backblaze B2 ou outro endpoint compatível, defina também `HITKEEP_S3_ENDPOINT` e, quando necessário, `HITKEEP_S3_URL_STYLE=path`. Consulte [Backups no S3](https://hitkeep.com/guides/data/s3-backups/).

## Solução de problemas

**O painel mostra “An unexpected error occurred” durante a configuração ou o login.** Verifique nesta ordem:

1. **Leia primeiro os logs:** `docker compose logs hitkeep`. O HitKeep registra falhas do servidor no nível error. Se o navegador mostra erro, mas o log permanece vazio, a requisição não chegou ao contêiner: verifique o proxy e `HITKEEP_PUBLIC_URL`.
2. **`HITKEEP_PUBLIC_URL` deve corresponder exatamente à barra de endereços**, incluindo protocolo, host e porta. Com uma URL `https://`, os cookies são seguros e o login por HTTP falha. Depois de alterar `.env`, execute `docker compose up -d` para recriar o contêiner.
3. **`Setup has already been completed.`** indica que já existe usuário no banco, geralmente em um volume `hitkeep_data` antigo. `docker compose down -v` cria um início limpo, mas exclui todos os dados analíticos.
4. **Configurações de e-mail não bloqueiam a configuração inicial.** A primeira conta não envia e-mail. SMTP só importa depois para convites, redefinição de senha e relatórios.
5. **Precisa de mais detalhes?** Adicione `HITKEEP_LOG_LEVEL: debug` em `environment:` e execute `docker compose up -d` novamente.

## Relacionados

- [Proxies confiáveis](https://hitkeep.com/guides/installation/trusted-proxies/)
- [Login social](https://hitkeep.com/guides/security/social-sign-in/)
- [Domínios de rastreamento personalizados](https://hitkeep.com/guides/tracking/custom-tracking-domains/)
- [Referência de configuração](https://hitkeep.com/reference/configuration/)
- [Retenção de dados](https://hitkeep.com/guides/data/retention/)
- [Backups no S3](https://hitkeep.com/guides/data/s3-backups/)
- [Instalação pelo binário](https://hitkeep.com/pt/guides/installation/binary/)

Precisa de hospedagem gerenciada com escolha de região? [Compare o HitKeep Cloud](https://hitkeep.com/pt/pricing/) para hospedagem na UE (Frankfurt) ou nos EUA (Virgínia), sem administrar contêiner, atualizações ou backups.

[Anterior Binário Linux](https://hitkeep.com/pt/guides/installation/binary/)[Próximo Kubernetes e Helm](https://hitkeep.com/pt/guides/installation/kubernetes/)
