# Agent guide – Umami analytics stack This repo is a **self-hosted Umami analytics stack** for deployment via **Portainer** (stack from repository). It does not contain application source code; it defines the Docker Compose stack, CI, and docs. ## Purpose - Run [Umami](https://umami.is) (privacy-focused analytics) with PostgreSQL. - Reverse proxy: **Traefik** on the existing Docker network **marina-net**. - Deploy by adding the stack in Portainer and pointing it at this repo. ## Architecture - **marina-net** (external): Shared network where Traefik runs. Only the **umami** service from this stack is attached so Traefik can route to it. No database on this network. - **umami-backend** (internal): Only **umami** and **db** (PostgreSQL). Isolated from Traefik and the rest of the host. - **umami** is on both networks; **db** is only on umami-backend. - **Volumes**: One external volume, **umami-db-data**, for PostgreSQL data. Declared with `external: true`; the user must create it (e.g. `docker volume create umami-db-data`) before first deploy. ## Design decisions - **No secrets in repo**: All sensitive values (APP_SECRET, POSTGRES_PASSWORD, etc.) come from Portainer stack environment variables or a local `.env`; see `.env.example` and SETUP.md. - **External volume only**: DB data lives in a named external volume with an `umami-` prefix so it is explicit and portable. - **Traefik Host rule**: Default host is **analytics.mifi.holdings**; can be changed in `docker-compose.yml` if deploying elsewhere. HTTPS is handled by Traefik (entrypoints `web` and `websecure`); no cert paths in this repo. - **Variable substitution**: Compose uses `${POSTGRES_DB}`, `${POSTGRES_USER}`, `${POSTGRES_PASSWORD}`, `${APP_SECRET}` so Portainer (or `.env`) injects values. ## Key files | File | Role | | ------------------------- | --------------------------------------------------------------------------------------------------- | | `docker-compose.yml` | Stack definition: services, networks, volumes, Traefik labels, env substitution. | | `.env.example` | List of env var names and placeholders; no real values. | | `SETUP.md` | Human-facing setup: volume creation, secret generation, Portainer env vars, Host rule, first login. | | `AGENTS.md` | This file; for agents and developers. | | `.woodpecker/ci.yaml` | CI: install deps, format check (Prettier). | | `.woodpecker/deploy.yaml` | Deploy: trigger Portainer webhook after CI (no image build in this repo). | ## Where to change things - **Traefik hostname**: In `docker-compose.yml`, label `traefik.http.routers.umami.rule=Host(\`...\`)`. Default is **analytics.mifi.holdings**. - **Secrets**: Only in Portainer stack env or a local `.env`; never commit real values. - **DB volume name**: Compose uses `umami-db-data`; if you change it, update the `volumes` section and document the new name (e.g. in SETUP.md). ## Deployment context - **Repo**: `git.mifi.dev/mifi-holdings/umami.git` - **CI**: Woodpecker; pipelines under `.woodpecker/` (ci, deploy). Deploy depends on **ci** (not build); this repo has no Docker image build (stack-from-repo only). - **Prerequisites**: Existing Docker network **marina-net** and Traefik so the Umami service can be reached via the configured host. - **First login**: No default credentials; the admin account is created in the Umami UI on first visit.