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.

· 9 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 Statistik auf deinem Server, unter deiner Domain, ohne dass je ein Byte an Dritte geht.

Was bauen wir?

Am Ende läuft HitKeep 2.12.0 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 schlankes Distroless-Image (rund 71 MB), 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

4 vCore · 8 GB RAM · 256 GB NVMe

ab 10,36 €/Monat

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

Zu netcup →

💶 5 € Gutschein für netcup-Neukunden:36nc17844976032 (nur Neukunden, keine Domains)

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.12.0
    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/archive
      HITKEEP_BACKUP_PATH: /var/lib/hitkeep/backups
    volumes:
      - hitkeep_data:/var/lib/hitkeep/data
      - hitkeep_archive:/var/lib/hitkeep/archive
      - hitkeep_backups:/var/lib/hitkeep/backups
    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: {}
  hitkeep_archive: {}
  hitkeep_backups: {}
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: Ohne diesen Wert sieht HitKeep als Absender jedes Aufrufs nur die interne IP von Traefik – dann landen alle Besucher als ein einziger. 172.16.0.0/12 deckt die Docker-Netze ab, sodass HitKeep dem X-Forwarded-For-Header von Traefik vertraut und die echte Besucher-IP auswertet.
  • 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 unter /var/lib/hitkeep/ ab; die passenden Volumes sorgen dafür, dass sie ein Update oder einen Neustart überleben.

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                         SERVICE   STATUS                   PORTS
hitkeep   pascalebeier/hitkeep:2.12.0   hitkeep   Up 18 minutes (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 die Site-Einstellungen und wechsle auf den Reiter Tracking. Dort findest du den Live tracking verifier (der auf den ersten Treffer wartet) und die Konfiguration des Tracking-Codes samt Tracker-Host:

HitKeep-Tracking-Einstellungen: Live-Verifier wartet auf den ersten Treffer, darunter die Konfiguration des Tracking-Codes mit Tracker-Host und Optionen wie DNT und Web Vitals.
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. Optional kannst du auf demselben Reiter „Web Vitals" einschalten, um Ladezeiten (LCP, INP, CLS, FCP, TTFB) mitzumessen, oder „Collect DNT" aktivieren, wenn du auch Besucher mit „Do Not Track" zählen willst – aus Datenschutzsicht ist die Voreinstellung (DNT respektieren) die sauberere.

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.
  • Email Reports: Lass dir eine Zusammenfassung regelmäßig per E-Mail schicken, statt selbst ins Dashboard schauen zu müssen.

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. Dann fehlt oder greift HITKEEP_TRUSTED_PROXIES nicht: HitKeep sieht nur Traefiks interne IP. Stelle sicher, dass die Variable gesetzt ist (172.16.0.0/12 deckt die Docker-Netze ab) und starte den Stack neu (docker compose up -d). Danach werten Besucherzahlen und Herkunft wieder die echte Client-IP aus dem X-Forwarded-For-Header aus.

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.

Wartung & Backups

Updates: HitKeep bewegt sich in der 2.x-Reihe zügig weiter – schau etwa monatlich in die Releases. Für ein Update setzt du den neuen Tag in der compose.yaml (ersetze 2.12.0 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. Weil diese Dateien im laufenden Betrieb beschrieben werden, sicherst du sie am konsistentesten, indem du den Container kurz stoppst (docker compose stop), das Volume sicherst und wieder startest – oder das von HitKeep unter HITKEEP_BACKUP_PATH abgelegte Backup mit einbeziehst. 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.

Feedback per E-Mail: feedback@serverkueche.de

Das könnte dir auch schmecken

Forgejo: der eigene Git-Server hinter Traefik
Anwendungen Fortgeschritten

Forgejo: der eigene Git-Server hinter Traefik

Forgejo mit Docker & Traefik aufsetzen: eigener Git-Server mit HTTPS, Repos per Web-UI, Klonen über HTTPS und SSH – die …

· 10 Min. Lesezeit