Salta ai contenuti
Inizia gratis in Cloud

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.

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

RegistryImmagine
Docker Hubpascalebeier/hitkeep
GitHub Container Registryghcr.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.

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.

La configurazione seguente mantiene dati attivi, archivi di conservazione e snapshot automatici in volumi separati. Lo stesso file è disponibile come examples/compose.yml, con 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: {}

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

Finestra del terminale
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
Finestra del terminale
docker compose up -d
docker compose logs -f hitkeep

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

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 e la configurazione del modello AI.

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

Finestra del terminale
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.

Leggi le ultime note di rilascio e verifica che esista un backup recente. Poi scarica l’immagine stabile e ricrea solo il servizio HitKeep:

Finestra del terminale
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.

In produzione, esegui HitKeep dietro un reverse proxy HTTPS. Configura i proxy attendibili 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-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.

Finestra del terminale
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
}

I team self-hosted possono usare domini di tracciamento personalizzati 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.

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:

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.

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.

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.

Per usare object storage, sostituisci i percorsi locali con URL s3:// e aggiungi a .env:

Finestra del terminale
# 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.

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.

Ti serve hosting gestito con scelta esplicita della regione? Confronta HitKeep Cloud per hosting UE (Francoforte) o Stati Uniti (Virginia) senza gestire container, aggiornamenti o backup.