---
title: "Ospitare HitKeep con Docker Compose | HitKeep"
description: "Ospita HitKeep con Docker Compose, storage persistente, rete preconfigurata ed esempi di reverse proxy per Caddy, nginx e Traefik."
canonical: "https://hitkeep.com/it/guides/installation/docker-compose/"
---

# Ospitare HitKeep con Docker Compose

Docker Compose offre una distribuzione riproducibile e versionabile con volumi persistenti. I dati analytics restano in un volume Docker nominato sul tuo server, incluso il database condiviso `hitkeep.db` e gli eventuali database dei tenant in `tenants/*/hitkeep.db`.

Questa pagina riguarda l’esecuzione di HitKeep come servizio self-hosted. Per l’ambiente contributor con hot reload, Go, Air, Angular, Mailpit e dati demo in Docker, usa la [guida per contribuire](https://hitkeep.com/guides/contributing/).

Le immagini HitKeep vengono pubblicate in due registry a ogni release:

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

Entrambi contengono le stesse immagini multipiattaforma (`linux/amd64`, `linux/arm64`) con attestazioni di provenienza firmate. Scegli il registry più adatto alla tua rete o ai limiti di pull.

Non inserire segreti nei file Compose

Passa i valori sensibili (`HITKEEP_JWT_SECRET`, password SMTP) tramite variabili d’ambiente, un file `.env` o Docker secrets, non nel `compose.yml` o nei flag. Escludi `.env` dal controllo versione. Per requisiti più rigorosi usa Docker secrets.

## Avvio rapido

La distribuzione usa due file nella stessa directory: `compose.yml`, da copiare senza modificarlo, e `.env`, che contiene i tuoi valori. All’avvio Compose sostituisce ogni `${VARIABLE}` con la riga corrispondente di `.env`.

### 1. Crea compose.yml

La configurazione seguente mantiene dati attivi, archivi di conservazione e snapshot automatici in volumi separati. Lo stesso file è disponibile come [`examples/compose.yml`](https://github.com/PascaleBeier/hitkeep/blob/main/examples/compose.yml), con [`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. Crea .env

Genera la chiave di firma delle sessioni nel terminale e copia il risultato:

```
openssl rand -hex 32
```

Se `openssl` non è installato, `head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'; echo` genera un valore equivalente su Linux.

Crea quindi `.env` accanto a `compose.yml`:

```
# 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 non è uno script di shell

`.env` contiene righe semplici `KEY=value`: niente `echo`, parentesi graffe o sostituzioni `$(command)`. Docker Compose lo legge letteralmente. Le virgolette non sono necessarie. Aggiungi il file a `.gitignore`.

I due file usano volutamente sintassi diverse: in `compose.yml`, YAML usa `KEY: value`; `.env` usa il formato dotenv `KEY=value`.

### 3. Avvia HitKeep

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

Le righe di log `Starting HitKeep` e `HTTP server starting` indicano che il servizio è attivo.

### 4. Accedi

Apri `HITKEEP_PUBLIC_URL` nel browser. La procedura guidata crea il primo account, che diventa automaticamente proprietario dell’istanza, e ti accompagna nell’aggiunta del primo sito.

Il database si trova nel volume `hitkeep_data`; anche la directory di recupero automatico `/var/lib/hitkeep/data/recovery` è persistente. Gli archivi di conservazione sono in `hitkeep_archive` e gli snapshot automatici in `hitkeep_backups`. I bundle di recupero contengono materiale del database, non seguono la rotazione dei backup e vanno protetti e rimossi separatamente. MCP è esposto su `/mcp`, ma richiede comunque token bearer API con ambito limitato.

MCP è opzionale ed è abilitato nell’esempio per i team che desiderano accesso di sola lettura per assistenti e report. Rimuovi `HITKEEP_MCP_ENABLED`, `HITKEEP_MCP_PATH` e `HITKEEP_MCP_MAX_RANGE_DAYS` se non intendi pubblicarlo.

L’arricchimento tramite provider AI è opzionale e disabilitato per impostazione predefinita. Mantieni `HITKEEP_AI_ENABLED=false` finché non hai scelto provider e modello, configurato le credenziali e impostato limiti di budget locali. Consulta [Raccomandazioni Opportunity](https://hitkeep.com/guides/analytics/opportunities/) e la [configurazione del modello AI](https://hitkeep.com/guides/admin/ai-model-configuration/).

L’accesso social è opzionale. Imposta ID client e segreto per ogni provider e registra l’esatto callback derivato da `HITKEEP_PUBLIC_URL`. La [guida all’accesso social](https://hitkeep.com/guides/security/social-sign-in/) descrive provider, callback, verifica email, inviti, MFA e collegamento account. `HITKEEP_SOCIAL_SIGNUP_ENABLED` non abilita la registrazione pubblica su un’istanza self-hosted.

I dati per città, provider e ASN sono integrati nelle immagini di release. Le distribuzioni Compose non richiedono `IP2LOCATION_DOWNLOAD_TOKEN`.

## Verifica

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

`/healthz` conferma che il processo è attivo. `/readyz` conferma la disponibilità del database condiviso e di ogni database tenant aperto. Se HitKeep è raggiungibile solo dal reverse proxy, usa l’URL visibile nel browser.

## Aggiornamento

Leggi le [ultime note di rilascio](https://github.com/PascaleBeier/hitkeep/releases/latest) e verifica che esista un backup recente. Poi scarica l’immagine stabile e ricrea solo il servizio HitKeep:

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

Compose conserva i volumi nominati quando sostituisce il container. Non eseguire `docker compose down -v` durante un aggiornamento: `-v` elimina i volumi.

## Configurazioni reverse proxy

In produzione, esegui HitKeep dietro un reverse proxy HTTPS. Configura i [proxy attendibili](https://hitkeep.com/guides/installation/trusted-proxies/) affinché analytics e rate limiting usino gli IP reali.

`HITKEEP_PUBLIC_URL` può includere un prefisso, per esempio `https://www.example.net/hitkeep/`. Il proxy deve pubblicare lo stesso prefisso, come `/hitkeep/*`, e inoltrarlo al container. Dashboard, API, `hk.js`, `hk-vitals.js` ed endpoint di ingestione vengono così serviti sotto quel prefisso.

- Caddy
- nginx
- Traefik

`caddy-docker-proxy` gestisce HTTPS automatico e genera la configurazione dalle label Docker. Usa una rete ingress dedicata e rendi attendibile in HitKeep solo il relativo CIDR.

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

Imposta nel servizio HitKeep `HITKEEP_PUBLIC_URL`, `HITKEEP_JWT_SECRET` e il CIDR restituito come `HITKEEP_TRUSTED_PROXIES`. Le label minime sono:

```
labels:
caddy: ${HITKEEP_HOSTNAME:?set in .env}
caddy.reverse_proxy: "{{upstreams 8080}}"
caddy.encode: "zstd gzip"
```

Per una sottodirectory, mantieni allineati URL pubblico e route:

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

Con nginx sull’host, associa la porta del container al loopback:

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

Imposta in `.env`:

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

Configura quindi 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;
  }
}
```

Ricarica nginx con `nginx -t && systemctl reload nginx`. Se tutti i visitatori sembrano provenire dallo stesso IP privato, ricontrolla i [proxy attendibili](https://hitkeep.com/guides/installation/trusted-proxies/).

Per stack Traefik esistenti, collega HitKeep alla rete del proxy e applica queste label:

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

Imposta `HITKEEP_PUBLIC_URL`, `HITKEEP_JWT_SECRET` e `HITKEEP_TRUSTED_PROXIES` sul CIDR della rete Traefik, insieme agli stessi volumi e percorsi dell’avvio rapido.

## Domini di tracciamento personalizzati

I team self-hosted possono usare [domini di tracciamento personalizzati](https://hitkeep.com/guides/tracking/custom-tracking-domains/) con qualsiasi reverse proxy che termina TLS e preserva l’header `Host`. Usa la modalità TLS esterna quando nginx, Traefik, un load balancer o un altro processo ACME gestisce i certificati; usa il profilo Caddy solo per l’emissione on-demand dalla dashboard.

### TLS esterno con nginx o Traefik

Aggiungi:

```
HITKEEP_CUSTOM_TRACKING_TLS_MODE: external
```

Prima di fare clic su **Verify**, aggiungi ogni hostname al proxy. La verifica richiede che `https://<hostname>/hk.js` risponda con il tracker e un certificato valido. Gli esempi ufficiali sono:

- [`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’esempio nginx limita gli host alle risorse del tracker e alle route di ingestione; quello Traefik usa voci `Host(...)` esatte. Non sostituirle con una regola catch-all se non vuoi accettare hostname arbitrari.

### TLS on-demand con Caddy

Aggiungi al servizio 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:-}
```

Genera il token con `openssl rand -hex 32` e aggiungilo a `.env`:

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

Configura Caddy con un endpoint ask limitato. HitKeep restituisce `204` solo se il token coincide e l’hostname richiesto è un dominio di tracciamento abilitato e verificato via DNS. Non abilitare TLS on-demand senza `ask`, altrimenti ogni hostname che raggiunge il listener può tentare l’emissione di un certificato.

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

L’avvio rapido abilita il worker di backup con checkpoint e salva gli snapshot nel volume persistente `hitkeep_backups`. Prova un ripristino e copia i backup fuori dall’host Docker, così un guasto non elimina dati attivi e dati di recupero. Consulta [Backup e ripristino](https://hitkeep.com/guides/data/backups-and-restore/).

### Backup o archivi compatibili con S3

Per usare object storage, sostituisci i percorsi locali con URL `s3://` e aggiungi a `.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
```

Per MinIO, Cloudflare R2, Backblaze B2 o altri endpoint compatibili imposta anche `HITKEEP_S3_ENDPOINT` e, se necessario, `HITKEEP_S3_URL_STYLE=path`. Consulta [Backup S3](https://hitkeep.com/guides/data/s3-backups/).

## Risoluzione dei problemi

**La dashboard mostra “An unexpected error occurred” durante la configurazione o l’accesso.**

1. Leggi prima i log: `docker compose logs hitkeep`. Se il browser mostra un errore ma i log restano vuoti, la richiesta non ha raggiunto il container: controlla reverse proxy e `HITKEEP_PUBLIC_URL`.
2. `HITKEEP_PUBLIC_URL` deve coincidere esattamente con la barra degli indirizzi, inclusi schema, host e porta. Con un URL `https://`, i cookie sono secure e l’accesso via HTTP fallisce. Dopo modifiche a `.env`, esegui di nuovo `docker compose up -d`.
3. `Setup has already been completed.` indica che esiste già un utente, spesso in un vecchio volume `hitkeep_data`. `docker compose down -v` azzera i volumi, eliminando tutti i dati analytics.
4. Le impostazioni email non bloccano la creazione del primo account. SMTP serve in seguito per inviti, reset password e report.
5. Per maggiori dettagli aggiungi `HITKEEP_LOG_LEVEL: debug` sotto `environment:` e ricrea il container.

## Pagine correlate

- [Proxy attendibili](https://hitkeep.com/guides/installation/trusted-proxies/)
- [Accesso social](https://hitkeep.com/guides/security/social-sign-in/)
- [Domini di tracciamento personalizzati](https://hitkeep.com/guides/tracking/custom-tracking-domains/)
- [Riferimento di configurazione](https://hitkeep.com/reference/configuration/)
- [Conservazione dei dati](https://hitkeep.com/guides/data/retention/)
- [Backup S3](https://hitkeep.com/guides/data/s3-backups/)
- [Installazione binaria](https://hitkeep.com/it/guides/installation/binary/)

Ti serve hosting gestito con scelta esplicita della regione? [Confronta HitKeep Cloud](https://hitkeep.com/it/pricing/) per hosting UE (Francoforte) o Stati Uniti (Virginia) senza gestire container, aggiornamenti o backup.

[Indietro Binario Linux](https://hitkeep.com/it/guides/installation/binary/)[Avanti Kubernetes e Helm](https://hitkeep.com/it/guides/installation/kubernetes/)
