Self-hosted Umami: analytics bez cookies, bez bannera, bez Google'a
Date Published

Google Analytics na małej stronie wymaga cookie bannera, third-party skryptu z googletagmanager.com i wysyłki danych na serwery Google'a w USA. Po co ten cyrk dla 200 wizyt dziennie? No właśnie. Self-hosted Umami załatwia to samo na własnym VPS-ie: jeden mały kontener plus Postgres, zero cookies, dane na Twoim serwerze. Setup zajmuje 5 minut. Jeśli wiesz gdzie są pułapki.
Co potrzebujesz
- VPS z Dockerem (~100 MB RAM na Umami + ~50 MB na Postgres)
- Subdomena typu stats.example.com z A-recordem na IP VPS-a
- Reverse proxy z auto-certem Let's Encrypt (Traefik, Caddy, NPM, cokolwiek już masz)
Ja postawiłem to przez Coolify (one-click w sekcji Services → Umami), ale to nie jest wymóg. Umami to publiczny obraz ghcr.io/umami-software/umami i działa na każdej maszynie z Dockerem.
4 kroki setupu
1. DNS. A-record stats.example.com → IP serwera. Sprawdź dig +short stats.example.com zanim ruszysz dalej — bez tego Let's Encrypt nie wystawi certa.
2. Umami + Postgres. Minimalny compose.yaml:
1services:2 umami:3 image: ghcr.io/umami-software/umami:3.0.34 environment:5 DATABASE_URL: postgres://umami:strong-pass@db:5432/umami6 APP_SECRET: ${APP_SECRET} # openssl rand -base64 327 TRACKER_SCRIPT_NAME: ascii.js # bypass adblock list8 DISABLE_TELEMETRY: 19 depends_on: [db]10 db:11 image: postgres:16-alpine12 environment:13 POSTGRES_USER: umami14 POSTGRES_PASSWORD: strong-pass15 POSTGRES_DB: umami
3. Pierwszy login. https://stats.example.com, login admin / umami. Pierwsza rzecz: zmień hasło. Druga: Settings → Websites → Add Website (Domain: example.com). Skopiuj Website ID, to UUID w formacie aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee.
4. Wstrzyknij tracker. W head strony:
1<script defer2 src="https://stats.example.com/ascii.js"3 data-website-id="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"4 data-do-not-track="true">5</script>
data-do-not-track="true" szanuje browser DNT, czyli GDPR data-minimization za darmo.
Pułapki, na które się nadziejesz
CSP. Jeśli masz strict Content-Security-Policy (a powinieneś), tracker padnie cicho. Domena Umami musi wejść do dwóch dyrektyw:
1script-src 'self' https://stats.example.com2connect-src 'self' https://stats.example.com
Pierwsza ładuje skrypt, druga puszcza POST /api/send z eventami.
Adblock. uBlock Origin i EasyPrivacy blokują domyślną ścieżkę /script.js. Dlatego w configu jest TRACKER_SCRIPT_NAME=ascii.js. Własna nazwa plus first-party domena (stats.example.com, nie cloud.umami.is) zbija wykrywalność do minimum. Jak dalej coś filtruje, zmień nazwę na cokolwiek genericznego (t.js, events.js).
Coolify-specific gotcha. Jeżeli stawiasz przez Coolify, pole Domains dla services wymaga formatu https://stats.example.com:3000. Port :3000 to wskaźnik dla Coolify który wewnętrzny port mapować, a nie publiczny. Traefik i tak wystawi to na 443. Counter-intuitive, ale tylko w Coolify; w czystym Docker Compose ten problem nie istnieje.
Co dostajesz
Czysty dashboard z page-viewami, top pages, referrers, kraje, urządzenia. Bez cookie bannera, bez ekranu zgód, bez fingerprint trackera, bez przekazywania danych do Google'a. Mała strona spokojnie zmieści się w 200 MB RAM-u, taniej niż jeden płatny GA4 add-on.
I to jest cała magia self-hosted analytics w 2026: jeden kontener, jedna subdomena, pięć minut roboty. Reszta to już Twój ruch.