docs: handleiding + functionele + technische specificatie
Drie nieuwe markdown-bestanden onder /docs: - handleiding.md — voor de dagelijkse gebruiker: eerste login, modules, veelvoorkomende taken (Caddy editen, sprint mergen via flow), wat expliciet niet vanuit de UI kan, log-locaties bij incidenten, veiligheidsadvies. - specs/functional.md — wat de app doet: scope per module met acceptatiecriteria, flow state-machine (pending/running/success/ failed/cancelled/timeout), hard limits (1 actieve flow, 64KB log knippen, 24u session), expliciete buiten-scope-lijst. - specs/technical.md — hoe het werkt: 3-process architectuur (dashboard container + agent op host + Postgres), stack-tabel met versies en redenen, data-model (User/Session/FlowRun/FlowStep), auth-flow met CSRF, agent-protocol over SSE, security-eigenschappen per laag. Lengtes pragmatisch gekozen — geen completeness-fetisj, wel genoeg om iemand die nieuw is in de codebase binnen 30 min te oriënteren. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
44e9280de1
commit
fda7be3214
3 changed files with 545 additions and 0 deletions
128
docs/handleiding.md
Normal file
128
docs/handleiding.md
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
# Handleiding — Ops Dashboard
|
||||
|
||||
Voor de dagelijkse beheerder van een single-host server-stack (Docker, systemd, Git, Caddy, Postgres). Deze handleiding beschrijft *hoe* je de app gebruikt, niet *hoe* hij werkt — voor dat laatste zie [`specs/technical.md`](./specs/technical.md).
|
||||
|
||||
## Eerste inlog
|
||||
|
||||
1. Open `https://<jouw-host>/` (bv. `https://ops.jp-visser.nl`).
|
||||
2. Je wordt doorgestuurd naar `/login`. Vul de admin-credentials in die je tijdens deploy in `SEED_USER_EMAIL` / `SEED_USER_PASSWORD` hebt gezet.
|
||||
3. Na succesvolle login zit je 24 uur ingelogd via een HttpOnly-cookie. Daarna opnieuw inloggen.
|
||||
|
||||
Wachtwoord vergeten? Geen reset-flow in de app — los op met een SQL-update:
|
||||
|
||||
```bash
|
||||
# Genereer een nieuwe bcrypt-hash voor je nieuwe wachtwoord
|
||||
docker run --rm -e PW='<nieuw-wachtwoord>' node:22-alpine sh -c '
|
||||
cd /tmp && npm init -y >/dev/null 2>&1 && npm install --silent bcryptjs >/dev/null 2>&1
|
||||
node -e "console.log(require(\"bcryptjs\").hashSync(process.env.PW, 12))"
|
||||
'
|
||||
# Plak in psql:
|
||||
docker exec -it scrum4me-postgres psql -U scrum4me -d ops_dashboard \
|
||||
-c "UPDATE \"User\" SET pwd_hash = '<hash>' WHERE email = '<jouw-email>';"
|
||||
```
|
||||
|
||||
## Dashboard (home)
|
||||
|
||||
Vijf live status-widgets, auto-refresh ~5 sec:
|
||||
|
||||
| Widget | Toont |
|
||||
|---|---|
|
||||
| **Docker** | Aantal draaiende containers + lijst |
|
||||
| **Git** | Branch en uncommitted-status per geconfigureerd repo-pad |
|
||||
| **systemd** | Service-status (active/inactive/failed) per geconfigureerde unit |
|
||||
| **Caddy** | TLS-certs met dichtstbijzijnde expiratiedatum (geel = <30 dagen) |
|
||||
| **Audit** | Laatste flow-run met timestamp en exit-status |
|
||||
|
||||
Klik een widget aan om naar de detail-pagina te gaan.
|
||||
|
||||
## Modules
|
||||
|
||||
### `/docker` — Containers
|
||||
|
||||
Tabel van `docker ps` met auto-refresh. Klik op een container-naam voor detail (logs, image, ports, status).
|
||||
|
||||
Read-only — geen start/stop/restart vanuit de UI. Voor wijzigingen: een **Flow** (zie hieronder).
|
||||
|
||||
### `/git` — Repositories
|
||||
|
||||
Per geconfigureerd pad in `REPO_PATHS` (env var): branch, uncommitted-files (M/A/D/??), laatste 3 commits. Klik door voor diff-viewer.
|
||||
|
||||
Read-only — pulls/commits gaan via een Flow.
|
||||
|
||||
### `/systemd` — Services
|
||||
|
||||
Lijst van services uit `SYSTEMD_UNITS` (env var). Toont status, laatste log-regels. Klik door voor full journal-tail van die unit.
|
||||
|
||||
Restart-knop: alleen voor units die in `commands.yml` zijn whitelisted én in `sudoers.d/ops-agent` met `NOPASSWD` staan.
|
||||
|
||||
### `/caddy` — Reverse-proxy & TLS
|
||||
|
||||
Toont de actieve Caddyfile (syntax-highlighted) plus alle TLS-certs (subject + expiry). "Edit"-knop opent een editor — opslaan **valideert** de Caddyfile via `caddy validate` voordat het wordt geschreven.
|
||||
|
||||
### `/flows` — Multi-step deployments
|
||||
|
||||
Twee voor-gedefinieerde flows:
|
||||
|
||||
- **Update Scrum4Me website** — pull main, build container, restart, smoke-test
|
||||
- **Update Caddy config** — schrijf nieuwe Caddyfile, valideer, restart Caddy, verifieer dat alle hostnames nog reageren
|
||||
|
||||
Een flow draait stap-voor-stap met **dry-run** als standaard. Na dry-run zie je per stap wat het gaat doen. Klik "Run" om echt uit te voeren. Tijdens executie zie je live stdout/stderr per stap.
|
||||
|
||||
### `/audit` — Flow-runs
|
||||
|
||||
Chronologische lijst van alle gestarte flows: starttijd, duur, exit-status, wie 'm startte. Klik door voor de volledige output (stdout/stderr per stap).
|
||||
|
||||
### `/settings/backups` — Backups
|
||||
|
||||
Postgres backup-management:
|
||||
|
||||
- Lijst van bestaande dump-bestanden in `/srv/scrum4me/backups`
|
||||
- "Backup now"-knop maakt een dump met timestamp-naam
|
||||
- Restore-runbook (handmatige stappen — geen automatische restore vanuit UI om de blast-radius klein te houden)
|
||||
|
||||
## Veelvoorkomende taken
|
||||
|
||||
### Container hangt — wat nu?
|
||||
|
||||
1. `/docker` → klik container-naam → bekijk logs
|
||||
2. Diagnose? Open een SSH-sessie en gebruik `docker logs`, `docker exec` etc. (Niet vanuit de UI — dat is buiten scope.)
|
||||
3. Restart nodig? Voeg de container toe aan `commands.yml` whitelist (op de host) + run via `/flows`
|
||||
|
||||
### Caddy-config wijzigen
|
||||
|
||||
1. `/caddy` → "Edit"
|
||||
2. Pas Caddyfile aan in de editor
|
||||
3. Save → app draait `caddy validate` → bij succes wordt het geschreven en Caddy herstart
|
||||
4. Verifieer in `/caddy` dat het cert-overzicht klopt
|
||||
|
||||
> Voor breaking changes (verkeerde syntax of niet-bestaande site): de validate-stap blokkeert. Bij twijfel: maak eerst een backup van `/srv/scrum4me/caddy/Caddyfile`.
|
||||
|
||||
### Sprint mergen via flow
|
||||
|
||||
`/flows/update-scrum4me-web` — kies branch (default `main`), klik dry-run, lees wat het doet, klik "Run". Stap-output stream live. Na success: smoke-test verifieert dat de homepage 200 geeft.
|
||||
|
||||
## Wat kan **niet** vanuit de UI
|
||||
|
||||
- SSH-toegang of arbitrary shell-commando's (alleen whitelisted commands.yml-keys)
|
||||
- User-management (één admin via seed; multi-user is buiten scope)
|
||||
- Container starten met andere image of args (alleen restart van bestaande)
|
||||
- Wachtwoord reset (SQL-update vereist)
|
||||
- Cert handmatig forceren (Caddy doet auto-ACME)
|
||||
|
||||
## Logs voor incident-response
|
||||
|
||||
| Component | Log-locatie |
|
||||
|---|---|
|
||||
| Dashboard app | `docker logs scrum4me-ops-dashboard` |
|
||||
| ops-agent | `journalctl -u ops-agent -f` |
|
||||
| Caddy | `docker logs scrum4me-caddy` |
|
||||
| Postgres | `docker logs scrum4me-postgres` |
|
||||
|
||||
Audit-trail van wat-doet-wie-wanneer: tabel `FlowRun` + `FlowStep` in de `ops_dashboard` database, of via `/audit` in de UI.
|
||||
|
||||
## Veiligheidsadvies
|
||||
|
||||
- Houd port 3099 (ops-agent) **niet** open naar de buitenwereld. UFW-regel scoped op `172.18.0.0/16`. Zie [`runbooks/post-install.md`](./runbooks/post-install.md).
|
||||
- Roteer `OPS_AGENT_SECRET` jaarlijks: nieuw secret in `.env` én `/etc/ops-agent/secret`, dan beide herstarten.
|
||||
- Voeg geen wildcards toe in `sudoers.d/ops-agent` — elke `systemctl`-actie moet een expliciete service-naam zijn.
|
||||
- `commands.yml` is single source of truth voor wat de agent mag — alles wat niet in de whitelist staat, kan een aanvaller niet uitvoeren ook al heeft hij het secret.
|
||||
Loading…
Add table
Add a link
Reference in a new issue