Voeg self-hosted Umami analytics + UptimeRobot uptime dashboard toe
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -17,8 +17,8 @@ Client-side errors (JavaScript crashes, broken links) should be logged, but the
|
||||
|
||||
### Dashboards
|
||||
A combination of:
|
||||
- **Website analytics** (visitors, page views, basic engagement) — e.g. a simple/free tool such as Plausible, Umami, or Google Analytics/Search Console.
|
||||
- **Uptime dashboard** (site reachability) — e.g. an external monitoring service such as UptimeRobot or Better Uptime.
|
||||
- **Website analytics**: **decided** — self-hosted Umami (Podman on the webserver Pi, see `operations/monitoring/umami-setup.md`), chosen over GA4/hosted Plausible for privacy-friendliness and no recurring cost.
|
||||
- **Uptime dashboard**: **decided** — UptimeRobot, chosen over Better Uptime for its established free tier.
|
||||
|
||||
(Original Question 6 = C, "Both (analytics + uptime dashboard)".)
|
||||
|
||||
@@ -28,7 +28,7 @@ A combination of:
|
||||
|
||||
## Open Action Items
|
||||
1. **Decide logging destination**: choose between "browser console only" (no central storage, manual debugging) or a free/low-cost external error-tracking service (e.g. Sentry free tier) once this becomes a priority. Until decided, `monitoring-setup.md` documents both options so either can be adopted without re-doing this stage.
|
||||
2. **Pick concrete analytics + uptime tools**: `monitoring-setup.md` lists candidate free-tier tools; final tool selection/account creation is a manual follow-up outside this workflow (no code changes required to swap providers, since neither is wired into the codebase yet beyond an optional embed snippet).
|
||||
2. ~~Pick concrete analytics + uptime tools~~ — **Resolved**: self-hosted Umami + UptimeRobot (see `monitoring-setup.md` and `umami-setup.md`). Remaining manual follow-ups: actually deploying the Umami containers on the Pi, registering DNS/SSL for `analytics.slpsoftware.nl`, creating the UptimeRobot monitor, and setting the `VITE_UMAMI_SCRIPT_URL`/`VITE_UMAMI_WEBSITE_ID` Gitea repository variables.
|
||||
|
||||
## Rationale
|
||||
Given this is a simple static marketing site with no backend and no existing monitoring, the aim is lightweight, low/no-cost observability: enough to know if the site is down (uptime) and how it's being used (analytics), plus a documented (if not yet finalized) path for capturing client-side errors. Alerting was deliberately left out to avoid over-engineering a notification pipeline before there's a concrete trigger/audience for it.
|
||||
|
||||
@@ -25,38 +25,49 @@ The destination was not finalized (original Question 3 = C). Two supported optio
|
||||
|
||||
## Dashboards
|
||||
|
||||
### Website analytics
|
||||
Pick one (all have generous free tiers suitable for a small marketing site):
|
||||
### Website analytics — decided: self-hosted Umami
|
||||
**Decided**: self-hosted Umami, running via Podman on the webserver Pi (Pi Main,
|
||||
`192.168.1.103:3000`), reachable for the dashboard itself via `analytics.slpsoftware.nl`
|
||||
(reverse-proxied + SSL via certbot, same pattern as `test.slpsoftware.nl`). Chosen over
|
||||
GA4 for privacy-friendliness (typically no cookie banner needed) and full self-hosted
|
||||
control, and over a hosted Umami/Plausible plan to avoid recurring cost.
|
||||
|
||||
| Option | Notes |
|
||||
|---|---|
|
||||
| Plausible / Umami | Privacy-friendly, lightweight, no cookie banner typically required; self-hosted or low-cost hosted tier |
|
||||
| Google Analytics (GA4) / Search Console | Free, widely known, but heavier script and involves third-party data sharing (cookie/consent implications) |
|
||||
- Full step-by-step setup: `operations/monitoring/umami-setup.md` (Podman/compose files,
|
||||
systemd auto-start, reverse proxy + SSL, website registration).
|
||||
- Example config: `operations/deployment/umami/podman-compose.yml.example` +
|
||||
`.env.example`; `operations/deployment/nginx/analytics-nginx.conf.example`.
|
||||
- The tracking script is injected client-side by `src/components/UmamiAnalytics.tsx`,
|
||||
gated on two build-time variables (`VITE_UMAMI_SCRIPT_URL`, `VITE_UMAMI_WEBSITE_ID`),
|
||||
wired into `continuous_integration.yaml`'s `Build` step as Gitea repository variables,
|
||||
not secrets (same pattern as `VITE_SENTRY_DSN`). It never loads during local
|
||||
development (`pnpm dev`), even if those variables happen to be set, so local testing
|
||||
never pollutes visitor analytics.
|
||||
- Key metrics to surface: unique visitors, page views per route (Home, Packages, etc. —
|
||||
see `frontend-components.md`), and referral sources.
|
||||
|
||||
**Setup (once a tool is picked)**:
|
||||
1. Create an account/site entry with the chosen provider and obtain the tracking snippet or `<script>` tag.
|
||||
2. Add the snippet to `index.html` (or load it conditionally in `src/main.tsx`) — this is a documentation/config task, not something the current codebase needs restructuring for.
|
||||
3. Key metrics to surface: unique visitors, page views per route (Home, Packages, etc. — see `frontend-components.md`), and referral sources.
|
||||
### Uptime dashboard — decided: UptimeRobot
|
||||
**Decided**: UptimeRobot (free tier: up to 50 monitors, 5-minute check interval, optional
|
||||
e-mail notification on downtime — opportunistic, not a designed alerting feature per
|
||||
`monitoring-plan.md`). Chosen over Better Uptime for its long-standing free tier and
|
||||
simplicity for a single low-traffic site.
|
||||
|
||||
### Uptime dashboard
|
||||
Pick one:
|
||||
**Setup**:
|
||||
1. Create a free UptimeRobot account (https://uptimerobot.com).
|
||||
2. Register `test.slpsoftware.nl` as an HTTP(S) monitor now (checking for a `200`
|
||||
response); add the production URL once hosting is finalized (see
|
||||
`operations/deployment/deployment-plan.md` "Open Item") — still an open follow-up.
|
||||
3. Optional: publish a public status page if desired for transparency to visitors.
|
||||
4. Key metric to surface: uptime percentage / current status.
|
||||
|
||||
| Option | Notes |
|
||||
|---|---|
|
||||
| UptimeRobot | Free tier: up to 50 monitors, 5-minute check interval, optional e-mail notification on downtime (opportunistic, not a designed alerting feature per `monitoring-plan.md`) |
|
||||
| Better Uptime | Free tier available; similar capability, nicer public status page option |
|
||||
|
||||
**Setup (once a tool is picked)**:
|
||||
1. Register the production URL (once hosting is finalized — see `operations/deployment/deployment-plan.md` "Open Item") as an HTTP(S) monitor, checking for a `200` response.
|
||||
2. Optional: publish a public status page if desired for transparency to visitors.
|
||||
3. Key metric to surface: uptime percentage / current status.
|
||||
No application code changes are needed for UptimeRobot — it works purely by polling the
|
||||
public URL from the outside, entirely independent of the site's own codebase.
|
||||
|
||||
## Summary Table
|
||||
|
||||
| Concern | Approach | Status |
|
||||
|---|---|---|
|
||||
| Client-side errors | Logging (console today; Sentry free tier optional later) | Destination open item |
|
||||
| Visitor/usage insight | Analytics dashboard (Plausible/Umami/GA4) | Tool selection open item |
|
||||
| Site reachability | Uptime dashboard (UptimeRobot/Better Uptime) | Tool selection + production URL open item |
|
||||
| Visitor/usage insight | Analytics dashboard (self-hosted Umami) | Tool decided; deployment (Podman on Pi Main + `analytics.slpsoftware.nl`) is a manual follow-up, see `umami-setup.md` |
|
||||
| Site reachability | Uptime dashboard (UptimeRobot) | Tool decided; account creation + production URL are manual follow-ups |
|
||||
| Alerting | Out of scope | Not configured |
|
||||
| Shared infrastructure reuse | Out of scope | None exists yet |
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# Umami Self-Hosted Setup (Analytics)
|
||||
|
||||
Stapsgewijze handleiding om Umami (self-hosted website-analytics) op te zetten op de
|
||||
webserver-Pi (Pi Main, `192.168.1.103`) met Podman, en bereikbaar te maken via
|
||||
`analytics.slpsoftware.nl`. Dit vult het "Analytics/uptime dashboard" open item uit
|
||||
`operations/production-readiness-checklist.md` in voor het analytics-gedeelte.
|
||||
|
||||
## Vereisten
|
||||
- Podman is al aanwezig op de Pi (bevestigd door de gebruiker).
|
||||
- `podman-compose` geïnstalleerd: `pip3 install --user podman-compose` (of via de package
|
||||
manager van je distro, indien beschikbaar).
|
||||
- DNS: een A-record voor `analytics.slpsoftware.nl` dat naar het publieke IP van de
|
||||
reverse-proxy-Pi wijst (dezelfde Pi die ook `test.slpsoftware.nl` afhandelt).
|
||||
|
||||
## 1. Umami + database opzetten (op de webserver-Pi)
|
||||
1. Maak een map aan, bv. `~/umami/`, en kopieer daarin:
|
||||
- `operations/deployment/umami/podman-compose.yml.example` → `~/umami/podman-compose.yml`
|
||||
- `operations/deployment/umami/.env.example` → `~/umami/.env`
|
||||
2. Vul in `~/umami/.env` een echte `POSTGRES_PASSWORD` en `APP_SECRET` in (bv. via
|
||||
`openssl rand -base64 32` voor beide — gebruik twee verschillende waarden).
|
||||
3. Start de containers:
|
||||
```bash
|
||||
cd ~/umami
|
||||
podman-compose up -d
|
||||
```
|
||||
4. Controleer dat Umami draait en bereikbaar is op het interne netwerk:
|
||||
```bash
|
||||
curl http://192.168.1.103:3000/api/heartbeat
|
||||
```
|
||||
Dit zou een JSON-antwoord met `"ok"` moeten teruggeven.
|
||||
|
||||
## 2. Automatisch starten na reboot (systemd user service)
|
||||
Podman-compose start niet vanzelf op na een herstart van de Pi, tenzij je dit expliciet
|
||||
instelt. Omdat rootless Podman hier al gebruikt wordt, is een systemd **user**-service de
|
||||
eenvoudigste aanpak:
|
||||
|
||||
1. Zorg dat de gebruiker-sessie blijft "linger-en" na uitloggen/reboot:
|
||||
```bash
|
||||
sudo loginctl enable-linger $(whoami)
|
||||
```
|
||||
2. Maak `~/.config/systemd/user/umami.service` aan:
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Umami analytics (podman-compose)
|
||||
After=network-online.target
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=%h/umami
|
||||
ExecStart=/usr/bin/podman-compose up
|
||||
ExecStop=/usr/bin/podman-compose down
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
```
|
||||
3. Activeer en start de service:
|
||||
```bash
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now umami.service
|
||||
```
|
||||
|
||||
## 3. Reverse proxy + SSL (op de reverse-proxy-Pi)
|
||||
1. Kopieer `operations/deployment/nginx/analytics-nginx.conf.example` naar bv.
|
||||
`/etc/nginx/sites-available/slpsoftware-analytics.conf` op de reverse-proxy-Pi, en maak
|
||||
een symlink in `sites-enabled`.
|
||||
2. Zorg dat het DNS-record voor `analytics.slpsoftware.nl` al actief is, en draai dan:
|
||||
```bash
|
||||
sudo certbot --nginx -d analytics.slpsoftware.nl
|
||||
```
|
||||
3. Herlaad nginx: `sudo nginx -t && sudo systemctl reload nginx`.
|
||||
4. Test: open `https://analytics.slpsoftware.nl` in de browser — je zou het
|
||||
Umami-inlogscherm moeten zien (standaard inloggegevens: `admin` / `umami`, **direct
|
||||
wijzigen na eerste login**).
|
||||
|
||||
## 4. Website registreren in Umami en het website-ID ophalen
|
||||
1. Log in op `https://analytics.slpsoftware.nl` en wijzig direct het standaardwachtwoord.
|
||||
2. Ga naar **Settings → Websites → Add website** en vul in:
|
||||
- Name: `SLP Software` (of naar keuze)
|
||||
- Domain: het domein van de daadwerkelijke website (bv. `slpsoftware.nl` of
|
||||
`test.slpsoftware.nl`, afhankelijk van welke omgeving je eerst wilt meten)
|
||||
3. Na het opslaan toont Umami een **Website ID** (een UUID) — dit heb je nodig voor de
|
||||
volgende stap.
|
||||
|
||||
## 5. Tracking script koppelen aan de website (build-configuratie)
|
||||
De React-app (`src/components/UmamiAnalytics.tsx`) injecteert het Umami tracking-script
|
||||
automatisch, mits de volgende twee build-time variabelen zijn ingesteld — beide zijn
|
||||
**geen secrets** (client-side zichtbaar), dus als Gitea Actions **repository variables**
|
||||
(niet secrets), net als `VITE_SENTRY_DSN`:
|
||||
|
||||
| Variabele | Waarde |
|
||||
|---|---|
|
||||
| `VITE_UMAMI_SCRIPT_URL` | `https://analytics.slpsoftware.nl/script.js` |
|
||||
| `VITE_UMAMI_WEBSITE_ID` | het Website ID uit stap 4 |
|
||||
|
||||
Stel deze in via **Gitea → Repository Settings → Actions → Variables**. Zodra beide
|
||||
bestaan, pakt de eerstvolgende build ze automatisch op; zonder deze variabelen slaat de
|
||||
app het inladen van het script gewoon over (geen crash, geen tracking).
|
||||
|
||||
**Lokaal (`pnpm dev`)**: het tracking-script wordt hier bewust nooit geladen (zie
|
||||
`UmamiAnalytics.tsx`), zodat lokaal testen de bezoekersstatistieken niet vervuilt. Wil je
|
||||
dit toch lokaal testen, zet dan tijdelijk beide waarden in `.env.local` (zie
|
||||
`.env.example`) én verwijder tijdelijk de `import.meta.env.DEV`-check.
|
||||
|
||||
## Openstaande handmatige stappen
|
||||
- [ ] `podman-compose up -d` daadwerkelijk draaien op Pi Main.
|
||||
- [ ] Systemd user-service instellen voor auto-start na reboot.
|
||||
- [ ] DNS-record + certbot voor `analytics.slpsoftware.nl` op de reverse-proxy-Pi.
|
||||
- [ ] Standaard Umami-wachtwoord direct wijzigen na eerste login.
|
||||
- [ ] Website aanmaken in Umami en het Website ID overnemen.
|
||||
- [ ] `VITE_UMAMI_SCRIPT_URL` en `VITE_UMAMI_WEBSITE_ID` als Gitea repository variables instellen.
|
||||
Reference in New Issue
Block a user