Zum Inhalt springen
Serverküche
Suche

Die Suche wird geladen … (nur in der veröffentlichten Seite verfügbar).

Anwendungen Schwierigkeit: Fortgeschritten

HitKeep: datenschutzfreundliche Web-Analytics selbst hosten

HitKeep mit Docker und Traefik aufsetzen: cookielose, DSGVO-freundliche Website-Statistik auf dem eigenen Server – mit Tracking-Code und Backups.

· 10 Min. Lesezeit ·Dauer: ca. 30 Minuten
Inhaltsverzeichnis

Google Analytics kennt jeder – und genau das ist das Problem: Es schickt die Daten deiner Besucher zu Google, verlangt einen Cookie-Banner und macht dich erklärungspflichtig. HitKeep dreht das um: cookielose Web-Analytics auf deinem Server, unter deiner Domain, ohne dass je ein Byte an Dritte geht.

Was bauen wir?

Am Ende läuft HitKeep 2.13.18 als einzelner Container hinter deinem Traefik, erreichbar unter https://DEINE_DOMAIN. Du bekommst ein Dashboard mit Seitenaufrufen, Besuchern, Verweildauer, Referrern und Geräten – gespeist von einem winzigen JavaScript-Snippet, das du in deine Website einbaust. HitKeep arbeitet cookielos (kein Consent-Banner nötig) und speichert alles lokal in einer eingebetteten DuckDB-Datenbank. Das Image ist ein Distroless-Image (rund 68 MB Download, entpackt gut 230 MB auf der Platte), das komplett ohne externe Datenbank auskommt – ideal für einen kleinen VPS.

Hinweis

HitKeep ist „cookielos", weil es Besucher über einen täglich wechselnden Hash statt über einen gesetzten Cookie wiedererkennt. Das ist deutlich datenschutzfreundlicher als klassisches Tracking, ersetzt aber keine rechtliche Beratung. Ob du komplett ohne Einwilligung auskommst, hängt von deinem konkreten Einsatz ab – im Zweifel mit einem Datenschutzbeauftragten klären.

Voraussetzungen

  • Ein Server mit Debian 13 und laufendem Docker (getestet auf einem netcup VPS).
  • Ein Reverse Proxy mit Traefik, der TLS-Zertifikate per Let’s Encrypt holt. HitKeep bringt keinen eigenen HTTPS-Server mit – Traefik übernimmt die Verschlüsselung. Dieses Tutorial setzt das dort beschriebene proxy-Netz und den Resolver le voraus.
  • Eine (Sub-)Domain, die auf deinen Server zeigt (A-/AAAA-Record). Wir nutzen im Beispiel DEINE_DOMAIN.
  • Die Website, die du messen willst – HitKeep misst jede Seite, in die du das Snippet einbaust.
🍳 Empfehlung Anzeige

VPS 1000 G12.5

4 vCore · 8 GB RAM · 128 GB SSD

ab 14,50 €/Monat

Ein einzelner Container mit eingebetteter DuckDB – der kleinste vServer reicht dafür locker.

Zu netcup →

💶 1 Monat gratis:

Einmal einlösbar, gilt für VPS 1000 G12.5. Im leeren Warenkorb einlösen – der Code legt den Server selbst hinein. Im Warenkorb einlösen →

💶 5 € Gutschein für netcup-Neukunden: immer gültig · nicht für Domains und VPS Lite

Alle netcup-Gutscheine →

Schritt für Schritt

Schritt 1: JWT-Secret erzeugen

HitKeep signiert die Login-Sitzungen mit einem geheimen Schlüssel. Erzeuge dir einen zufälligen 32-Byte-Wert – nicht ausdenken, sondern generieren:

Terminal
openssl rand -hex 32

Du bekommst eine 64 Zeichen lange Hex-Zeichenkette. Kopiere sie – sie kommt gleich in die Konfiguration. Ändert sich dieses Secret später, werden alle offenen Logins ungültig; halte es also stabil und geheim.

Schritt 2: Compose-Datei anlegen

Lege einen Ordner für den Stack an und wechsle hinein:

Terminal
mkdir -p /opt/hitkeep && cd /opt/hitkeep

Erstelle die Datei compose.yaml. Ersetze DEINE_DOMAIN durch deine echte Domain und DEIN_JWT_SECRET durch den Wert aus Schritt 1:

YAML
services:
  hitkeep:
    image: pascalebeier/hitkeep:2.13.18
    container_name: hitkeep
    restart: unless-stopped
    environment:
      HITKEEP_PUBLIC_URL: https://DEINE_DOMAIN
      HITKEEP_JWT_SECRET: DEIN_JWT_SECRET
      HITKEEP_TRUSTED_PROXIES: 172.16.0.0/12
      HITKEEP_DB_PATH: /var/lib/hitkeep/data/hitkeep.db
      HITKEEP_DATA_PATH: /var/lib/hitkeep/data
      HITKEEP_ARCHIVE_PATH: /var/lib/hitkeep/data/archive
      HITKEEP_BACKUP_PATH: /var/lib/hitkeep/data/backups
    volumes:
      - hitkeep_data:/var/lib/hitkeep/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.hitkeep.rule=Host(`DEINE_DOMAIN`)"
      - "traefik.http.routers.hitkeep.entrypoints=websecure"
      - "traefik.http.routers.hitkeep.tls.certresolver=le"
      - "traefik.http.services.hitkeep.loadbalancer.server.port=8080"
    networks: [proxy]
volumes:
  hitkeep_data: {}
networks:
  proxy:
    external: true

Die wichtigsten Stellen im Detail:

  • HITKEEP_PUBLIC_URL ist die öffentliche Adresse, unter der HitKeep erreichbar ist. Daraus baut die Oberfläche später den Tracking-Snippet und die Links. Sie muss exakt der URL entsprechen, unter der du HitKeep aufrufst – sonst kommst du in eine Login-Schleife.
  • HITKEEP_TRUSTED_PROXIES ist der Knackpunkt hinter einem Reverse Proxy: HitKeep vertraut in der Voreinstellung (*) dem X-Forwarded-For-Header von jedem Absender – jeder Besucher könnte sich also eine fremde IP andichten. 172.16.0.0/12 schränkt das auf die Docker-Netze ein (das proxy-Netz liegt darin, im Test etwa 172.19.0.0/16), sodass nur noch Traefik die Besucher-IP setzen darf. Wichtig: Der Bereich muss die IP deines Proxys wirklich enthalten – passt er nicht, sieht HitKeep nur noch Traefiks Container-IP.
  • loadbalancer.server.port=8080 sagt Traefik, dass HitKeep intern auf Port 8080 lauscht. Der Container veröffentlicht selbst keine Ports nach außen – der Zugriff läuft ausschließlich über Traefik.
  • Die vier _PATH-Variablen legen Datenbank, Daten, Archiv und Backups alle unterhalb von /var/lib/hitkeep/data ab – bewusst in einem Volume. Der Container läuft als Nicht-Root-Benutzer (UID 65532), und nur dieses eine Verzeichnis bringt das Image mit den passenden Rechten mit. Hängst du zusätzliche Volumes für Archiv und Backups an eigene Pfade, legt Docker sie root an, und HitKeep quittiert das im Log mit Initial backup run failed und permission_denied.

Schritt 3: Stack starten und auf TLS warten

Starte den Container:

Terminal
docker compose up -d

Prüfe nach ein paar Sekunden den Status:

Terminal
docker compose ps

Du solltest den Container als healthy sehen – HitKeep bringt einen eigenen Healthcheck mit:

Ausgabe
NAME      IMAGE                          COMMAND     SERVICE   CREATED          STATUS                    PORTS
hitkeep   pascalebeier/hitkeep:2.13.18   "hitkeep"   hitkeep   40 seconds ago   Up 40 seconds (healthy)   7946/tcp, 8080/tcp

Traefik holt jetzt im Hintergrund das Let’s-Encrypt-Zertifikat für deine Domain. Prüfe von deinem eigenen Rechner aus, dass die Auslieferung des Tracking-Skripts steht:

Terminal
curl -sI https://DEINE_DOMAIN/hk.js

Erwartete Ausgabe (gekürzt) – Status 200 und ein text/javascript-Typ, aggressiv gecacht:

Ausgabe
HTTP/2 200
content-type: text/javascript; charset=utf-8
cache-control: public, max-age=31536000, immutable

Achtung

Bekommst du hier ein 404 von Traefik oder eine Zertifikatswarnung, warte eine Minute (Let’s Encrypt braucht kurz) und prüfe, dass der A-/AAAA-Record deiner Domain wirklich auf den Server zeigt. Solange das Zertifikat nicht steht, lädt auch das Snippet im Browser nicht.

Schritt 4: Admin-Konto anlegen

Rufe https://DEINE_DOMAIN im Browser auf. Beim allerersten Start begrüßt dich HitKeep mit der Ersteinrichtung. Lege hier dein Administrator-Konto an – Name, E-Mail-Adresse und ein Passwort. Nimm eine lange Passphrase oder ein per Passwortmanager erzeugtes Zufallspasswort; dieses Konto sieht sämtliche Statistiken und darf nicht an einem schwachen Passwort hängen:

HitKeep-Ersteinrichtung: Formular zum Anlegen des Administrator-Kontos mit Vor- und Nachname, E-Mail-Adresse und Passwort.
Beim ersten Aufruf legst du dein Admin-Konto an.

Tipp

Diese Ersteinrichtung ist nur beim allerersten Aufruf offen. Trotzdem gilt: Richte das Admin-Konto sofort nach dem Start ein und lass keinen frisch gestarteten HitKeep-Wizard ungesichert im Netz stehen.

Schritt 5: Website anlegen und Tracking-Code holen

Nach dem Login klickst du links oben bei Sites auf das Plus und legst deine Website an – als Domain trägst du die Domain der Seite ein, die du messen willst (z. B. DEINE_WEBSITE).

Öffne dann über das </>-Symbol unter dem Site-Namen die Site-Einstellungen im Reiter Tracking. Dort findest du oben den Live tracking verifier, der auf den ersten Treffer wartet, und darunter unter Install HitKeep on … die Einbau-Varianten: Script tag, npm (getippter Tracker für React/Vue/Angular/Astro), WordPress und Server-side. Alle melden in dasselbe Dashboard; wir nehmen den Script-Tag:

HitKeep-Tracking-Einstellungen: Live-Verifier wartet auf den ersten Treffer, darunter die Einbau-Varianten Script tag, npm, WordPress und Server-side mit dem fertigen Snippet.
Der Tracking-Reiter liefert das Snippet und prüft live, ob Treffer ankommen.

Der einzubauende Code besteht aus einer einzigen Zeile. HitKeep braucht keine Site-ID im Snippet – die Zuordnung passiert automatisch über die Domain der Seite, auf der das Skript läuft:

HTML
<script async src="https://DEINE_DOMAIN/hk.js"></script>

Hinweis

Wichtig ist der Unterschied zwischen Tracker-Host und gemessener Domain: hk.js wird von deiner HitKeep-Domain (DEINE_DOMAIN) geladen, zugeordnet wird der Treffer aber der Domain der besuchten Seite (DEINE_WEBSITE). Beide dürfen unterschiedlich sein – die in HitKeep angelegte Site muss nur zum Hostnamen der besuchten Seite passen.

Automatisches Event-Tracking (ausgehende Klicks, Downloads, Formular-Absendungen) ist standardmäßig aktiv. Unter Advanced options kannst du das Snippet anpassen – etwa „Web Vitals" einschalten, um Ladezeiten (LCP, INP, CLS, FCP, TTFB) mitzumessen, oder „Collect DNT", wenn du auch Besucher mit „Do Not Track" zählen willst. Aus Datenschutzsicht ist die Voreinstellung (DNT respektieren) die sauberere. Wichtig: Diese Schalter werden nicht in HitKeep gespeichert, sie schreiben nur zusätzliche data--Attribute in den Code-Schnipsel, den du danach neu kopieren musst:

HTML
<script async src="https://DEINE_DOMAIN/hk.js" data-enable-web-vitals="true"></script>

Schritt 6: Tracking-Code in die Website einbauen

Füge die Snippet-Zeile aus Schritt 5 in den <head> deiner Website ein – bei einer statischen Seite direkt ins HTML-Template, bei einem CMS in den Kopfbereich bzw. ein „Custom HTML"-Feld. Durch das async-Attribut blockiert das Skript den Seitenaufbau nicht.

Rufe danach eine Seite deiner Website im Browser auf. Der Live tracking verifier aus Schritt 5 sollte innerhalb weniger Sekunden von „Waiting" auf einen ersten Treffer springen – das ist die Bestätigung, dass die Kette Website → hk.js → HitKeep steht.

Schritt 7: Das Dashboard prüfen

Sobald Treffer eintrudeln, füllt sich das Dashboard. Unter Dashboard siehst du die Kennzahlen deiner Website – Live-Besucher, Seitenaufrufe, eindeutige Sitzungen, Absprungrate, Verweildauer und den Traffic-Verlauf:

HitKeep-Dashboard mit Kennzahlen-Kacheln (Live-Besucher, Seitenaufrufe, eindeutige Sitzungen, Absprungrate) und einem Traffic-Verlaufsdiagramm für den aktuellen Tag.
Das Dashboard bündelt die wichtigsten Kennzahlen und den Traffic-Verlauf.

Weiter unten listet Latest Hits die einzelnen Aufrufe mit Pfad, Zeitpunkt, Referrer und Gerät auf – hier siehst du auf einen Blick, über welche Suchmaschinen und Verweise deine Besucher kommen:

HitKeep-Tabelle „Latest Hits" mit einzelnen Seitenaufrufen, Referrern wie Suchmaschinen sowie dem Gerätetyp je Aufruf.
Latest Hits zeigt jeden einzelnen Aufruf mit Referrer und Gerät.

Damit steht deine selbst gehostete Statistik: Jeder Aufruf deiner Website landet direkt in deiner eigenen Datenbank, ohne Umweg über Dritte.

Schritt 8: Mehr als nur Seitenaufrufe

Für den Anfang reichen Seitenaufrufe und Referrer – HitKeep kann aber deutlich mehr, und die Bausteine dafür findest du in der linken Navigation. Ein paar, die sich für die meisten Seiten lohnen:

  • Goals (Ziele): Definiere ein Ereignis als Ziel – etwa das Absenden eines Kontaktformulars oder einen Klick auf „Kaufen". So misst du nicht nur, wie viele kommen, sondern wie viele das tun, was du willst.
  • Funnels (Trichter): Verkette mehrere Schritte (Startseite → Produktseite → Warenkorb) und sieh, an welcher Stelle Besucher abspringen.
  • Events: Neben den automatisch erfassten Ereignissen (ausgehende Klicks, Downloads, Formulare) kannst du eigene Ereignisse aus deinem Frontend senden.
  • Web Vitals: Schaltest du sie im Tracking-Reiter ein, siehst du echte Ladezeiten deiner Besucher (LCP, INP, CLS) statt synthetischer Laborwerte.
  • UTM: Kampagnen-Parameter (utm_source, utm_medium, utm_campaign) werden ausgewertet – praktisch, um Newsletter- oder Social-Reichweite auseinanderzuhalten.
  • Reporting: Lass dir eine Zusammenfassung regelmäßig per E-Mail schicken, statt selbst ins Dashboard schauen zu müssen (dafür brauchst du die HITKEEP_MAIL_*-Variablen mit den Zugangsdaten deines Mailservers).

Eine einzelne HitKeep-Instanz verwaltet außerdem beliebig viele Websites: Über das Plus bei Sites legst du weitere an, jede mit eigenem Snippet und eigenem Dashboard. Du brauchst also keinen zweiten Container, wenn du mehrere Projekte messen willst.

Wenn es nicht funktioniert

Der Live-Verifier bleibt auf „Waiting" / keine Treffer im Dashboard. Prüfe im Browser (Entwicklertools → Netzwerk), ob hk.js überhaupt geladen wird und der Sende-Request danach mit Status 2xx zurückkommt. Häufigste Ursachen: Das Snippet steckt nicht im HTML, die in HitKeep angelegte Site-Domain passt nicht zum Hostnamen der besuchten Seite, oder ein Ad-/Tracking-Blocker filtert den Aufruf. Da du unter deiner eigenen Domain hostest (First-Party), greifen die meisten Blocker nicht – manche Listen kennen aber den Pfad hk.js.

Alle Besucher kommen scheinbar von einer einzigen IP, Land und Provider stehen auf „(Unknown)". Dann greift HITKEEP_TRUSTED_PROXIES nicht: Der angegebene Bereich enthält die IP deines Proxys nicht, und HitKeep wertet nur noch Traefiks Container-IP aus. Prüfe mit docker network inspect proxy, in welchem Subnetz der Proxy liegt – 172.16.0.0/12 deckt die üblichen Docker-Netze ab – und starte den Stack neu (docker compose up -d). Danach zählt wieder die echte Client-IP aus dem X-Forwarded-For-Header.

Traefik liefert 404 oder 502. Ein 404 heißt meist, dass die Router-Regel nicht greift – prüfe, dass Host(...) deine echte Domain enthält und der Container im proxy-Netz hängt. Ein 502 deutet auf den falschen Port: HitKeep lauscht intern auf 8080, deshalb muss loadbalancer.server.port=8080 gesetzt sein.

Nach dem Login landest du wieder auf der Anmeldeseite (Login-Schleife). Das ist fast immer eine Diskrepanz bei HITKEEP_PUBLIC_URL: Der Wert muss exakt der Adresse entsprechen, über die du HitKeep aufrufst (inklusive https://, ohne abschließenden Slash). Korrigiere die Variable und starte den Container neu.

Der Container startet nicht bzw. ist nicht healthy. Sieh in die Logs: docker compose logs -f hitkeep. Ein fehlendes oder leeres HITKEEP_JWT_SECRET ist eine typische Startbremse – erzeuge eines wie in Schritt 1 und trage es ein.

Dein Problem ist nicht dabei? Alle Fehlermeldungen durchsuchen →

Wartung & Backups

Updates: HitKeep bewegt sich in der 2.x-Reihe zügig weiter – zwischen 2.12.0 und 2.13.18 lagen keine sieben Wochen. Schau also etwa monatlich in die Releases. Für ein Update setzt du den neuen Tag in der compose.yaml (ersetze 2.13.18 durch die neue Version) und ziehst ihn:

Terminal
docker compose pull && docker compose up -d

Weil die Daten in Volumes liegen, bleiben deine Statistiken dabei erhalten. Pinne die Version bewusst auf einen festen Tag statt latest, damit ein Neustart dir nicht ungeplant eine neue Hauptversion unterschiebt.

Backups: Deine gesamte Statistik steckt in einer eingebetteten DuckDB-Datei (hitkeep.db samt Write-Ahead-Log hitkeep.db.wal) unter /var/lib/hitkeep/data. Sichere deshalb nicht eine Einzeldatei, sondern das komplette Volume hitkeep_data regelmäßig – am saubersten mit restic. HitKeep legt darin selbst stündlich einen Snapshot unter backups/ ab und hält die letzten 24 vor; im Log siehst du das als Database backup completed. Weil die Live-Dateien im laufenden Betrieb beschrieben werden, sicherst du am konsistentesten entweder diese fertigen Snapshots oder das Volume, während der Container kurz gestoppt ist (docker compose stop). Ein Backup, das du nie zurückgespielt hast, ist nur ein Hoffnungsschimmer: Teste die Wiederherstellung einmal auf einem Testsystem.

Aufräumen: Die Datenbank wächst mit dem Traffic. Behalte die Größe der Volumes im Blick (docker system df -v) und plane bei viel Traffic genügend Speicher ein.

Zuletzt aktualisiert: 09.09.2026

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken