HitKeep mit Docker Compose selbst hosten
Docker Compose bietet dir eine reproduzierbare, versionierbare Bereitstellung mit persistenten Speicher-Volumes. Deine Analysedaten verbleiben in einem benannten Docker-Volume auf deinem Server, einschließlich der gemeinsamen hitkeep.db und aller mandantenlokalen Datenbanken unter tenants/*/hitkeep.db.
Diese Seite beschreibt HitKeep als selbst gehosteten Dienst. Für die Hot-Reload-Entwicklungsumgebung mit Go, Air, Angular, Mailpit und vorbereiteten Demo-Daten in Docker nutze die Anleitung zum Mitwirken.
HitKeep-Images werden mit jedem Release in zwei Registries veröffentlicht:
| Registry | Image |
|---|---|
| Docker Hub | pascalebeier/hitkeep |
| GitHub Container Registry | ghcr.io/pascalebeier/hitkeep |
Beide Registries enthalten identische plattformübergreifende Images (linux/amd64, linux/arm64) mit signierten Provenienz-Attestierungen. Wähle die Registry passend zu deinen Netzwerk- oder Pull-Rate-Anforderungen.
Schnellstart
Abschnitt betitelt „Schnellstart“Eine Bereitstellung besteht aus zwei Dateien in einem Verzeichnis: compose.yml (unverändert kopieren) und .env (hier stehen deine Werte). Compose ersetzt beim Start jedes ${VARIABLE} in compose.yml durch die entsprechende Zeile aus .env.
1. compose.yml erstellen
Abschnitt betitelt „1. compose.yml erstellen“Erstelle ein Verzeichnis und füge diese compose.yml hinzu. Diese Basiskonfiguration speichert Live-Daten, Aufbewahrungsarchive und automatische Backup-Snapshots in getrennten benannten Volumes. Dieselbe Datei wird im Repository als examples/compose.yml gepflegt, zusammen mit examples/.env.example, falls du lieber die Quelldateien kopierst.
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. .env erstellen
Abschnitt betitelt „2. .env erstellen“Erzeuge zuerst den Signaturschlüssel für Sitzungen. Führe diesen Befehl in deinem Terminal aus und kopiere die Ausgabe:
openssl rand -hex 32Falls openssl nicht installiert ist, erzeugt head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n'; echo auf jedem Linux-System einen gleichwertigen Wert.
Erstelle anschließend neben compose.yml mit deinem Editor eine Datei namens .env und trage deine Werte ein:
# 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. HitKeep starten
Abschnitt betitelt „3. HitKeep starten“docker compose up -ddocker compose logs -f hitkeepDie Logzeilen Starting HitKeep und HTTP server starting zeigen, dass der Dienst läuft.
4. Anmelden
Abschnitt betitelt „4. Anmelden“Öffne HITKEEP_PUBLIC_URL im Browser. Der Einrichtungsassistent erstellt das erste Konto, macht es automatisch zum Instanzbesitzer und führt dich durch das Hinzufügen deiner ersten Website.
Die Datenbankdatei liegt im Volume hitkeep_data. Damit bleibt auch das Standardverzeichnis für automatische Wiederherstellung, /var/lib/hitkeep/data/recovery, persistent. Aufbewahrungsarchive liegen in hitkeep_archive, automatische Datenbank-Snapshots in hitkeep_backups. Wiederherstellungspakete enthalten Datenbankmaterial, werden nicht über die Backup-Aufbewahrung rotiert und müssen separat geschützt und gelöscht werden. MCP ist unter /mcp erreichbar, Clients benötigen dennoch bereichsgebundene API-Client-Bearer-Token.
MCP ist im Produkt optional und in diesem Compose-Beispiel für Teams aktiviert, die schreibgeschützten Assistenten- oder Reporting-Zugriff wünschen. Entferne HITKEEP_MCP_ENABLED, HITKEEP_MCP_PATH und HITKEEP_MCP_MAX_RANGE_DAYS, wenn du keinen MCP-Endpunkt veröffentlichen möchtest.
KI-Provider-Anreicherung ist optional und standardmäßig deaktiviert. Belasse HITKEEP_AI_ENABLED=false, bis du Provider und Modell gewählt, Zugangsdaten konfiguriert und lokale Budgetgrenzen gesetzt hast. Die genauen Felder stehen unter Opportunity-Empfehlungen und in der Anleitung zur KI-Modellkonfiguration.
Social Sign-in ist optional. Setze Client-ID und Client-Secret für jeden gewünschten Provider und registriere anschließend die exakte Callback-URL, die sich aus HITKEEP_PUBLIC_URL ergibt. Die Anleitung zu Social Sign-in behandelt Provider-Registrierung, Callback-Pfade, E-Mail-Verifizierung, Einladungen, MFA und Kontoverknüpfung. HITKEEP_SOCIAL_SIGNUP_ENABLED öffnet keine öffentliche Registrierung auf einer selbst gehosteten Instanz.
Daten für Stadt-, Provider- und ASN-Erkennung sind in Release-Images eingebettet. Laufende Compose-Bereitstellungen benötigen kein IP2LOCATION_DOWNLOAD_TOKEN.
Installation prüfen
Abschnitt betitelt „Installation prüfen“Prüfe, ob Compose einen laufenden Dienst sieht und beide Laufzeitprüfungen erfolgreich sind:
docker compose pscurl --fail http://localhost:8080/healthzcurl --fail http://localhost:8080/readyzdocker compose logs --since=5m hitkeep/healthz bestätigt, dass der Prozess läuft. /readyz bestätigt, dass die gemeinsame Datenbank und jede geöffnete Mandantendatenbank bereit sind. Falls HitKeep nur über deinen Reverse Proxy erreichbar ist, prüfe stattdessen dessen im Browser sichtbare URL.
Upgrade
Abschnitt betitelt „Upgrade“Lies die aktuellen Release Notes und stelle sicher, dass ein aktuelles Backup vorhanden ist. Lade anschließend das aktuelle stabile Image und erstelle ausschließlich den HitKeep-Dienst neu:
docker compose pull hitkeepdocker compose up -d hitkeepdocker compose pscurl --fail http://localhost:8080/readyzCompose behält die benannten Daten-, Archiv- und Backup-Volumes, wenn der Container ersetzt wird. Führe während eines Upgrades niemals docker compose down -v aus; -v löscht diese Volumes.
Reverse-Proxy-Konfigurationen
Abschnitt betitelt „Reverse-Proxy-Konfigurationen“Betreibe HitKeep für produktives HTTPS hinter einem Reverse Proxy. Konfiguriere vertrauenswürdige Proxys, damit echte Client-IPs für Webanalyse und Ratenbegrenzung genutzt werden.
HITKEEP_PUBLIC_URL darf ein Pfadpräfix enthalten. Setze beispielsweise HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/, wenn HitKeep unterhalb einer bestehenden Website eingebunden wird. Der Proxy muss dasselbe Präfix wie /hitkeep/* veröffentlichen und an den HitKeep-Container weiterleiten. HitKeep stellt dann Dashboard-Basis-Href, API-Anfragen, hk.js, hk-vitals.js und Ingest-Endpunkte unter diesem Präfix bereit.
caddy-docker-proxy übernimmt automatisches HTTPS mit Let’s Encrypt und erzeugt die Caddy-Konfiguration direkt aus Docker-Labels.
Als bewährte Praxis solltest du ein eigenes Ingress-Netzwerk verwenden und in HitKeep ausschließlich dessen CIDR vertrauen.
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: trueZwei Werte kommen aus deinem Terminal: das Sitzungsgeheimnis und die CIDR des Caddy-Netzwerks:
openssl rand -hex 32docker network inspect caddy --format '{{(index .IPAM.Config 0).Subnet}}'Erstelle anschließend die .env-Datei mit deinem Editor:
# Required. Paste the generated 64-character hex string here.HITKEEP_JWT_SECRET=paste-the-generated-value-hereHITKEEP_PUBLIC_URL=https://analytics.example.comHITKEEP_HOSTNAME=analytics.example.comCADDY_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=commonHITKEEP_MAIL_HOST=smtp.example.comHITKEEP_MAIL_PORT=587HITKEEP_MAIL_USERNAME=postmaster@example.comHITKEEP_MAIL_PASSWORD=change-meHITKEEP_MAIL_FROM_ADDRESS=analytics@example.comHITKEEP_MAIL_FROM_NAME=HitKeepHITKEEP_TRUSTED_PROXIES muss der CIDR deines Reverse-Proxy-Netzwerks entsprechen, nicht 0.0.0.0/0.
Halte bei einer Einbindung unter einem Unterverzeichnis HITKEEP_PUBLIC_URL und das Routenpräfix des Reverse Proxys synchron. Die entsprechende Caddy-Route lautet:
HITKEEP_PUBLIC_URL=https://www.example.net/hitkeep/HITKEEP_HOSTNAME=www.example.netwww.example.net {handle /hitkeep* { reverse_proxy hitkeep:8080}encode zstd gzip}Bei einem bestehenden nginx auf dem Host, der seine Zertifikate etwa mit certbot selbst verwaltet, behältst du die compose.yml aus dem Schnellstart und leitest nginx an den veröffentlichten Port weiter.
Passe die Schnellstartdateien an zwei Stellen an:
- Binde den Port in
compose.ymlan Loopback, damit nur der lokale nginx den Container erreichen kann:
ports: - "127.0.0.1:8080:8080"- Setze in
.envdie öffentliche URL auf die von nginx bereitgestellte Domain und vertraue dem Docker-Netzwerk. Host-Datenverkehr erreicht den Container über das Docker-Netzwerk-Gateway im Bereich172.16.0.0/12:
HITKEEP_PUBLIC_URL=https://analytics.example.comHITKEEP_TRUSTED_PROXIES=172.16.0.0/12Füge nginx anschließend einen Server-Block hinzu:
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; }}Lade nginx neu (nginx -t && systemctl reload nginx) und öffne https://analytics.example.com. Wenn alle Besucher von derselben privaten IP zu kommen scheinen, prüfe erneut die vertrauenswürdigen Proxys.
Veröffentliche HitKeep in bestehenden Traefik-Stacks über 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: {}Eigene Tracking-Domains
Abschnitt betitelt „Eigene Tracking-Domains“Selbst gehostete Teams können eigene Tracking-Domains mit jedem Reverse Proxy nutzen, der TLS terminiert und den ursprünglichen Host-Header erhält. Nutze den externen TLS-Modus, wenn Zertifikate von nginx, Traefik, einem Load Balancer oder einem anderen ACME-Prozess verwaltet werden. Nutze das Caddy-Profil nur, wenn du über das Dashboard geführtes Domain-Onboarding mit On-Demand-Zertifikaten wünschst.
Externes TLS mit nginx oder Traefik
Abschnitt betitelt „Externes TLS mit nginx oder Traefik“Ergänze diese HitKeep-Einstellung, wenn der Reverse Proxy bereits Zertifikate verwaltet:
HITKEEP_CUSTOM_TRACKING_TLS_MODE: externalFüge im externen Modus jeden Tracking-Hostnamen zum Proxy hinzu, bevor das Team in HitKeep auf Verify klickt. Die Verifizierungsprüfung verlangt, dass https://<hostname>/hk.js den Tracker mit einem gültigen Zertifikat ausliefert.
Das HitKeep-Repository enthält Beispiele ohne Caddy:
examples/nginx.custom-tracking.confexamples/compose.nginx-custom-tracking.ymlexamples/traefik.custom-tracking.ymlexamples/compose.traefik-custom-tracking.yml
Das nginx-Beispiel beschränkt eigene Tracking-Hosts bereits am Proxy auf Tracker-Assets und Ingest-Routen. Das Traefik-Beispiel verwendet exakte Host(...)-Einträge für jeden Tracking-Hostnamen. Ersetze sie nur dann durch eine Catch-all-Regel, wenn der Proxy bewusst beliebige Hostnamen akzeptieren soll.
Caddy On-Demand-TLS
Abschnitt betitelt „Caddy On-Demand-TLS“Ergänze diese HitKeep-Einstellungen im Dienst 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:-}Erzeuge das Ask-Token im Terminal (openssl rand -hex 32) und füge es als neue Zeile in .env ein:
HITKEEP_CADDY_TLS_ASK_TOKEN=paste-the-generated-value-hereNutze ein Caddyfile mit persistentem Speicher und einem eingeschränkten On-Demand-TLS-Ask-Endpunkt:
{email ops@example.comstorage 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:8080encode 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 sendet ?domain= an die Ask-URL, bevor es ein Zertifikat ausstellt. HitKeep antwortet nur dann mit 204, wenn das Token stimmt und der angefragte Hostname eine aktivierte, per DNS verifizierte eigene Tracking-Domain ist. Betreibe Caddy On-Demand-TLS niemals ohne ask; andernfalls kann jeder Hostname, der den Caddy-Listener erreicht, eine Zertifikatsausstellung versuchen.
Das HitKeep-Repository enthält ein vollständiges optionales Profil:
Der Schnellstart aktiviert HitKeeps Worker für konsistente Checkpoint-Backups und speichert Snapshots im persistenten Volume hitkeep_backups. Teste eine Wiederherstellung, bevor du dich darauf verlässt, und kopiere Backups vom Docker-Host weg, damit ein Hostausfall nicht Live- und Wiederherstellungsdaten zugleich entfernt. Backups und Wiederherstellung beschreibt den vollständigen Datensatz und Ablauf.
S3-kompatible Backups oder Archive nutzen
Abschnitt betitelt „S3-kompatible Backups oder Archive nutzen“Die Beispiele oben verwenden lokale Docker-Volumes. Um Backup-Snapshots oder Aufbewahrungsarchive in Objektspeicher zu schreiben, ersetze die lokalen Pfade durch s3://-URLs und ergänze die S3-Einstellungen in .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-meSetze für MinIO, Cloudflare R2, Backblaze B2 oder einen anderen S3-kompatiblen Endpunkt zusätzlich HITKEEP_S3_ENDPOINT und bei Bedarf HITKEEP_S3_URL_STYLE=path. Unter S3-Backups findest du providerspezifische Beispiele.
Fehlerbehebung
Abschnitt betitelt „Fehlerbehebung“Das Dashboard zeigt während Einrichtung oder Anmeldung „An unexpected error occurred“ an. Prüfe nacheinander:
- Zuerst Container-Logs lesen:
docker compose logs hitkeep. HitKeep protokolliert jeden serverseitigen Fehler auf Error-Level. Zeigt der Browser einen Fehler, während die Logs leer bleiben, hat die Anfrage den Container nie erreicht. Ursache ist dann der Reverse Proxy oder eine falscheHITKEEP_PUBLIC_URL, nicht HitKeep. HITKEEP_PUBLIC_URLmuss exakt der Adressleiste entsprechen – Schema, Host und Port. Bei einer öffentlichenhttps://-URL erhalten Sitzungscookies das Secure-Attribut; eine Anmeldung über reines HTTP schlägt dann still fehl. Führe nach einer Änderung an.enverneutdocker compose up -daus, weil Compose Umgebungsänderungen erst beim Neuerstellen des Containers übernimmt.Setup has already been completed.bedeutet, dass bereits ein Benutzer in der Datenbank existiert – meist in einemhitkeep_data-Volume aus einem früheren Versuch.docker compose down -ventfernt die benannten Volumes und ermöglicht einen sauberen Neustart. Dabei werden alle Analysedaten gelöscht.- E-Mail-Einstellungen sind bei der Einrichtung nicht die Ursache. Beim Erstellen des ersten Kontos wird keine E-Mail gesendet; leere
HITKEEP_MAIL_*-Werte blockieren den Vorgang nie. SMTP wird erst für Einladungen, Passwortzurücksetzungen und E-Mail-Berichte benötigt. - Mehr Details benötigt? Ergänze
HITKEEP_LOG_LEVEL: debugunterenvironment:incompose.ymlund führe erneutdocker compose up -daus.
Verwandte Themen
Abschnitt betitelt „Verwandte Themen“- Vertrauenswürdige Proxys
- Social Sign-in
- Eigene Tracking-Domains
- Konfigurationsreferenz
- Datenaufbewahrung
- S3-Backups
- Installation als Binärdatei
Du möchtest verwaltetes Hosting mit ausdrücklicher Regionswahl? HitKeep Cloud vergleichen.