Cookieless website analytics for getcmdr.com.
- getcmdr.com website ID:
5ea041ae-b99d-4c31-b031-89c4a0005456
The website's local .env file (at apps/website/.env) contains Umami API credentials:
UMAMI_API_URL=https://anal.veszelovszki.com
UMAMI_USERNAME=...
UMAMI_PASSWORD='...' # single-quoted because it contains special chars
These are for scripts and API calls only; the website runtime uses PUBLIC_UMAMI_HOST and PUBLIC_UMAMI_WEBSITE_ID
instead.
Useful when the API shows zero but you need to verify:
ssh hetzner "docker exec umami-db psql -U umami -d umami -c \
\"SELECT created_at, url_path FROM website_event \
WHERE website_id = '5ea041ae-b99d-4c31-b031-89c4a0005456' \
ORDER BY created_at DESC LIMIT 10;\""- CSP headers: The nginx CSP in
apps/website/nginx.confmust allowanal.veszelovszki.comin bothscript-src(loads the script) andconnect-src(sends events). Runcurl -sI https://getcmdr.com | grep content-security-policyto verify. TRACKER_SCRIPT_NAME: Set tomamiin the Umamidocker-compose.yml. The script is served at/mami(no.jsextension: Umami uses the value literally as the path). Short names likesbreak the Umami API because Next.js middleware matches any URL path containing the tracker name and rewrites it to serve the script. Keep the name distinctive.
Umami's docker-compose.yml and Caddy config live in the hetzner-server repo. Never edit files directly on the
server. The process:
- Edit the file in the local
hetzner-serverrepo - Commit and push
- On the server:
ssh hetzner "cd ~/hetzner-server && git pull" - Restart:
ssh hetzner "cd ~/hetzner-server/umami && docker compose down && docker compose up -d"