Umami Analytics¶
Overview¶
Umami is a self-hosted, privacy-friendly web analytics platform. No cookies, no cross-site tracking, GDPR-compliant by default. It replaces Google Analytics for Aletheia, Helios, and the practice websites.
- URL: https://analytics.groupe-suffren.com
- Container:
umami(imageghcr.io/umami-software/umami:postgresql-latest) - Database:
umamion the shared PostgreSQL container - Config source:
umami/docker-compose.ymlin the aether repo - Env file:
/opt/docker/umami/.env(decrypted fromumami/.env.enc)
First-time Setup¶
Run once on a new server:
This bootstraps everything: creates the umami database and user, obtains the SSL certificate,
deploys nginx config, and starts the container. See initialization
for the full step-by-step breakdown.
First Login¶
After make umami-init completes:
- Visit https://analytics.groupe-suffren.com
- Log in with the default credentials:
- Username:
admin - Password:
umami
- Username:
Change the default password immediately
The default admin/umami credentials are publicly known and documented by Umami.
Go to Profile → Password and set a strong password before doing anything else.
Adding a Website to Track¶
- In Umami, go to Settings → Websites → Add Website
- Fill in:
- Name: human-readable label (e.g.,
Cabinet Dentaire Aubagne) - Domain: the public domain (e.g.,
cabinet-dentaire-aubagne.fr)
- Name: human-readable label (e.g.,
- Save. Umami generates a Website ID (UUID).
- Copy the Website ID — it's needed to wire the tracker into Helios/Aletheia.
Wiring the Tracker¶
Helios (Next.js practice sites)¶
Helios reads the Website ID from a per-practice config. Add the UUID to the practice's
Helios configuration (see Helios docs for the
exact location). The tracking script is included automatically in the site's <head> by
the TrackPageView component.
Aletheia¶
Aletheia stores Website IDs on the SiteConfig model per practice. Update the value via
the admin or a fixture. The base template renders the tracking snippet when the field is set.
Dashboard and Reports¶
Default dashboard shows per-website metrics: visitors, pageviews, sessions, bounce rate, average visit duration. Click a website to drill down into:
- Pages — top pages by views, time on page
- Referrers — where visitors come from
- Browsers, OS, devices — client breakdown
- Countries, regions, cities — geographic data
- Events — custom events you've sent via
umami.track()
User Management¶
- Go to Settings → Users to add team members
- Each user can be assigned to specific websites or teams
- Roles: Admin (full access), View Only (read-only dashboards), Team Owner/Manager/Member
For agency-style access (e.g. a content writer who should only see one practice's data), create a Team, add the website(s), and invite the user into the team.
Backup and Restore¶
Umami data lives in the umami PostgreSQL database, which is backed up daily by the regular
cron job (see backups — umami is in the Databases backed up list).
Restore¶
Same procedure as any other database — see backups — restore a database from backup,
substituting umami for aletheia_prod.
Upgrading¶
Umami uses the rolling postgresql-latest tag. To force an upgrade:
Alternatively, pin a specific version by editing umami/docker-compose.yml, then
make deploy && make restart-umami.
Backup first
Major Umami releases sometimes require database migrations that run on first startup.
Take a fresh backup before upgrading: /opt/docker/backups/scripts/backup.sh.
Operations¶
# Container status
docker ps --filter name=umami
# Logs
docker logs --tail 100 umami
# Restart (config change or stuck container)
cd /opt/docker/aether/repo && make restart-umami
# Database shell
docker exec -it shared_postgres psql -U umami -d umami
Troubleshooting¶
Dashboard shows no data: check that the website's tracking snippet is actually loading —
open the site in a browser, open devtools, look for a request to
analytics.groupe-suffren.com/script.js. If missing, the Website ID is wrong or the
tracker isn't wired in.
Container unhealthy: check the database connection. Umami can't start if shared_postgres
is down or if the DATABASE_URL env var is wrong.
"Unauthorized" on login: password was changed but you've forgotten it. Reset via the database:
# This generates a bcrypt hash for the string "temp_pwd"
docker exec shared_postgres psql -U umami -d umami -c \
"UPDATE account SET password = '\$2b\$10\$...' WHERE username = 'admin';"
Generate the hash locally with htpasswd -bnBC 10 "" "<new-password>" | tr -d ':\n' | sed 's/$2y/$2b/'.