# BetriebDen Daemon in Produktion betreiben: Log-Rotation, Syslog, Daemon-Lifecycle und bekannte Fehlerbilder.

## Log-Rotation

Der Daemon handhabt beide gängigen Rotation-Muster:

- **Rotate-and-Rename** (Access-Log wird umbenannt, eine neue
  Datei nimmt seinen Platz). Erkannt über
  Inode-/Device-Wechsel auf dem überwachten Pfad.
- **Copytruncate** (Datei-Inhalt wird woandershin kopiert, dann das
  Original auf Größe Null gestutzt). Erkannt über
  `tell() > stat()`.

In beiden Fällen öffnet der Daemon die Datei vom Anfang neu und
schreibt `info reopen after rotate dev=… ino=…` (Rotate-and-Rename)
oder `info truncate file shrank` (Copytruncate) auf stderr.

Wenn rund um die Rotation Einträge fehlen, prüfe die
Rotation-Tool-Konfiguration:

- Auf OpenBSD `newsyslog` ist die Standard-Rotation
  Rotate-and-Rename — keine spezielle Konfiguration nötig.
- Auf Linux `logrotate` lieber den Default (rotieren + SIGHUP an
  den Webserver) statt `copytruncate`-Modus nehmen. Beides
  funktioniert, aber Rotate-and-Rename ist günstiger und verliert
  keine Zeilen.

## `rc.d`-Skript (OpenBSD)

Minimal-Variante `/etc/rc.d/abusive_http_watch`:

```sh
#!/bin/ksh
daemon="/usr/local/sbin/abusive_http_watch"
daemon_flags="/var/www/logs/access.log"
daemon_user="_www"
. /etc/rc.d/rc.subr
rc_bg=YES
rc_reload=NO
rc_cmd $1
```

Dann:

```sh
doas rcctl enable abusive_http_watch
doas rcctl start abusive_http_watch
doas rcctl check abusive_http_watch
```

Auf Linux mit systemd siehe die Distributions-Doku; eine einfache
`Type=simple`-Unit, die auf `/usr/local/sbin/abusive_http_watch`
mit denselben Argumenten zeigt, reicht.

## Syslog-Events

Der Daemon emittiert eine Event-Klasse — `added` — wenn eine neue
IP die Hit-Schwelle überschreitet. Format:

```
<syslog-tag>[<pid>]: added ip=<ip> path=<blocklist-pfad>
```

Beispiel:

```
abusive_http_watch[12345]: added ip=198.51.100.42 path=/var/www/run/abusive_http_hosts
```

Per `syslog.conf` in eine eigene Datei für Review routen:

```
local0.notice                                          /var/log/abusive_http.log
```

Zusammen mit `ABUSIVE_SYSLOG_FACILITY=local0` ergibt das ein
sauberes Audit-Log jeder geblockten IP.

## Monitoring-Signale

Für automatisiertes Monitoring sind zwei Indikatoren nützlich:

- **Blocklist-Wachstumsrate** — `wc -l /var/www/run/abusive_http_hosts`
  über die Zeit. Auf einem öffentlichen Webserver sollte das
  stetig wachsen (mehrere IPs pro Tag bis viele pro Stunde, je
  nach Exposure). Eine 24h-Flatline auf einer Public-Site deutet
  darauf hin, dass der Daemon nicht läuft oder das falsche Log liest.
- **Prozess-Health** — `pgrep -f abusive_http_watch` sollte immer
  genau eine PID liefern. Alert auf null.

Für Prometheus-Setups reicht ein winziger Exporter, der einfach
die Blocklist-Datei `wc -l`t und die Zahl als Gauge exponiert.
Kein Metrics-Endpunkt im Daemon selbst — by design, um ihn
dependency-frei zu halten.

## Troubleshooting

### Die Blocklist-Datei bleibt leer

Mögliche Ursachen, nach Wahrscheinlichkeit:

1. **Daemon liest die falsche Datei.** Im Vordergrund mit
   `ABUSIVE_DEBUG=1` starten. Prüfen, dass er
   `start following dev=… ino=…` für den erwarteten Pfad loggt.
   Falls nicht, das Argument korrigieren.
2. **Kein echter Angriffstraffic.** Unwahrscheinlich auf einem
   öffentlichen Webserver, aber bei internem möglich. Mit
   `ABUSIVE_DEBUG=1` laufen lassen und nach `[dbg] ip=…`-Zeilen
   ohne entsprechendes `[dbg] token match` suchen.
3. **Whitelist verschluckt alles.** `/etc/abusive_http_whitelist`
   prüfen — ein irrtümlicher `/0`-CIDR-Eintrag whitelisted das
   ganze Internet. Entfernen und neu starten.
4. **Hit-Schwelle zu hoch.** `ABUSIVE_MIN_HITS` testweise auf `1`
   senken und Verhalten beobachten.

### Die Blocklist wächst, aber die Firewall blockt nicht

Der Daemon schreibt die Datei. Die Firewall muss angewiesen
werden, sie zu lesen. Prüfen:

- Cron lädt die `pf`-Tabelle / das `nftables`-Set alle paar
  Minuten neu (der Daemon ruft `pfctl` nicht selbst auf).
- Die Firewall-Regel, die auf die Tabelle verweist, ist in der
  richtigen Chain und `quick` genug, um vor späteren
  `pass`-Regeln zu greifen.

### Legitime Nutzer werden geblockt

Ihre öffentliche IP oder CIDR-Range zu
`/etc/abusive_http_whitelist` hinzufügen. Der Daemon liest die
Whitelist bei jeder Zeile neu — Änderungen greifen binnen
Sekunden.

Um eine einzelne IP aus der bestehenden Blocklist zu entfernen,
die Datei direkt editieren und die Firewall-Tabelle neu laden. Der
Daemon braucht keinen Neustart — er trägt die IP nur dann wieder
ein, wenn der Nutzer erneut Token trifft.

### Daemon crasht nach Log-Rotation

Sollte mit der oben beschriebenen Rotation-Handhabung nicht
passieren. Wenn doch, im Vordergrund mit `ABUSIVE_DEBUG=1` laufen
lassen, eine Rotation auslösen und stderr mitschreiben. Das
mitgeschriebene Log per [Kontakt](/de/contact/)-Seite schicken —
das ist ein echter Bug, den wir fixen wollen.

## Sauberer Shutdown

Der Daemon fängt `SIGTERM` ab und beendet sich sauber nach der
aktuellen Iteration:

```sh
doas rcctl stop abusive_http_watch
```

Loggt `[info] TERM received, exiting`, schließt das
Logfile-Handle, flusht alle ausstehenden Writes und beendet sich
mit Status 0. Keine State-Korruption, auch bei einem stark
genutzten Log.
