SSD Nodes Learn Hosting plans →
Anleitungen Matt ConnorVon Matt Connor · Aktualisiert 2026-08-25

OpenAnalytics auf einem VPS selbst hosten: Voraussetzungen

Prüfen Sie vorab den realen Bedarf: ClickHouse, Postgres, Valkey, 4 GB RAM, 25 GB Speicher und vier DNS-Einträge. Danach folgen Installation und Speicherverbrauch.

Der Footprint vor dem ersten Schritt

Für das Self-Hosting von OpenAnalytics benötigen Sie einen Linux-VPS mit etwa 4 GB RAM, 25 GB freiem Speicherplatz, Docker mit dem Compose-Plugin und vier DNS-Einträge, die bereits auf den Server zeigen. Das ist die wesentliche Voraussetzung und sollte vor dem ersten Befehl genannt werden, nicht danach.

Der Stack besteht aus sechs Anwendungsdiensten und drei Datenspeichern. Postgres speichert die Steuerungsebene: Konten, Websites, API-Schlüssel und Freigabelinks. ClickHouse speichert die Rohereignisse und die Aggregationen, die das Dashboard abruft. Valkey läuft zweimal: einmal als dauerhafte Ereigniswarteschlange und einmal als Cache, dessen Verlust tolerierbar ist, weil für diese beiden Aufgaben entgegengesetzte Eviction-Richtlinien erforderlich sind. Nur ein Prozess, das Query-Gateway, darf ClickHouse lesen. Vor der Ausführung prüft es bei jedem Query-Umschlag eine Ed25519-Signatur.

Wenn Sie eine einzelne Binärdatei und eine Konfigurationsdatei erwartet haben, ist dies nicht die passende Lösung. GoatCounter ist in dieser Kategorie die Option mit einer einzelnen Binärdatei: eine ausführbare Go-Datei, standardmäßig SQLite und überhaupt keine externe Datenbank. Der umfangreichere Stack bietet Funnels, Web Vitals, Revenue Attribution aus Ihrem eigenen Stripe-Konto und einen MCP-Server (Model Context Protocol). Auswahl zwischen selbst gehosteten Analytics-Tools behandelt diesen Zielkonflikt ausführlich. Dieser Leitfaden setzt voraus, dass Sie sich bereits entschieden haben.

Zunächst vier DNS-Einträge auf den Server verweisen

Die vier Subdomains müssen vor Beginn auf die öffentliche IP-Adresse des Servers auflösen. Caddy fordert beim ersten Start Let's-Encrypt-Zertifikate an. Die Challenge schlägt fehl, wenn der Name noch nicht aufgelöst wird.

  • app.example.com stellt das Dashboard bereit.
  • api.example.com stellt die API und die OAuth-Callbacks bereit.
  • c.example.com stellt den Collector und das Tracker-Skript bereit.
  • rt.example.com stellt den Echtzeitstream bereit.

Verwenden Sie vier A-Records oder einen A-Record und drei darauf verweisende CNAMEs. Bestätigen Sie die Auflösung mit dig +short app.example.com, bevor Sie fortfahren. Ein vor einer Minute hinzugefügter Name kann beim verwendeten Resolver von Let's Encrypt weiterhin als NXDOMAIN zwischengespeichert sein. Warten Sie daher einen fehlgeschlagenen ersten Zertifikatsversuch ab und prüfen Sie die Caddy-Logs. Eine erneute Ausführung der Installation beschleunigt die DNS-Propagation nicht.

So hosten Sie OpenAnalytics mit Docker Compose selbst

Checken Sie ein Release-Tag aus. Im Standard-Branch findet die Entwicklung statt. Ein Release-Tag entspricht den tatsächlich veröffentlichten Images. Die folgenden Befehle setzen voraus, dass Docker und das Compose-Plugin bereits installiert sind. Das wird unter Docker-Compose-Dienste auf einem VPS ausführen beschrieben.

git clone https://github.com/OpenLabs-so/openanalytics
cd openanalytics
git checkout "$(git tag -l 'v*' --sort=-v:refname | sed '/-/d' | head -1)"
cd infra/selfhost
./generate-secrets.sh --domain example.com --email you@example.com --with-geoip
docker compose pull && docker compose up -d

sed '/-/d' in der Checkout-Zeile überspringt Vorabversionen. Dadurch verwenden Sie die neueste stabile Version statt eines Release Candidate. --with-geoip lädt die DB-IP-City-Datenbank während der Generierung herunter. Wenn Sie diesen Schritt überspringen, enthält jedes Ereignis ein leeres Landfeld. Die Geografieansicht zeigt dann überhaupt keine Daten an. Sie können die Datenbank später hinzufügen. Führen Sie dazu infra/selfhost/geoip/fetch-dbip.sh aus, setzen Sie GEOIP_DB_PATH=/geoip/dbip-city-lite.mmdb in env/collector.env und erstellen Sie den Collector mit docker compose up -d --force-recreate collector neu. Die Datenbank wird monatlich aktualisiert. Wiederholen Sie den Download daher monatlich. Andernfalls veralten die Stadtdaten.

Sichern Sie die generierten Geheimnisse, bevor Sie fortfahren

Der Generator schreibt drei Dinge. .env enthält die Domainnamen und die Image-Referenzen. env/*.env enthält eine Datei mit Geheimnissen pro Dienst. docker-compose.override.yml enthält drei Ed25519-Schlüsselpaaren als YAML-Blockskalare, weil mehrzeilige PEM-Inhalte nicht in einer Env-Datei gespeichert werden können. Alle diese Dateien sind von Git ausgeschlossen. Keiner dieser Werte kann mit denselben Werten erneut generiert werden.

Kopieren Sie diese Dateien jetzt vom Rechner weg. Der Verlust jeder Datei hat eine konkrete Folge:

  • Wenn Sie die Store-Passwörter verlieren, haben Sie keinen Zugriff mehr auf Postgres und ClickHouse. Sie können die Passwörter nur innerhalb der Container zurücksetzen.
  • Wenn Sie OA_CREDENTIAL_KEYRING verlieren, sind alle gespeicherten Anmeldedaten von Drittanbietern nicht wiederherstellbar. Jeder, der ein Stripe-Konto verbunden hat, muss es erneut verbinden.
  • Wenn Sie ANONYMOUS_IDENTITY_SECRET verlieren, wird die Besucheridentität neu zugeordnet: Die Besucher von gestern zählen alle als neu, und die Unterbrechung ist in den Diagrammen sichtbar.
  • Wenn Sie AUTH_SECRET verlieren, werden alle Sitzungen ungültig. Alle Benutzer müssen sich erneut anmelden.
  • Wenn Sie einen privaten Signaturschlüssel verlieren, tauschen Sie das Schlüsselpaar aus. Dabei gehen keine Daten verloren.

Zwei Geheimnisse müssen jeweils in zwei Dateien bytegenau identisch sein. ANONYMOUS_IDENTITY_SECRET steht in collector.env und worker.env, weil der Collector den Besucher-Hash berechnet und der Worker ihn schreibt. OA_CREDENTIAL_KEYRING steht in api.env und worker.env. Alle anderen Geheimnisse sind absichtlich genau einem Dienst zugeordnet. Ein Dienst, dem ein Geheimnis übergeben wird, das er nicht besitzen darf, beendet sich, statt zu starten.

Stack starten und prüfen

grep OA_IMAGE .env
docker compose pull
docker compose up -d
docker compose logs -f migrate
docker compose ps

migrate wendet die Postgres- und ClickHouse-Schemas an und wird anschließend beendet. Daher ist ein gestoppter migrate-Container der korrekte Endzustand. tracker-build kompiliert oa.js in ein Volume, das Caddy bereitstellt, und wird ebenfalls beendet. Alle anderen Dienste sollten in docker compose ps healthy anzeigen. Ein Dienst, der in einer Schleife neu gestartet wird, scheitert fast immer an der Validierung der Umgebung. Das Log listet alle Probleme gemeinsam auf und nicht jeweils eines pro Neustart. Die beiden häufigsten Ursachen sind eine leer gelassene Variable, die abgelehnt und nicht als nicht gesetzt behandelt wird, sowie ein Secret in der falschen Service-Datei.

Auf arm64 oder bei Verwendung eines Branches gibt es keine veröffentlichten Images. In diesem Fall erstellen Sie sie lokal mit docker compose up -d --build. Ein Host mit 4 GB Arbeitsspeicher kann während dieses Builds nicht mehr genügend Speicher haben. Richten Sie daher zuerst Swap ein. Dieser wird nur während des Builds benötigt:

fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Der Build dauert ungefähr zehn Minuten. Das Herunterladen dauert nur wenige Minuten. Deshalb gibt es die Release-Images.

Erstellen Sie das erste Konto sofort

Öffnen Sie https://app.example.com. Eine Bereitstellung, bei der sich noch niemand angemeldet hat, zeigt kein Anmeldeformular. Stattdessen bietet sie an, das erste Konto zu erstellen. Dieses Konto bleibt dauerhaft das privilegierte Konto. Nur dieses Konto kann die Bereitstellungseinstellungen aufrufen. Sobald es existiert, antwortet die Route mit 409. Dadurch kann sich niemand nachträglich Zugang verschaffen. Erstellen Sie das Konto, sobald der Stack fehlerfrei läuft, nicht erst in der folgenden Woche.

Tracker installieren

Fügen Sie im Dashboard eine Website hinzu. Daraufhin erhalten Sie das Tag. Die Struktur ist fest vorgegeben:

<script
  async
  src="https://c.example.com/oa.js"
  data-key="YOUR_TRACKING_KEY"
  data-collector="https://c.example.com"
></script>

Fügen Sie es in den Head der Seite ein. Der Tracking-Schlüssel ist absichtlich öffentlich und gehört daher in Ihr HTML, wo ihn jeder lesen kann. Das Script installiert window.oa. Aufrufe wie oa("track", ...) werden von einem Stub in eine Warteschlange gestellt und nach dem Laden der Datei abgearbeitet. Dadurch geht ein früh ausgelöstes benutzerdefiniertes Ereignis nicht verloren. Wenn window.oa auf der Seite bereits anderweitig verwendet wird, installiert der Tracker sich stattdessen als window.openanalytics. Wenn dieselbe Website auch als Onion-Service erreichbar ist, darf das Tag nicht in diesen Build gelangen. Ein von c.example.com geladenes Script führt Besucher des Tor Browser zurück ins Clearnet und verknüpft beide Adressen innerhalb desselben Seitenaufrufs.

Prüfen Sie anschließend den gesamten Pfad von Ende zu Ende:

curl -s https://c.example.com/oa.js -o /dev/null -w '%{http_code} %{size_download}\n'
curl -s https://api.example.com/health | head -c 200
docker compose logs --tail=50 worker | grep -i batch

Der erste Befehl sollte 200 und einige Kilobyte ausgeben. Laden Sie eine Seite Ihrer Website. Suchen Sie anschließend innerhalb weniger Sekunden nach einer Batch-Zeile im Worker-Log. Der Collector antwortet mit 202, sobald er ein Ereignis akzeptiert hat. 202 bedeutet, dass das Ereignis in die Warteschlange gestellt wurde, nicht dass es gespeichert ist. Der Worker überträgt die Ereignisse nach ClickHouse. Werden Ereignisse akzeptiert, erscheinen aber keine Daten im Dashboard, ist der Worker blockiert. Eine kontinuierlich wachsende Valkey-Warteschlangentiefe bestätigt das. Häufige Ursachen sind falsche ClickHouse-Zugangsdaten in worker.env oder eine fehlende Berechtigung auf einer Tabelle, die eine Migration gerade hinzugefügt hat.

Den Collector öffentlich und das Dashboard hinter der Authentifizierung betreiben

Caddy ist in der Compose-Datei enthalten und beschafft selbstständig Zertifikate für alle vier Namen. Der Standardpfad erfordert daher keine Proxy-Arbeiten von Ihnen. Wenn auf dem Server bereits ein Nginx-Reverse-Proxy läuft, schalten Sie stattdessen den bereitgestellten infra/selfhost/nginx.conf.example vor den Stack und behalten Sie dessen Header-Verarbeitung bei:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header CF-Connecting-IP "";
proxy_set_header True-Client-IP "";
proxy_set_header Fly-Client-IP "";

Der Collector leitet den täglichen Besucher-Hash aus der Client-IP ab. Er muss diese Adresse daher aus der Verbindung übernehmen und darf sie niemals aus einem Header lesen. Wenn Sie CF-Connecting-IP von einem nicht vertrauenswürdigen Proxy weiterreichen, kann jeder Aufrufer eine beliebige Adresse angeben. Dadurch werden die Geolokalisierung verfälscht und gleichzeitig die Besucherzahlen erhöht.

Der Zugriff wird sauber nach Hostnamen getrennt. c. und rt. müssen für jeden Besucher jeder gemessenen Website erreichbar sein. Schalten Sie daher niemals eine Basic-Authentifizierung oder eine IP-Allowlist vor diese beiden Hostnamen. app. und api. müssen nur für angemeldete Personen erreichbar sein. Das Dashboard wird durch die eigene Authentifizierung der Anwendung geschützt: Die Anmeldung per Passwort ist standardmäßig über AUTH_PASSWORD_SIGNIN=enabled in env/api.env aktiviert. Die Google- oder GitHub-Schaltflächen erscheinen nur, wenn für den jeweiligen Anbieter sowohl die Client-ID als auch das Client-Secret vorhanden sind. Magic Links benötigen einen Mail-Transport. Ohne diesen schreibt die API den Versand nur in eine Outbox. Dadurch wird nichts zugestellt und es tritt kein Fehler auf. Wenn Ihre anderen selbst gehosteten Anwendungen bereits hinter einer gemeinsamen Authentik-Anmeldung liegen, entscheiden Sie frühzeitig, ob dieses Dashboard daran teilnimmt oder eigene Konten verwendet. Das erste Konto, das Sie hier anlegen, bleibt dauerhaft das privilegierte Konto.

Eine Einstellung entscheidet, ob das Dashboard überhaupt funktioniert. AUTH_TRUSTED_ORIGINS in env/api.env muss exakt dem Ursprung des Dashboards entsprechen. Bei einem falschen oder fehlenden Wert sendet die API keine CORS-Header (Cross-Origin Resource Sharing). Der Browser verweigert dann jeden Aufruf. Das Dashboard rendert zwar sein Layout, zeigt aber keine Daten an, während docker compose ps weiterhin einen fehlerfreien Zustand meldet.

Kümmern Sie sich während der Proxy-Konfiguration auch um automatisierten Datenverkehr. Crawler greifen wie normale Besucher auf den Collector zu. Ihre Seitenaufrufe landen dadurch in ClickHouse und in Ihren Kennzahlen. KI-Crawler auf dem Server blockieren hält einen Teil dieses Datenverkehrs von der Datenbank fern, bevor er Genauigkeit und Speicherplatz beeinträchtigt.

Was „cookieless“ hier bedeutet und welche Kosten damit verbunden sind

Es wird kein Cookie gesetzt. Die Besucheridentität ist ein gesalzener Hash. Das Salt wechselt täglich. Rohe IP-Adressen werden niemals gespeichert. Die Geolokalisierung wird lokal anhand der DB-IP-Datei auf Ihrer eigenen Festplatte ermittelt. Es verlässt also keine Abfrage zu einem Besucher den Host. Lokale Abfragen entfernen den Anbieter, nicht die Daten. Das ist dieselbe Einschränkung wie bei einer eigenen SearXNG-Instanz, wenn die IP-Adresse Ihres Servers für die Suchmaschinen sichtbar wird.

Damit entfällt ein Bezeichner, der auf dem Gerät des Besuchers gespeichert bleibt. Genau dieser Bezeichner führt dazu, dass ein Tracker unter die Einwilligungsregeln der EU-ePrivacy-Vorschriften fällt. Aggregierte Setups wie dieses werden deshalb häufig ohne Einwilligungsbanner betrieben. Die DSGVO gilt weiterhin für alle Daten, die Sie speichern, und für die Speicherdauer. Ob dies in Ihrem konkreten Fall zulässig ist, entscheidet Ihre eigene Rechtsberatung, nicht eine README-Datei.

Der Nachteil ist, dass sich Besucher nicht über mehrere Tage hinweg erkennen lassen. Durch den Wechsel des Salt wird eine Person, die am Montag und erneut am Mittwoch Ihre Website besucht, absichtlich als zwei Besucher gezählt. Dafür gibt es keine Umgehung. Die täglichen Besucherzahlen sind belastbar. Wöchentliche und monatliche Besucherzahlen werden aus den Tageswerten gebildet und überschätzen daher die Reichweite. Eine Kennzahl für „wiederkehrende Besucher“ über längere Zeiträume misst deshalb nicht das, was ihre Bezeichnung nahelegt. Sitzungen und Besuchsverläufe sind innerhalb eines einzelnen Tages zuverlässig. Die Rotation von ANONYMOUS_IDENTITY_SECRET hat denselben Effekt wie ein Tageswechsel. Behandeln Sie diese Rotation daher als Datenänderung und nicht als routinemäßige Wartung.

Der Collector berücksichtigt Do Not Track und Global Privacy Control. Dabei handelt es sich um ein Browser-Signal, das einer Website mitteilt, dass sie personenbezogene Daten nicht verkaufen oder weitergeben soll. Das Script-Tag enthält eigene Schalter für denselben Zweck: data-respect-gpc, data-respect-dnt und data-require-consent. data-require-consent hält die gesamte Erfassung zurück, bis eine Einwilligung erteilt wurde, und speichert die Antwort in localStorage unter dem Schlüssel oa.consent. Mit data-storage="none" deaktivieren Sie den Browser-Speicher vollständig.

Warum die Festplatte nach sechs Monaten voll ist

Das bringt eine selbst gehostete Analytics-Instanz zum Ausfall. Die Ereignisse selbst sind meistens nicht die Ursache.

Beginnen Sie mit den Images. Ein Release veröffentlicht zehn davon. Zusammen belegen sie ungefähr 13 GB auf der Festplatte. Bei einem Upgrade werden die neuen Images abgerufen, bevor die alten gelöscht werden. Für eine gewisse Zeit sind daher zwei Generationen vorhanden. Das macht den größten Teil des Bedarfs von 25 GB aus, bevor überhaupt ein einzelner Seitenaufruf verarbeitet wird.

Dann kommen die Snapshots. snapshot.sh stoppt den Stack, archiviert beide Datenvolumes einschließlich aller Secrets und startet den Stack anschließend neu. Hier sind nur Kopien im gestoppten Zustand sicher, weil ClickHouse Teile im Hintergrund zusammenführt. Eine Kopie während einer Zusammenführung ist nicht konsistent. upgrade.sh erstellt vor jedem Upgrade automatisch einen Snapshot. Dadurch sammeln sich die Archive auf derselben Festplatte an, bis Sie ihre Anzahl begrenzen.

./snapshot.sh create --label before-something-risky
./snapshot.sh list
./snapshot.sh --keep 3

Auf einem Host, dessen Speicherplatz fast erschöpft ist, sollten Sie die vorherige Generation vor dem Upgrade freigeben. Das ist während des laufenden Betriebs des Stacks sicher, weil Images, die laufende Container verwenden, weiterhin referenziert werden:

docker image prune -a -f

Dann kommen die Ereignisse selbst. ClickHouse komprimiert spaltenorientierte Daten stark. Deshalb wächst das Volumen der Rohdaten langsamer als von vielen Benutzern erwartet. Die Aggregationstabellen, aus denen das Dashboard liest, sind neben der Rohtabelle klein. Messen Sie daher statt zu schätzen:

docker system df -v
docker compose exec clickhouse df -h /var/lib/clickhouse

Für die Aufschlüsselung nach Tabelle führen Sie den Befehl mit den ClickHouse-Anmeldedaten aus, die der Generator unter infra/selfhost/env/ geschrieben hat:

SELECT table, formatReadableSize(sum(bytes_on_disk)) AS size, sum(rows) AS row_count
FROM system.parts
WHERE active
GROUP BY table
ORDER BY sum(bytes_on_disk) DESC;

Erfassen Sie diesen Wert in der ersten Woche und erneut in der vierten Woche. Zwei Messpunkte ergeben eine Wachstumsrate. Anhand der Wachstumsrate können Sie bestimmen, wann das Volume vergrößert werden muss. Die Self-Hosting-Anleitung dokumentiert mit Stand August 2026 keinen Aufbewahrungs- oder Time-to-Live-Parameter für rohe Ereignisse. Dimensionieren Sie die Festplatte daher anhand der gemessenen Rate. Gehen Sie nicht davon aus, dass alte Zeilen automatisch ablaufen.

Eine Falle beim Löschen sollten Sie kennen, bevor sie Probleme verursacht. Beim Löschen einer Site oder eines Kontos wird ein Auftrag für den Worker in die Warteschlange gestellt. Dieser Worker benötigt gesetzte Werte für CLICKHOUSE_MAINTENANCE_USER und CLICKHOUSE_MAINTENANCE_PASSWORD. Außerdem muss in ClickHouse ein passender oa_maintenance-Benutzer vorhanden sein. Ohne diese Voraussetzungen bleibt der Löschauftrag dauerhaft in der Warteschlange. Die Site verschwindet aus dem Dashboard, aber alle Zeilen bleiben auf der Festplatte. Dadurch sieht es nach einer Bereinigung aus, ohne dass Speicherplatz freigegeben wird.

Upgrades und die drei Kosten

git fetch --tags
git checkout "$(git tag -l 'v*' --sort=-v:refname | sed '/-/d' | head -1)"
cd infra/selfhost
./upgrade.sh

upgrade.sh gibt vor dem Ausführen drei Kosten aus. Ausfallzeit ist real: Ereignisse, die während des Ausfalls des Collectors auftreten, gehen verloren, weil der Tracker sie nicht erneut versucht. Beim Rollback gehen Daten verloren, da rollback.sh --to backups/<snapshot> beide Speicher vollständig ersetzt und jede Zeile verwirft, die nach der Erstellung dieses Snapshots geschrieben wurde. Der Speicherplatz ist die dritte Kostenart. Gemeint ist der oben beschriebene Snapshot-Bestand.

Zwei Regeln für Neustarts werden leicht falsch umgesetzt. Starten Sie das Query-Gateway vor der API, weil eine neuere API Query-Felder sendet, die ein älteres Gateway ablehnt. ClickHouse muss außerdem neu erstellt und nicht nur neu gestartet werden, weil docker compose restart die ursprüngliche Umgebung des Containers wiederverwendet und Ihre Änderung stillschweigend ignoriert:

docker compose up -d --force-recreate clickhouse

Das Dashboard hat dieselbe Fehlerquelle. Die drei NEXT_PUBLIC_*-Ursprünge in env/web.env sind in das Browser-Bundle kompiliert und werden beim Start des Containers eingesetzt. Daher beheben Sie ein Dashboard, das den falschen Hostnamen verwendet, mit docker compose up -d --force-recreate web und niemals mit restart. Das Log des Webcontainers gibt die Ursprünge aus, mit denen er gestartet wurde. So lässt sich am schnellsten bestätigen, dass die Änderung übernommen wurde.

Wenn ClickHouse nach einer Konfigurationsänderung den Start verweigert, lesen Sie die erste Logzeile. Eine Zeile, die mit oa-entrypoint: beginnt, zeigt, dass der Entry Point einen von Ihnen gesetzten Wert ablehnt. Andernfalls ist die Konfigurationsdatei meist ungültiges XML. Die häufigste Ursache ist ein doppelter Bindestrich innerhalb eines XML-Kommentars, was dort nicht zulässig ist.

AGPL-3.0 und der Name

Der Code steht unter der Lizenz AGPL-3.0. Wenn Sie ihn unverändert für Ihre eigenen Websites betreiben, entsteht dadurch keinerlei Pflicht zur Veröffentlichung. Diese Pflicht beginnt, sobald Sie den Code ändern und die geänderte Version als Netzwerkdienst betreiben: Die Lizenz verpflichtet Sie dann, den Benutzern dieses Dienstes den geänderten Quellcode anzubieten. Das gilt auch, wenn Sie Kunden Dashboards auf Ihrer Instanz bereitstellen oder den Code in ein Produkt integrieren, das Sie verkaufen. Wenn Sie Ihre Änderungen in einem öffentlichen Fork pflegen, erfüllen Sie diese Pflicht ohne weitere Maßnahmen.

Die Marke ist vom Code getrennt. Der Name „OpenAnalytics“ und die von den Autoren betriebene Domain des gehosteten Projekts identifizieren die von ihnen betriebene Instanz und sind nicht Bestandteil der Lizenzeinräumung. Ihre Bereitstellung führt die Software aus, ohne die Marke zu übernehmen. Geben Sie dem Dienst daher einen eigenen Namen, bevor Sie ihn zahlenden Kunden anbieten.

FAQ

Kann ich OpenAnalytics auf einem 1 GB VPS ausführen?

Nein. Das Projekt benötigt etwa 4 GB RAM und 25 GB freien Speicherplatz, weil eine Bereitstellung sechs Anwendungsdienste neben Postgres, ClickHouse und zwei Valkey-Instanzen ausführt. ClickHouse allein ist kein kleiner Prozess. Auf einem System mit 1 GB starten die Container, anschließend beendet der Out-of-Memory-Killer des Kernels einen davon, meistens ClickHouse. Wenn ein Tarif mit 1 GB die feste Vorgabe ist, verwenden Sie ein Tool mit einer einzelnen Binärdatei wie GoatCounter. Es läuft mit SQLite und benötigt keine externe Datenbank.

Das müssen Sie mit Ihrem Rechtsberater klären. Die technischen Voraussetzungen sprechen jedoch dafür, dass Sie darauf verzichten können. Es gibt kein Cookie. Die Besucheridentität wird als täglich wechselnder Salt-Hash gespeichert. Rohe IP-Adressen werden nie gespeichert. Dadurch werden keine dauerhaften Daten zur Identifizierung des Besuchers geschrieben. Die DSGVO regelt weiterhin, welche Daten Sie speichern und wie lange Sie sie aufbewahren. Wenn die Erfassung ausdrücklich von einer Einwilligung abhängig sein soll, setzen Sie data-require-consent im Script-Tag. Der Tracker erfasst dann nichts, bis die Einwilligung erteilt wurde, und speichert die Antwort in localStorage unter oa.consent.

Warum liefern Ereignisse den Status 202 zurück, erscheinen aber nie im Dashboard?

202 bedeutet, dass der Collector das Ereignis angenommen und in die Warteschlange gestellt hat. Es bedeutet nicht, dass das Ereignis gespeichert wurde. Der Worker verarbeitet diese Warteschlange in ClickHouse. Ein leeres Dashboard bei erfolgreichen Anfragen weist daher auf den Worker hin. Lesen Sie docker compose logs --tail=50 worker und überwachen Sie die Tiefe der Valkey-Warteschlange. Eine weiter wachsende Warteschlange bedeutet, dass der Worker blockiert ist. Häufige Ursachen sind falsche ClickHouse-Zugangsdaten in worker.env oder eine fehlende Berechtigung für eine Tabelle, die durch eine aktuelle Migration angelegt wurde.

Warum ist das Dashboard leer, obwohl alle Container fehlerfrei sind?

Prüfen Sie zuerst AUTH_TRUSTED_ORIGINS in env/api.env. Der Wert muss exakt mit dem Origin des Dashboards übereinstimmen. Andernfalls sendet die API keine CORS-Header. Der Browser verweigert dann jeden Aufruf, und Sie sehen zwar das funktionierende Layout, aber keine Daten. Prüfen Sie anschließend die drei NEXT_PUBLIC_*-Werte in env/web.env. Sie werden beim Start des Webcontainers ersetzt. Um sie zu korrigieren, benötigen Sie docker compose up -d --force-recreate web, weil ein einfacher Neustart die alten Werte beibehält.

Verhindert AGPL-3.0, dass ich dies Kunden anbiete?

Nein, die Lizenz stellt eine Bedingung. Wenn Sie den Code unverändert ausführen, schulden Sie niemandem etwas. Wenn Sie ihn ändern und die geänderte Version als Dienst betreiben, den andere Personen nutzen, müssen Sie diesen Nutzern Ihren geänderten Quellcode anbieten. Ein öffentliches Fork erfüllt diese Anforderung. Unabhängig davon ist der Name „OpenAnalytics“ nicht zusammen mit dem Code lizenziert. Alles, was Sie verkaufen, benötigt daher einen eigenen Namen.