docs(runbook): post-install steps voor docker-bereikbaarheid agent

Documenteert de drie stappen die nodig zijn ná `setup.sh` om de
ops-agent bereikbaar te maken vanuit de dashboard-container:

1. systemd drop-in om OPS_AGENT_HOST op 0.0.0.0 te zetten
2. UFW allow-regel voor docker-subnet (172.18.0.0/16) naar :3099
3. Sync /etc/ops-agent/secret met OPS_AGENT_SECRET uit dashboard .env

Inclusief verificatie-commando's en een symptoom-tabel voor de drie
meest voorkomende failure-modes ('fetch failed', 'Unauthorized',
lege data). Komt voort uit de eerste live deploy op ops.jp-visser.nl
waar elke stap onafhankelijk faalde.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Janpeter Visser 2026-05-13 22:06:52 +02:00
parent 656aa27a7f
commit 12d305669b

View file

@ -0,0 +1,116 @@
# Post-install: ops-agent bereikbaar maken vanuit de dashboard-container
Na `sudo bash deploy/ops-agent/setup.sh` draait de agent met de defaults uit
`deploy/ops-agent/ops-agent.service`:
```
Environment=OPS_AGENT_HOST=127.0.0.1
```
Dat is veilig (alleen host-loopback) maar **niet bereikbaar vanuit de
ops-dashboard Docker-container**: 127.0.0.1 in de container = de container
zelf, niet de host. Containers op de compose-bridge zien de host alleen via de
bridge-gateway (`172.18.0.1`). De agent moet dáár ook op luisteren, en je
firewall moet de docker-subnet doorlaten naar poort 3099.
Drie stappen, allemaal as root.
## 1. Bind agent op alle interfaces
Drop-in:
```bash
sudo mkdir -p /etc/systemd/system/ops-agent.service.d
sudo tee /etc/systemd/system/ops-agent.service.d/override.conf >/dev/null <<'EOF'
[Service]
Environment=OPS_AGENT_HOST=0.0.0.0
EOF
sudo systemctl daemon-reload
sudo systemctl restart ops-agent
```
Verifieer: `ss -tnlp | grep 3099` moet `0.0.0.0:3099` tonen.
> Strakker alternatief: `OPS_AGENT_HOST=172.18.0.1` (alleen op bridge-IP). Werkt
> alleen als je UFW-rule óók die specifieke source toelaat en je de bridge-IP
> niet wijzigt bij compose-recreate.
## 2. Firewall doorlaten
Default UFW-policy is `deny incoming`. Voeg een regel toe voor het docker-subnet:
```bash
sudo ufw allow from 172.18.0.0/16 to any port 3099 proto tcp comment 'ops-agent'
```
Zonder deze regel droppen kernel-iptables packets vanaf de container, **ook al
luistert de agent op 0.0.0.0**. Symptoom: vanuit de container TCP-timeout naar
`172.18.0.1:3099` terwijl L3 ping wel werkt.
> Zorg dat poort 3099 níét in je perimeter-firewall (cloud-firewall, externe
> router) open staat — de UFW-rule scoped al op het docker-subnet, maar als de
> agent op `0.0.0.0` bindt en je perimeter het toestaat, is hij vanaf het hele
> internet bereikbaar (al beschermd door HMAC-secret).
## 3. Sync shared secret met dashboard
`setup.sh` genereert `/etc/ops-agent/secret` met een random waarde. De
ops-dashboard heeft die waarde nodig in `.env` als `OPS_AGENT_SECRET`. Twee
paden:
**A. Overneem wat setup.sh genereerde** (eenvoudig, sterk):
```bash
sudo cat /etc/ops-agent/secret # noteer
# vul in: OPS_AGENT_SECRET=<die waarde> in /srv/.../ops-dashboard/.env
```
**B. Forceer een eigen waarde** (handig als je hem al in `.env` had staan):
```bash
SECRET=$(grep '^OPS_AGENT_SECRET=' /srv/scrum4me/ops-dashboard/.env | cut -d= -f2- | tr -d '"')
printf '%s' "$SECRET" | sudo tee /etc/ops-agent/secret >/dev/null
sudo chown root:ops-agent /etc/ops-agent/secret
sudo chmod 0640 /etc/ops-agent/secret
sudo systemctl restart ops-agent
```
## 4. Update dashboard .env + restart
```bash
# in /srv/.../ops-dashboard/.env
OPS_AGENT_URL=http://172.18.0.1:3099
```
En herstart de container:
```bash
cd /srv/scrum4me/compose
docker compose up -d --force-recreate ops-dashboard
```
## Verificatie
```bash
# Vanaf host (HMAC ontbreekt, dus 401 = OK)
curl -sI http://172.18.0.1:3099/ | head -2
# HTTP/1.1 401 Unauthorized
# Vanaf container (zelfde verwachting)
docker exec scrum4me-ops-dashboard sh -c 'wget -qO- --timeout=3 -S http://172.18.0.1:3099/ 2>&1 | head -2'
# UI smoke-test — open https://<dashboard-host>/docker
# zou container-tabel renderen zonder "agent 502: fetch failed"
```
## Symptomen-tabel
| Symptoom in dashboard | Oorzaak | Stap |
|---|---|---|
| `fetch failed` op elke module-page | Container kan agent niet bereiken | 1 of 2 |
| `agent 502 Unauthorized` met HMAC-error in agent-logs | Secret-mismatch | 3 |
| Module-pagina rendert maar lege/oude data | OPS_AGENT_URL onbereikbaar of cache | 4 |
Logs:
- agent: `journalctl -u ops-agent -f`
- dashboard: `docker logs -f scrum4me-ops-dashboard`