---
title: "Auto-héberger HitKeep avec Docker Compose | HitKeep"
description: "Auto-hébergez HitKeep avec Docker Compose, un stockage persistant, un réseau préconfiguré et des exemples de proxy inverse pour Caddy, nginx et Traefik."
canonical: "https://hitkeep.com/fr/guides/installation/docker-compose/"
---

# Auto-héberger HitKeep avec Docker Compose

Docker Compose fournit un déploiement reproductible et versionnable avec des volumes persistants. Vos données d’analyse restent dans un volume Docker nommé sur votre serveur, notamment la base partagée `hitkeep.db` et les bases propres aux espaces créées sous `tenants/*/hitkeep.db`.

Cette page explique comment exécuter HitKeep comme service auto-hébergé. Pour l’environnement de contribution avec rechargement à chaud, Go, Air, Angular, Mailpit et des données de démonstration dans Docker, consultez le [guide de contribution](https://hitkeep.com/guides/contributing/).

Les images HitKeep sont publiées dans deux registres à chaque version :

| Registre | Image |
| --- | --- |
| Docker Hub | pascalebeier/hitkeep |
| GitHub Container Registry | ghcr.io/pascalebeier/hitkeep |

Les deux registres proposent les mêmes images multiplateformes (`linux/amd64`, `linux/arm64`) accompagnées d’attestations de provenance signées. Choisissez celui qui convient à votre réseau ou à vos limites de téléchargement.

Ne placez pas les secrets dans les fichiers Compose

Transmettez les valeurs sensibles (`HITKEEP_JWT_SECRET`, mots de passe SMTP) par des variables d’environnement, un fichier `.env` ou des secrets Docker, jamais en clair dans `compose.yml` ni dans les options de commande. Excluez `.env` du contrôle de version. Pour une gestion plus stricte, utilisez les secrets Docker.

## Démarrage rapide

Un déploiement tient dans deux fichiers du même répertoire : `compose.yml` (copiez-le tel quel, sans le modifier) et `.env` (qui contient vos valeurs). Au démarrage, Compose remplace chaque `${VARIABLE}` de `compose.yml` par la ligne correspondante de `.env`.

### 1. Créer compose.yml

Créez un répertoire et ajoutez-y ce fichier `compose.yml`. Cette base conserve les données actives, les archives de rétention et les instantanés automatiques dans trois volumes nommés distincts. Le même fichier est maintenu dans le dépôt sous [`examples/compose.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.yml), avec le fichier [`examples/.env.example`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/.env.example), si vous préférez les copier depuis la source.

```
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. Créer .env

Commencez par générer la clé de signature de session dans votre terminal, puis copiez le résultat :

```
openssl rand -hex 32
```

Si `openssl` n’est pas installé, `head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'; echo` produit une valeur équivalente sur toute machine Linux.

Créez ensuite, avec votre éditeur, un fichier `.env` à côté de `compose.yml` et renseignez vos valeurs :

```
# 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’est pas un script shell

`.env` contient de simples lignes `CLÉ=valeur` : ni `echo`, ni accolades, ni substitution `$(commande)`. Docker Compose le lit littéralement ; une commande collée dans le fichier devient donc du texte. Les guillemets sont inutiles. Excluez ce fichier du contrôle de version en l’ajoutant à `.gitignore`.

Les deux fichiers emploient volontairement une syntaxe différente : `compose.yml` est en YAML et écrit `CLÉ: valeur`, tandis que `.env` utilise le format dotenv `CLÉ=valeur`.

### 3. Démarrer HitKeep

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

Les lignes de journal `Starting HitKeep` et `HTTP server starting` indiquent que le service est démarré.

### 4. Se connecter

Ouvrez `HITKEEP_PUBLIC_URL` dans votre navigateur. L’assistant crée le premier compte, qui devient automatiquement propriétaire de l’instance, puis vous aide à ajouter votre premier site.

La base se trouve dans le volume `hitkeep_data`. Le répertoire de récupération automatique par défaut, `/var/lib/hitkeep/data/recovery`, reste donc lui aussi persistant. Les archives de rétention sont dans `hitkeep_archive` et les instantanés automatiques dans `hitkeep_backups`. Les paquets de récupération contiennent des données de base, ne suivent pas la rotation des sauvegardes et doivent être protégés puis supprimés séparément. MCP est exposé sous `/mcp`, mais les clients ont toujours besoin de jetons d’API porteur limités à leur périmètre.

MCP est facultatif dans le produit et activé dans cet exemple Compose pour les équipes qui souhaitent un accès en lecture seule à leurs assistants ou rapports. Supprimez `HITKEEP_MCP_ENABLED`, `HITKEEP_MCP_PATH` et `HITKEEP_MCP_MAX_RANGE_DAYS` si vous ne publiez pas de point de terminaison MCP.

L’enrichissement par un fournisseur d’IA est facultatif et désactivé par défaut. Conservez `HITKEEP_AI_ENABLED=false` jusqu’à avoir choisi un fournisseur et un modèle, configuré les identifiants et défini des plafonds locaux. Consultez [Recommandations d’opportunités](https://hitkeep.com/guides/analytics/opportunities/) et la [configuration des modèles d’IA](https://hitkeep.com/guides/admin/ai-model-configuration/).

La connexion sociale est facultative. Définissez l’identifiant et le secret client de chaque fournisseur voulu, puis enregistrez l’URL de rappel exacte dérivée de `HITKEEP_PUBLIC_URL`. Le guide [Connexion sociale](https://hitkeep.com/guides/security/social-sign-in/) couvre l’enregistrement, les rappels, la vérification de l’adresse e-mail, les invitations, la MFA et l’association de comptes. `HITKEEP_SOCIAL_SIGNUP_ENABLED` n’ouvre pas l’inscription publique sur une instance auto-hébergée.

Les données de ville, de fournisseur et d’ASN sont intégrées aux images publiées. Les déploiements Compose n’ont pas besoin de `IP2LOCATION_DOWNLOAD_TOKEN`.

## Vérifier le déploiement

Confirmez que Compose voit un service en cours d’exécution et que les deux sondes réussissent :

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

`/healthz` confirme que le processus est actif. `/readyz` confirme que la base partagée et toutes les bases d’espace ouvertes sont prêtes. Si HitKeep n’est accessible que par le proxy inverse, interrogez plutôt son URL visible dans le navigateur.

## Mettre à niveau

Lisez les [dernières notes de version](https://github.com/PascaleBeier/hitkeep/releases/latest) et vérifiez qu’une sauvegarde actuelle existe. Téléchargez ensuite l’image stable actuelle et recréez uniquement le service HitKeep :

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

Compose conserve les volumes nommés de données, d’archives et de sauvegardes quand il remplace le conteneur. N’exécutez pas `docker compose down -v` pendant une mise à niveau : `-v` supprime ces volumes.

## Configurer un proxy inverse

En production, placez HitKeep derrière un proxy inverse pour HTTPS. Configurez les [proxys de confiance](https://hitkeep.com/guides/installation/trusted-proxies/) afin d’utiliser les véritables adresses IP clientes pour l’analyse et la limitation de débit.

`HITKEEP_PUBLIC_URL` peut inclure un préfixe de chemin. Par exemple, utilisez `HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/` pour monter HitKeep sous un site existant. Le proxy doit publier le même préfixe, comme `/hitkeep/*`, et le transmettre au conteneur. HitKeep sert alors sous ce préfixe la base du tableau de bord, l’API, `hk.js`, `hk-vitals.js` et les points d’ingestion.

- Caddy
- nginx
- Traefik

`caddy-docker-proxy` gère automatiquement HTTPS avec Let’s Encrypt et génère sa configuration à partir des labels Docker. Utilisez de préférence un réseau d’entrée dédié et n’accordez votre confiance qu’à sa plage CIDR dans HitKeep.

```
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
```

Deux valeurs proviennent de votre terminal : le secret de session et la plage CIDR du réseau Caddy.

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

Créez ensuite le fichier `.env` dans votre éditeur :

```
# 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` doit correspondre à la plage CIDR du réseau du proxy inverse, et non à `0.0.0.0/0`.

Pour un montage dans un sous-répertoire, alignez `HITKEEP_PUBLIC_URL` et le préfixe de route du proxy. Voici la route Caddy équivalente :

```
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
}
```

Avec un nginx existant sur l’hôte, qui gère ses certificats, conservez le fichier `compose.yml` du démarrage rapide et dirigez nginx vers le port publié.

Apportez deux ajustements :

1. Dans `compose.yml`, liez le port à l’interface de bouclage afin que seul nginx local atteigne le conteneur :

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

1. Dans `.env`, définissez l’URL publique sur le domaine servi par nginx et faites confiance au réseau Docker. Le trafic de l’hôte atteint le conteneur par la passerelle Docker, située dans la plage `172.16.0.0/12` :

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

Ajoutez ensuite ce bloc serveur à 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;
  }
}
```

Rechargez nginx (`nginx -t && systemctl reload nginx`) et ouvrez `https://analytics.example.com`. Si tous les visiteurs semblent provenir de la même adresse privée, revoyez la configuration des [proxys de confiance](https://hitkeep.com/guides/installation/trusted-proxies/).

Pour une pile Traefik existante, exposez HitKeep avec des 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: {}
```

## Domaines de suivi personnalisés

Les équipes auto-hébergées peuvent utiliser les [domaines de suivi personnalisés](https://hitkeep.com/guides/tracking/custom-tracking-domains/) avec tout proxy inverse qui termine TLS et préserve l’en-tête `Host` d’origine. Utilisez le mode TLS externe quand nginx, Traefik, un répartiteur de charge ou un autre processus ACME gère les certificats. Choisissez le profil Caddy pour une intégration guidée depuis le tableau de bord avec émission de certificats à la demande.

### TLS externe avec nginx ou Traefik

Ajoutez ce paramètre HitKeep lorsque le proxy inverse gère déjà les certificats :

```
HITKEEP_CUSTOM_TRACKING_TLS_MODE: external
```

En mode externe, ajoutez chaque nom d’hôte de suivi au proxy avant que l’équipe clique sur **Vérifier** dans HitKeep. La sonde exige que `https://<hostname>/hk.js` renvoie le tracker avec un certificat valide.

Le dépôt HitKeep fournit des exemples sans 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)

L’exemple nginx limite les hôtes personnalisés aux ressources du tracker et aux routes d’ingestion. L’exemple Traefik utilise une entrée `Host(...)` exacte par nom d’hôte ; ne la remplacez pas par une règle générique, sauf si vous souhaitez accepter des noms arbitraires.

### TLS à la demande avec Caddy

Ajoutez ces paramètres au service `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:-}
```

Générez le jeton dans votre terminal avec `openssl rand -hex 32`, puis ajoutez cette ligne à `.env` :

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

Utilisez un Caddyfile avec un stockage persistant et un point de vérification restreint :

```
{
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
}
```

Caddy envoie `?domain=` à l’URL de vérification avant d’émettre un certificat. HitKeep renvoie `204` uniquement si le jeton correspond et si le nom demandé est un domaine de suivi actif dont le DNS a été vérifié. N’activez jamais le TLS à la demande sans `ask`, car tout nom d’hôte atteignant Caddy pourrait alors demander un certificat.

Le dépôt HitKeep propose un profil facultatif complet :

- [`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)

## Sauvegarder

Le démarrage rapide active le processus de sauvegarde cohérente de HitKeep et stocke les instantanés dans le volume persistant `hitkeep_backups`. Testez une restauration et copiez les sauvegardes hors de l’hôte Docker, afin qu’une panne ne détruise pas à la fois les données actives et celles de récupération. Consultez [Sauvegarde et restauration](https://hitkeep.com/guides/data/backups-and-restore/) pour l’ensemble complet des données et le processus de restauration.

### Utiliser un stockage S3 compatible pour les sauvegardes ou les archives

Les exemples ci-dessus emploient des volumes Docker locaux. Pour écrire les instantanés ou les archives de rétention dans un stockage objet, remplacez les chemins locaux par des URL `s3://` et ajoutez les paramètres S3 à `.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
```

Pour MinIO, Cloudflare R2, Backblaze B2 ou un autre point de terminaison compatible S3, définissez également `HITKEEP_S3_ENDPOINT` et, si nécessaire, `HITKEEP_S3_URL_STYLE=path`. Consultez [Sauvegardes S3](https://hitkeep.com/guides/data/s3-backups/) pour des exemples propres à chaque fournisseur.

## Résolution des problèmes

**Le tableau de bord affiche « An unexpected error occurred » pendant la configuration ou la connexion.** Procédez dans cet ordre :

1. **Lisez d’abord les journaux du conteneur** avec `docker compose logs hitkeep`. HitKeep journalise chaque erreur serveur au niveau error. Si le navigateur affiche une erreur mais que les journaux restent silencieux, la requête n’a pas atteint le conteneur : vérifiez le proxy inverse ou `HITKEEP_PUBLIC_URL`.
2. **`HITKEEP_PUBLIC_URL` doit correspondre exactement à la barre d’adresse**, schéma, hôte et port compris. Avec une URL publique en `https://`, les cookies de session sont sécurisés et la connexion en HTTP échoue silencieusement. Après avoir modifié `.env`, relancez `docker compose up -d` : Compose n’applique l’environnement qu’en recréant le conteneur.
3. **`Setup has already been completed.`** indique qu’un utilisateur existe déjà, souvent dans un volume `hitkeep_data` d’un essai précédent. `docker compose down -v` supprime les volumes nommés et repart de zéro, mais efface toutes les données d’analyse.
4. **La messagerie ne bloque pas la configuration initiale.** La création du premier compte n’envoie aucun message ; des valeurs `HITKEEP_MAIL_*` vides ne l’empêchent jamais. SMTP n’intervient qu’ensuite pour les invitations, la réinitialisation des mots de passe et les rapports.
5. **Besoin de plus de détails ?** Ajoutez `HITKEEP_LOG_LEVEL: debug` sous `environment:` dans `compose.yml`, puis relancez `docker compose up -d`.

## Ressources associées

- [Proxys de confiance](https://hitkeep.com/guides/installation/trusted-proxies/)
- [Connexion sociale](https://hitkeep.com/guides/security/social-sign-in/)
- [Domaines de suivi personnalisés](https://hitkeep.com/guides/tracking/custom-tracking-domains/)
- [Référence de configuration](https://hitkeep.com/reference/configuration/)
- [Conservation des données](https://hitkeep.com/guides/data/retention/)
- [Sauvegardes S3](https://hitkeep.com/guides/data/s3-backups/)
- [Installation binaire](https://hitkeep.com/fr/guides/installation/binary/)

Vous recherchez un hébergement géré avec un choix explicite de région ? [Comparez HitKeep Cloud](https://hitkeep.com/fr/pricing/) : HitKeep est exploité dans la région gérée de votre choix, UE (Francfort) ou États-Unis (Virginie).

[Précédent Binaire Linux](https://hitkeep.com/fr/guides/installation/binary/)[Suivant Kubernetes et Helm](https://hitkeep.com/fr/guides/installation/kubernetes/)
