Jak samodzielnie hostować OpenAnalytics na VPS
Poznaj rzeczywiste wymagania sprzętowe przed instalacją OpenAnalytics. Do poprawnego działania potrzeba 4 GB RAM, 25 GB miejsca na dysku, ClickHouse, Postgres oraz Valkey.
Wymagania wstępne przed rozpoczęciem
Aby samodzielnie hostować OpenAnalytics, wymagany jest VPS z systemem Linux, posiadający około 4 GB pamięci RAM, 25 GB wolnego miejsca na dysku, zainstalowany Docker z wtyczką Compose oraz cztery rekordy DNS wskazujące na serwer. Jest to rzetelne podsumowanie wymagań, które powinno znaleźć się przed wykonaniem pierwszej komendy, a nie po niej.
Stos technologiczny składa się z sześciu usług aplikacyjnych oraz trzech magazynów danych. Postgres obsługuje płaszczyznę sterowania: konta, witryny, klucze API oraz linki udostępniania. ClickHouse przechowuje surowe zdarzenia oraz agregaty odczytywane przez pulpit nawigacyjny. Valkey działa w dwóch instancjach: jako trwała kolejka zdarzeń oraz jako pamięć podręczna, której utrata jest dopuszczalna, ponieważ te dwa zadania wymagają odmiennych polityk usuwania danych. Tylko jeden proces, bramka zapytań (query gateway), ma uprawnienia do odczytu z ClickHouse; weryfikuje on podpis Ed25519 na każdej kopercie zapytania przed jego wykonaniem.
Jeśli oczekiwano jednego pliku binarnego i jednego pliku konfiguracyjnego, to rozwiązanie nie spełnia tych założeń. GoatCounter jest opcją jednoplikową w tej kategorii: jeden plik wykonywalny w języku Go, domyślnie korzystający z SQLite, bez żadnych zewnętrznych baz danych. Cięższy stos technologiczny zapewnia funkcje takie jak lejki sprzedażowe, wskaźniki web vitals, atrybucję przychodów z własnego konta Stripe oraz serwer MCP (model context protocol). Wybór między samodzielnie hostowanymi narzędziami analitycznymi to artykuł, który analizuje te różnice. Niniejszy przewodnik zakłada, że decyzja została już podjęta.
Skierowanie rekordów DNS na serwer przed rozpoczęciem
Cztery subdomeny muszą wskazywać na publiczny adres IP serwera przed rozpoczęciem jakichkolwiek działań. Caddy żąda certyfikatów Let's Encrypt przy pierwszym uruchomieniu, a wyzwanie (challenge) kończy się niepowodzeniem, jeśli nazwa nie jest jeszcze poprawnie rozwiązywana.
app.example.comobsługuje pulpit nawigacyjny (dashboard).api.example.comobsługuje API oraz wywołania zwrotne OAuth.c.example.comobsługuje moduł zbierający (collector) oraz skrypt śledzący.rt.example.comobsługuje strumień danych w czasie rzeczywistym.
Należy użyć czterech rekordów A lub jednego rekordu A i trzech rekordów CNAME wskazujących na ten pierwszy. Przed kontynuacją należy zweryfikować konfigurację za pomocą dig +short app.example.com. Nazwa dodana przed chwilą może być nadal przechowywana w pamięci podręcznej jako NXDOMAIN przez dowolny resolver, z którego korzysta Let's Encrypt. Jeśli pierwsza próba uzyskania certyfikatu zakończy się niepowodzeniem, należy odczekać i sprawdzić logi Caddy. Ponowne uruchomienie instalacji nie przyspiesza propagacji DNS.
Jak hostować OpenAnalytics przy użyciu Docker Compose
Pobierz oznaczoną wersję (tag). Główna gałąź służy do prac rozwojowych, natomiast tagi wersji odpowiadają opublikowanym obrazom. Poniższe polecenia zakładają, że Docker oraz wtyczka Compose są już zainstalowane, co opisano w uruchamianie usług Docker Compose na VPS.
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 -dParametr sed '/-/d' w poleceniu checkout pomija tagi wersji wstępnych, dzięki czemu pobierana jest najnowsza stabilna wersja, a nie kandydat do wydania. Polecenie --with-geoip pobiera bazę danych miast DB-IP podczas generowania. Pomiń ten krok, a każde zdarzenie będzie miało przypisaną wartość null dla kraju, co spowoduje, że widok geograficzny pozostanie pusty. Możesz dodać tę bazę później, uruchamiając infra/selfhost/geoip/fetch-dbip.sh, ustawiając GEOIP_DB_PATH=/geoip/dbip-city-lite.mmdb w pliku env/collector.env, a następnie odtwarzając kolektor za pomocą docker compose up -d --force-recreate collector. Baza danych jest odświeżana co miesiąc, więc powtarzaj proces pobierania co miesiąc, aby uniknąć dezaktualizacji danych o miastach.
Wykonaj kopię zapasową wygenerowanych sekretów przed kontynuacją
Generator tworzy trzy elementy. .env przechowuje nazwy domen oraz odniesienia do obrazów. env/*.env zawiera po jednym pliku sekretów dla każdej usługi. docker-compose.override.yml przechowuje trzy pary kluczy Ed25519 jako skalary blokowe YAML, ponieważ wieloliniowy format PEM nie może znajdować się w pliku env. Całość jest ignorowana przez git i żadnego z tych elementów nie można wygenerować ponownie z tymi samymi wartościami.
Skopiuj te pliki z maszyny już teraz. Utrata każdego z nich wiąże się z konkretnymi konsekwencjami:
- Utrata haseł do magazynu oznacza brak dostępu do Postgres i ClickHouse, co można zresetować tylko z wnętrza kontenerów.
- Utrata
OA_CREDENTIAL_KEYRINGsprawia, że wszystkie zapisane poświadczenia stron trzecich stają się niemożliwe do odzyskania, więc każdy, kto połączył konto Stripe, musi zrobić to ponownie. - Utrata
ANONYMOUS_IDENTITY_SECRETpowoduje zresetowanie tożsamości odwiedzających: wszyscy wczorajsi użytkownicy zostaną policzeni jako nowi, co będzie widoczne na wykresach. - Utrata
AUTH_SECRETunieważnia wszystkie sesje, więc wszyscy użytkownicy muszą zalogować się ponownie. - Utrata prywatnego klucza podpisywania wymaga rotacji pary kluczy. Żadne dane nie zostają utracone.
Dwa sekrety muszą być identyczne pod względem bajtowym w dwóch różnych plikach. ANONYMOUS_IDENTITY_SECRET występuje w collector.env oraz worker.env, ponieważ kolektor oblicza skrót odwiedzającego, a worker go zapisuje. OA_CREDENTIAL_KEYRING występuje w api.env oraz worker.env. Wszystkie pozostałe sekrety są celowo przypisane do dokładnie jednej usługi, a usługa, która otrzyma sekret, którego nie powinna posiadać, zakończy działanie zamiast się uruchomić.
Uruchomienie stosu i weryfikacja
grep OA_IMAGE .env
docker compose pull
docker compose up -d
docker compose logs -f migrate
docker compose psmigrate stosuje schematy Postgres oraz ClickHouse, a następnie kończy działanie, więc zatrzymany kontener migrate jest poprawnym stanem końcowym. tracker-build kompiluje oa.js do wolumenu obsługiwanego przez Caddy i również kończy pracę. Wszystkie pozostałe usługi powinny mieć status healthy w docker compose ps. Usługa restartująca się w pętli niemal zawsze oznacza niepowodzenie walidacji środowiska, a dziennik wyświetla wszystkie problemy na jednej liście, zamiast po jednym na restart. Dwie najczęstsze przyczyny to pozostawienie pustej zmiennej, która jest odrzucana zamiast traktowana jako nieustawiona, oraz umieszczenie sekretu w niewłaściwym pliku usługi.
W architekturze arm64 lub w przypadku korzystania z gałęzi rozwojowej, opublikowane obrazy nie istnieją i należy przeprowadzić budowanie lokalnie za pomocą docker compose up -d --build. Host z 4 GB pamięci RAM wyczerpuje zasoby w trakcie tego procesu. Należy najpierw dodać swap, który jest wymagany wyłącznie na czas budowania:
fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstabBudowanie trwa około dziesięciu minut. Pobieranie obrazów zajmuje kilka minut, dlatego udostępniane są gotowe obrazy wydań.
Natychmiastowe przejęcie pierwszego konta
Otwórz https://app.example.com. Wdrożenie, do którego nikt się jeszcze nie zalogował, nie wyświetla formularza logowania: oferuje utworzenie pierwszego konta. To konto na stałe uzyskuje uprawnienia administratora i jako jedyne ma dostęp do ekranu ustawień wdrożenia. Gdy konto już istnieje, ścieżka zwraca 409, co uniemożliwia nieautoryzowany dostęp osobom trzecim. Wykonaj tę czynność w momencie, gdy stos jest gotowy do pracy, a nie w późniejszym terminie.
Instalacja trackera
Dodaj witrynę w panelu sterowania, aby otrzymać tag. Jego format jest stały:
<script
async
src="https://c.example.com/oa.js"
data-key="YOUR_TRACKING_KEY"
data-collector="https://c.example.com"
></script>Umieść go w sekcji head strony. Klucz śledzenia jest z założenia publiczny, więc powinien znajdować się w kodzie HTML, gdzie każdy może go odczytać. Skrypt instaluje window.oa, a wywołania takie jak oa("track", ...) są kolejkowane przez stub i wysyłane po załadowaniu pliku, dzięki czemu zdarzenie niestandardowe wywołane wcześnie nie zostanie utracone. Jeśli inny element strony korzysta już z window.oa, tracker zainstaluje się jako window.openanalytics. Jeśli ta sama witryna jest dostępna również jako usługa onion, nie umieszczaj tagu w tej wersji, ponieważ skrypt pobrany z c.example.com przekieruje użytkownika Tor Browser do sieci publicznej (clearnet) i powiąże oba adresy w ramach jednego ładowania strony.
Następnie sprawdź całą ścieżkę od początku do końca:
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 batchPierwsze polecenie powinno zwrócić 200 oraz kilka kilobajtów danych. Załaduj stronę w swojej witrynie, a następnie w ciągu kilku sekund sprawdź linię wsadową (batch) w dzienniku procesu roboczego (worker). Kolektor odpowiada 202 w momencie przyjęcia zdarzenia, a 202 oznacza, że zdarzenie zostało zakolejkowane, a nie zapisane. Proces roboczy odpowiada za przenoszenie zdarzeń do ClickHouse. Jeśli zdarzenia są przyjmowane, ale nie pojawiają się w panelu sterowania, oznacza to, że proces roboczy jest zablokowany, co potwierdza stale rosnąca głębokość kolejki Valkey. Typowe przyczyny to błędne dane uwierzytelniające ClickHouse w worker.env lub brak uprawnień do tabeli dodanej w wyniku niedawnej migracji.
Utrzymanie kolektora publicznie i panelu za uwierzytelnianiem
Caddy jest dostarczany wewnątrz pliku compose i automatycznie uzyskuje certyfikaty dla wszystkich czterech nazw, więc domyślna ścieżka nie wymaga dodatkowej konfiguracji proxy. Jeśli na serwerze działa już odwrotne proxy nginx, należy umieścić stos za dostarczonym infra/selfhost/nginx.conf.example, zachowując nienaruszoną obsługę nagłówków:
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 "";Kolektor wylicza dzienny skrót odwiedzającego na podstawie adresu IP klienta, dlatego musi pobierać ten adres bezpośrednio z połączenia, a nie z nagłówka. Przekazywanie CF-Connecting-IP z niezaufanego węzła pozwala każdemu wywołującemu podać dowolny adres, co jednocześnie zafałszowuje geolokalizację i zawyża liczbę odwiedzin.
Dostęp jest rozdzielony według nazwy hosta. c. oraz rt. muszą być dostępne dla każdego odwiedzającego każdą mierzoną witrynę, dlatego nie należy stosować przed nimi uwierzytelniania basic auth ani list dozwolonych adresów IP. app. oraz api. muszą być dostępne tylko dla osób zalogowanych. Własny mechanizm uwierzytelniania aplikacji chroni panel: logowanie hasłem jest domyślnie włączone przez AUTH_PASSWORD_SIGNIN=enabled w env/api.env, a przyciski Google lub GitHub pojawiają się tylko wtedy, gdy dla danego dostawcy istnieją identyfikator klienta (client ID) oraz klucz tajny (client secret). Magiczne linki wymagają transportu poczty; bez niego API jedynie zapisuje wysyłkę w skrzynce nadawczej, więc wiadomość nie jest dostarczana, a błędy nie są zgłaszane. Jeśli inne własne aplikacje znajdują się już za jednym logowaniem Authentik, należy wcześniej zdecydować, czy panel ma do nich dołączyć, czy zachować własne konta, ponieważ pierwsze utworzone tutaj konto na stałe otrzymuje uprawnienia administratora.
Jedno ustawienie decyduje o tym, czy panel w ogóle działa. AUTH_TRUSTED_ORIGINS w env/api.env musi dokładnie odpowiadać źródłu (origin) panelu. Jeśli jest błędne lub go brakuje, API nie wysyła nagłówków CORS (cross-origin resource sharing), przeglądarka odrzuca każde wywołanie, a panel wyświetla układ strony bez danych, podczas gdy docker compose ps zgłasza, że wszystko działa poprawnie.
Podczas konfiguracji proxy warto zająć się zautomatyzowanym ruchem. Boty indeksujące trafiają do kolektora tak samo jak inni użytkownicy, a ich odsłony trafiają do ClickHouse i do statystyk. Blokowanie botów AI na poziomie serwera pozwala wyeliminować część tego ruchu z bazy danych, zanim wpłynie on negatywnie na dokładność danych i zajętość dysku.
Co oznacza brak plików cookie i jakie wiąże się z tym ograniczenie
W tym rozwiązaniu nie stosuje się plików cookie. Identyfikator odwiedzającego jest solonym haszem, sól zmienia się codziennie, a surowe adresy IP nigdy nie są zapisywane. Geolokalizacja jest rozwiązywana lokalnie w oparciu o plik DB-IP znajdujący się na dysku serwera, dzięki czemu żadne zapytanie dotyczące odwiedzającego nie opuszcza hosta. Utrzymywanie zapytań lokalnie eliminuje zewnętrznego dostawcę, ale nie zmienia charakteru danych; jest to to samo ograniczenie, które występuje, gdy uruchamiasz własną instancję SearXNG, a adres IP Twojego serwera staje się adresem widocznym dla wyszukiwarek.
Zaletą tego rozwiązania jest brak identyfikatora trwale zapisanego na urządzeniu odwiedzającego, co jest kluczowym czynnikiem kwalifikującym mechanizm śledzący do objęcia unijnymi przepisami ePrivacy dotyczącymi zgody. Konfiguracje oparte wyłącznie na danych zagregowanych są z tego powodu często uruchamiane bez banerów zgody. RODO nadal reguluje zakres i czas przechowywania danych, a ostateczna interpretacja prawna należy do Twojego doradcy, a nie do pliku README.
Koszt tego rozwiązania to brak możliwości śledzenia tożsamości między dniami. Rotacja soli oznacza, że osoba odwiedzająca witrynę w poniedziałek i ponownie w środę jest liczona jako dwóch różnych odwiedzających; jest to zamierzone działanie i nie ma od niego obejścia. Dzienne liczby unikalnych użytkowników są poprawne. Tygodniowe i miesięczne statystyki unikalnych użytkowników są budowane na podstawie danych dziennych i zawyżają zasięg, dlatego każda długookresowa metryka "powracającego użytkownika" nie mierzy tego, co sugeruje jej nazwa. Sesje i ścieżki użytkownika są wiarygodne w obrębie jednego dnia. Rotacja ANONYMOUS_IDENTITY_SECRET wywołuje ten sam efekt co zmiana dnia, dlatego należy traktować tę rotację jako zmianę w danych, a nie jako rutynową czynność porządkową.
Kolektor respektuje nagłówki Do Not Track oraz Global Privacy Control, czyli sygnały przeglądarki informujące witrynę o zakazie sprzedaży lub udostępniania danych osobowych. Znacznik skryptu posiada własne przełączniki dla tego samego obszaru: data-respect-gpc, data-respect-dnt oraz data-require-consent, który wstrzymuje zbieranie danych do momentu uzyskania zgody i zapamiętuje odpowiedź w localStorage pod kluczem oa.consent. Ustawienie data-storage="none" całkowicie wyłącza przechowywanie danych w przeglądarce.
Dlaczego dysk zapełnia się po sześciu miesiącach
To najczęstsza przyczyna awarii samodzielnie hostowanych serwerów analitycznych, przy czym zdarzenia zazwyczaj nie są głównym powodem.
Zacznij od obrazów. Wydanie publikuje ich dziesięć, co zajmuje około 13 GB na dysku. Aktualizacja pobiera nową generację przed usunięciem starej, więc przez pewien czas przechowywane są dwie generacje. To wypełnia większość z wymaganych 25 GB, zanim jeszcze pojawi się pierwsza odsłona strony.
Następnie migawki. snapshot.sh zatrzymuje stos, archiwizuje oba wolumeny danych wraz ze wszystkimi sekretami i restartuje usługę. Tylko kopie typu cold są tutaj bezpieczne, ponieważ ClickHouse scala części w tle, a kopia wykonana w trakcie scalania nie jest spójna. upgrade.sh wykonuje taką kopię automatycznie przed każdą aktualizacją, więc archiwa gromadzą się na tym samym dysku, dopóki nie zostaną ograniczone.
./snapshot.sh create --label before-something-risky
./snapshot.sh list
./snapshot.sh --keep 3Na hoście zbliżającym się do limitu usuń poprzednią generację przed aktualizacją. Jest to bezpieczne podczas pracy stosu, ponieważ obrazy obsługujące uruchomione kontenery są nadal referencjonowane:
docker image prune -a -fNastępnie same zdarzenia. ClickHouse silnie kompresuje dane kolumnowe, więc objętość surowych zdarzeń rośnie wolniej, niż większość osób zakłada, a tabele podsumowujące, z których korzysta pulpit nawigacyjny, są małe w porównaniu z tabelą surową. Mierz, zamiast zgadywać:
docker system df -v
docker compose exec clickhouse df -h /var/lib/clickhouseAby uzyskać dane dla poszczególnych tabel, uruchom to polecenie z poświadczeniami ClickHouse, które generator zapisał w infra/selfhost/env/:
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;Wykonaj ten pomiar w pierwszym i czwartym tygodniu. Dwa punkty pozwalają wyznaczyć tempo wzrostu, a tempo wzrostu informuje, kiedy należy zwiększyć rozmiar wolumenu. Przewodnik po self-hostingu nie dokumentuje żadnego parametru retencji ani czasu życia (TTL) dla surowych zdarzeń na stan z sierpnia 2026, więc dobierz rozmiar dysku na podstawie zmierzonego tempa, zamiast zakładać, że stare wiersze wygasną samoczynnie.
Warto znać jedną pułapkę związaną z usuwaniem, zanim stanie się problemem. Usunięcie witryny lub konta dodaje zadanie do kolejki dla procesu worker, a ten proces wymaga ustawienia CLICKHOUSE_MAINTENANCE_USER oraz CLICKHOUSE_MAINTENANCE_PASSWORD, przy czym w ClickHouse musi istnieć pasujący użytkownik oa_maintenance. Bez nich usuwanie pozostaje w kolejce na zawsze. Witryna znika z pulpitu nawigacyjnego, ale wszystkie wiersze pozostają na dysku, więc sprawia to wrażenie wykonania czyszczenia bez odzyskania miejsca.
Aktualizacje i trzy rodzaje kosztów
git fetch --tags
git checkout "$(git tag -l 'v*' --sort=-v:refname | sed '/-/d' | head -1)"
cd infra/selfhost
./upgrade.shupgrade.sh wyświetla trzy rodzaje kosztów przed wykonaniem operacji. Przestój jest realny: zdarzenia, których próba rejestracji nastąpiła w czasie niedostępności kolektora, zostają utracone, ponieważ tracker nie ponawia prób ich wysłania. Wycofanie zmian (rollback) powoduje utratę danych, gdyż rollback.sh --to backups/<snapshot> całkowicie zastępuje oba magazyny i odrzuca każdy wiersz zapisany po wykonaniu migawki. Trzecim kosztem jest przestrzeń dyskowa, zajmowana przez wspomniany stos migawek.
Łatwo popełnić błąd w dwóch zasadach restartu. Uruchom bramę zapytań (query gateway) przed API, ponieważ nowsza wersja API wysyła pola zapytań, których starsza brama nie akceptuje. ClickHouse wymaga odtworzenia (recreate), a nie restartu, ponieważ docker compose restart używa oryginalnego środowiska kontenera i ignoruje wprowadzone zmiany:
docker compose up -d --force-recreate clickhousePanel sterowania (dashboard) zawiera analogiczną pułapkę. Trzy źródła NEXT_PUBLIC_* w env/web.env są kompilowane do pakietu przeglądarkowego i podstawiane w momencie startu kontenera. Dlatego panel odwołujący się do błędnej nazwy hosta naprawia się za pomocą docker compose up -d --force-recreate web, a nigdy przez restart. Dziennik kontenera webowego wyświetla źródła, z którymi został uruchomiony; jest to najszybszy sposób na potwierdzenie, że poprawka została wdrożona.
Jeśli ClickHouse odmawia uruchomienia po edycji konfiguracji, przeczytaj pierwszą linię jego dziennika. Linia rozpoczynająca się od oa-entrypoint: oznacza, że punkt wejścia (entrypoint) odrzuca ustawioną wartość. Każdy inny komunikat zazwyczaj oznacza, że plik konfiguracyjny zawiera nieprawidłowy kod XML. Najczęstszą przyczyną jest podwójny myślnik wewnątrz komentarza XML, co jest niedozwolone.
AGPL-3.0 oraz nazwa
Kod jest objęty licencją AGPL-3.0. Uruchamianie go w niezmienionej formie na własnych stronach nie wiąże się z żadnym obowiązkiem publikacji. Obowiązek ten powstaje w momencie modyfikacji kodu i uruchomienia tak zmienionej wersji jako usługi sieciowej: licencja wymaga wówczas udostępnienia zmodyfikowanego kodu źródłowego użytkownikom tej usługi. Dotyczy to udostępniania klientom paneli nawigacyjnych w Twojej instancji oraz dołączania oprogramowania do produktów przeznaczonych na sprzedaż. Utrzymywanie zmian w publicznym forku spełnia ten wymóg bez konieczności podejmowania dodatkowych działań.
Marka jest oddzielona od kodu. Nazwa "OpenAnalytics" oraz domena hostowana przez projekt identyfikują instancję obsługiwaną przez autorów i nie stanowią części udzielonej licencji. Twoje wdrożenie uruchamia oprogramowanie bez użycia tej marki, dlatego nadaj usłudze własną nazwę, zanim udostępnisz ją płacącym klientom.
FAQ
Czy mogę uruchomić OpenAnalytics na VPS z 1 GB pamięci RAM?
Nie. Projekt wymaga około 4 GB pamięci RAM oraz 25 GB wolnego miejsca na dysku, ponieważ jedno wdrożenie uruchamia sześć usług aplikacyjnych obok Postgres, ClickHouse oraz dwóch instancji Valkey. Sam ClickHouse nie jest lekkim procesem. Na maszynie z 1 GB pamięci kontenery startują, a następnie mechanizm kernel out-of-memory killer wyłącza jeden z nich, zazwyczaj ClickHouse. Jeśli plan 1 GB jest sztywnym ograniczeniem, należy użyć narzędzia typu single-binary, takiego jak GoatCounter, które działa w oparciu o SQLite bez zewnętrznej bazy danych.
Czy muszę stosować baner cookies w OpenAnalytics?
To pytanie do prawnika, jednak fakty techniczne przemawiają na korzyść użytkownika. System nie używa plików cookie, identyfikator użytkownika jest solonym hashem, który zmienia się codziennie, a surowe adresy IP nigdy nie są zapisywane, więc nie powstaje trwały identyfikator odwiedzającego. RODO nadal reguluje zakres przechowywanych danych i czas ich retencji. Jeśli zbieranie danych ma być jawnie autoryzowane, należy ustawić data-require-consent w tagu skryptu: tracker nie zbiera wtedy żadnych danych do momentu wyrażenia zgody i przechowuje odpowiedź w localStorage w ramach oa.consent.
Dlaczego zdarzenia zwracają kod 202, ale nie pojawiają się w panelu?
202 oznacza, że kolektor przyjął i zakolejkował zdarzenie, a nie że zostało ono zapisane. Proces roboczy (worker) opróżnia tę kolejkę do ClickHouse, więc pusty panel przy udanych żądaniach wskazuje na problem z workerem. Należy przeczytać docker compose logs --tail=50 worker i monitorować głębokość kolejki Valkey. Stale rosnąca kolejka oznacza, że worker jest zablokowany, a najczęstszą przyczyną są błędne dane logowania do ClickHouse w worker.env lub brak uprawnień do tabeli utworzonej podczas ostatniej migracji.
Dlaczego panel jest pusty, mimo że wszystkie kontenery działają poprawnie?
W pierwszej kolejności należy sprawdzić AUTH_TRUSTED_ORIGINS w env/api.env. Wartość ta musi dokładnie odpowiadać źródłu (origin) panelu; w przeciwnym razie API nie wysyła nagłówków CORS, przeglądarka odrzuca każde wywołanie, a użytkownik widzi działający układ strony bez danych. Drugą kwestią do sprawdzenia są trzy wartości NEXT_PUBLIC_* w env/web.env, które są podstawiane podczas startu kontenera web. Ich poprawa wymaga docker compose up -d --force-recreate web, ponieważ zwykły restart zachowuje stare wartości.
Czy licencja AGPL-3.0 zabrania oferowania tego rozwiązania klientom?
Nie, nakłada ona jeden warunek. Uruchomienie kodu w wersji niezmienionej nie wiąże się z żadnymi zobowiązaniami. W przypadku modyfikacji kodu i udostępniania go jako usługi dla innych osób, należy zapewnić tym użytkownikom dostęp do zmodyfikowanego kodu źródłowego, co można zrealizować poprzez publiczny fork. Ponadto nazwa "OpenAnalytics" nie jest licencjonowana wraz z kodem, więc każda usługa komercyjna musi posiadać własną nazwę.