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:
| 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.
Avvio rapido
Sezione intitolata “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
Sezione intitolata “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, 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: {}2. Crea .env
Sezione intitolata “2. Crea .env”Genera la chiave di firma delle sessioni nel terminale e copia il risultato:
openssl rand -hex 32Se 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.comHITKEEP_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=587HITKEEP_MAIL_USERNAME=HITKEEP_MAIL_PASSWORD=HITKEEP_MAIL_FROM_ADDRESS=hitkeep@localhostHITKEEP_MAIL_FROM_NAME=HitKeep3. Avvia HitKeep
Sezione intitolata “3. Avvia HitKeep”docker compose up -ddocker compose logs -f hitkeepLe righe di log Starting HitKeep e HTTP server starting indicano che il servizio è attivo.
4. Accedi
Sezione intitolata “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 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.
Verifica
Sezione intitolata “Verifica”docker compose pscurl --fail http://localhost:8080/healthzcurl --fail http://localhost:8080/readyzdocker 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
Sezione intitolata “Aggiornamento”Leggi le ultime note di rilascio e verifica che esista un backup recente. Poi scarica l’immagine stabile e ricrea solo il servizio HitKeep:
docker compose pull hitkeepdocker compose up -d hitkeepdocker compose pscurl --fail http://localhost:8080/readyzCompose conserva i volumi nominati quando sostituisce il container. Non eseguire docker compose down -v durante un aggiornamento: -v elimina i volumi.
Configurazioni reverse proxy
Sezione intitolata “Configurazioni reverse proxy”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.
openssl rand -hex 32docker 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.comHITKEEP_TRUSTED_PROXIES=172.16.0.0/12Configura 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.
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
Sezione intitolata “Domini di tracciamento personalizzati”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.
TLS esterno con nginx o Traefik
Sezione intitolata “TLS esterno con nginx o Traefik”Aggiungi:
HITKEEP_CUSTOM_TRACKING_TLS_MODE: externalPrima 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.confexamples/compose.nginx-custom-tracking.ymlexamples/traefik.custom-tracking.ymlexamples/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
Sezione intitolata “TLS on-demand con Caddy”Aggiungi al servizio HitKeep:
HITKEEP_CUSTOM_TRACKING_TLS_MODE: caddy-on-demandHITKEEP_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-hereConfigura 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.
Backup o archivi compatibili con S3
Sezione intitolata “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/archiveHITKEEP_S3_REGION=eu-central-1# Static credentials are optional when your container runtime provides an AWS credential chain.HITKEEP_S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLEHITKEEP_S3_SECRET_ACCESS_KEY=change-mePer 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.
Risoluzione dei problemi
Sezione intitolata “Risoluzione dei problemi”La dashboard mostra “An unexpected error occurred” durante la configurazione o l’accesso.
- 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 eHITKEEP_PUBLIC_URL. HITKEEP_PUBLIC_URLdeve coincidere esattamente con la barra degli indirizzi, inclusi schema, host e porta. Con un URLhttps://, i cookie sono secure e l’accesso via HTTP fallisce. Dopo modifiche a.env, esegui di nuovodocker compose up -d.Setup has already been completed.indica che esiste già un utente, spesso in un vecchio volumehitkeep_data.docker compose down -vazzera i volumi, eliminando tutti i dati analytics.- Le impostazioni email non bloccano la creazione del primo account. SMTP serve in seguito per inviti, reset password e report.
- Per maggiori dettagli aggiungi
HITKEEP_LOG_LEVEL: debugsottoenvironment:e ricrea il container.
Pagine correlate
Sezione intitolata “Pagine correlate”- Proxy attendibili
- Accesso social
- Domini di tracciamento personalizzati
- Riferimento di configurazione
- Conservazione dei dati
- Backup S3
- Installazione binaria
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.