From 7fd3bb37e6654f265f3a7ec5a8cb7fdd7ea65b24 Mon Sep 17 00:00:00 2001 From: oskar Date: Wed, 24 Jun 2026 16:24:01 +0200 Subject: [PATCH] feat(umami): add Umami analytics service + deploy Two-container stack (umami + postgres) deployed to the hetzner host via a remote Docker context, attached to npm_default so Nginx Proxy Manager fronts stats.gethumanai.pl. Secrets live in a gitignored .env. Co-Authored-By: Claude Opus 4.8 (1M context) --- services/umami/.env.example | 10 +++++ services/umami/.gitignore | 1 + services/umami/README.md | 57 ++++++++++++++++++++++++++++ services/umami/deploy.sh | 63 +++++++++++++++++++++++++++++++ services/umami/docker-compose.yml | 54 ++++++++++++++++++++++++++ 5 files changed, 185 insertions(+) create mode 100644 services/umami/.env.example create mode 100644 services/umami/.gitignore create mode 100644 services/umami/README.md create mode 100755 services/umami/deploy.sh create mode 100644 services/umami/docker-compose.yml diff --git a/services/umami/.env.example b/services/umami/.env.example new file mode 100644 index 0000000..cc36726 --- /dev/null +++ b/services/umami/.env.example @@ -0,0 +1,10 @@ +# Copy to .env and fill in. Never commit .env. +# Generate secrets with: +# openssl rand -hex 32 # APP_SECRET +# openssl rand -hex 24 # POSTGRES_PASSWORD + +# Signing secret for sessions/tokens. Changing it invalidates existing sessions. +APP_SECRET= + +# PostgreSQL password (shared by the umami app and the umami-db container). +POSTGRES_PASSWORD= diff --git a/services/umami/.gitignore b/services/umami/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/services/umami/.gitignore @@ -0,0 +1 @@ +.env diff --git a/services/umami/README.md b/services/umami/README.md new file mode 100644 index 0000000..95e0e49 --- /dev/null +++ b/services/umami/README.md @@ -0,0 +1,57 @@ +# Umami + +Self-hosted privacy-friendly web analytics, served at **stats.gethumanai.pl**. + +Runs as two containers (`umami` + `umami-db` PostgreSQL) on the **hetzner** host, +deployed via a remote Docker context — same convention as `humanai-web`. +`umami` joins the `npm_default` network so Nginx Proxy Manager can proxy it by +container name; no host port is exposed. + +## Layout + +| File | Purpose | +|---|---| +| `docker-compose.yml` | umami app + postgres + volume + networks | +| `.env.example` | template for the two required secrets | +| `.env` | real secrets — **gitignored, never commit** | +| `deploy.sh` | pulls images on the remote, starts the stack, smoke-tests `/api/heartbeat` | + +## First-time setup + +```bash +cp .env.example .env +# fill in: +# openssl rand -hex 32 -> APP_SECRET +# openssl rand -hex 24 -> POSTGRES_PASSWORD +``` + +## Deploy + +```bash +./deploy.sh +``` + +The script creates the `hetzner` Docker context if missing, verifies the +`npm_default` network exists, runs `docker compose up -d --pull always`, waits +for the `umami` healthcheck, and smoke-tests the heartbeat endpoint. + +## Manual step in Nginx Proxy Manager + +Add a Proxy Host: + +| Field | Value | +|---|---| +| Domain | `stats.gethumanai.pl` | +| Scheme | `http` | +| Forward hostname | `umami` | +| Forward port | `3000` | +| Websockets | on | +| SSL | request a Let's Encrypt cert + Force SSL | + +Then open , log in with the default **admin / umami**, +and **change the password immediately**. + +## Add the tracking snippet + +In Umami: *Settings → Websites → Add* (domain `gethumanai.pl`), then copy the +generated `