# OperareOperarea daemonului în producție: rotație de log, syslog, lifecycle de daemon și imagini de eroare cunoscute.

## Rotația logului

Daemonul gestionează ambele pattern-uri uzuale de rotație:

- **Rotate-and-rename** (access logul este redenumit, un fișier nou îi ia locul). Detectat prin schimbarea inode/device pe calea monitorizată.
- **Copytruncate** (conținutul fișierului este copiat în altă parte, apoi originalul este truncat la zero). Detectat prin `tell() > stat()`.

În ambele cazuri, daemonul redeschide fișierul de la început și scrie `info reopen after rotate dev=… ino=…` (rotate-and-rename) sau `info truncate file shrank` (copytruncate) pe stderr.

Dacă lipsesc intrări în jurul rotației, verifică configurația uneltei de rotație:

- Pe OpenBSD, `newsyslog` are rotație standard rotate-and-rename — fără configurare specială necesară.
- Pe Linux, `logrotate` ia mai bine default-ul (rotație + SIGHUP către serverul web) decât modul `copytruncate`. Ambele funcționează, dar rotate-and-rename este mai ieftin și nu pierde linii.

## Scriptul `rc.d` (OpenBSD)

Variantă minimă `/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
```

Apoi:

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

Pe Linux cu systemd, vezi documentația distribuției; o unitate simplă `Type=simple` care arată către `/usr/local/sbin/abusive_http_watch` cu aceleași argumente este suficientă.

## Evenimente syslog

Daemonul emite o clasă de evenimente — `added` — când un IP nou depășește pragul de hit-uri. Format:

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

Exemplu:

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

Prin `syslog.conf`, rutează către un fișier propriu pentru review:

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

Împreună cu `ABUSIVE_SYSLOG_FACILITY=local0`, rezultă un audit log curat al fiecărui IP blocat.

## Semnale de monitoring

Pentru monitoring automat, doi indicatori sunt utili:

- **Rata de creștere a blocklistei** — `wc -l /var/www/run/abusive_http_hosts` în timp. Pe un server web public, ar trebui să crească constant (de la câteva IP-uri pe zi la multe pe oră, în funcție de expunere). O linie plată de 24h pe un site public sugerează că daemonul nu rulează sau citește logul greșit.
- **Sănătatea procesului** — `pgrep -f abusive_http_watch` ar trebui să returneze mereu exact un PID. Alertă la zero.

Pentru setupuri Prometheus, un mic exporter care doar `wc -l`uiește fișierul de blocklistă și expune numărul ca gauge este suficient. Fără endpoint de metrici în daemonul însuși — by design, pentru a-l ține fără dependențe.

## Troubleshooting

### Fișierul de blocklistă rămâne gol

Cauze posibile, în ordinea probabilității:

1. **Daemonul citește fișierul greșit.** Pornește în foreground cu `ABUSIVE_DEBUG=1`. Verifică să logheze `start following dev=… ino=…` pentru calea așteptată. Dacă nu, corectează argumentul.
2. **Nu există trafic real de atac.** Improbabil pe un server web public, dar posibil intern. Rulează cu `ABUSIVE_DEBUG=1` și caută linii `[dbg] ip=…` fără un `[dbg] token match` corespunzător.
3. **Whitelist-ul înghite totul.** Verifică `/etc/abusive_http_whitelist` — o intrare CIDR `/0` greșită pune tot internetul pe whitelist. Scoate și restartează.
4. **Pragul de hit-uri prea mare.** Coboară `ABUSIVE_MIN_HITS` de test la `1` și observă comportamentul.

### Blocklista crește, dar firewallul nu blochează

Daemonul scrie fișierul. Firewallul trebuie instruit să-l citească. Verifică:

- Cronul reîncarcă tabelul `pf` / setul `nftables` la fiecare câteva minute (daemonul nu cheamă `pfctl` el însuși).
- Regula de firewall care referă tabelul este în chain-ul potrivit și `quick` îndeajuns ca să prindă înainte de regulile `pass` ulterioare.

### Utilizatori legitimi sunt blocați

Adaugă IP-ul lor public sau range-ul CIDR la `/etc/abusive_http_whitelist`. Daemonul recitește whitelist-ul la fiecare linie — schimbările prind în câteva secunde.

Pentru a scoate un singur IP din blocklista existentă, editează direct fișierul și reîncarcă tabelul de firewall. Daemonul nu are nevoie de restart — va reintroduce IP-ul doar dacă utilizatorul lovește din nou tokenuri.

### Daemonul crash-uiește după rotația logului

Nu ar trebui să se întâmple cu gestionarea de rotație descrisă mai sus. Dacă totuși da, rulează în foreground cu `ABUSIVE_DEBUG=1`, declanșează o rotație și înregistrează stderr. Trimite logul înregistrat prin pagina de [Contact](/ro/contact/) — acesta este un bug real pe care vrem să-l reparăm.

## Shutdown curat

Daemonul prinde `SIGTERM` și se termină curat după iterația curentă:

```sh
doas rcctl stop abusive_http_watch
```

Loghează `[info] TERM received, exiting`, închide handle-ul fișierului de log, face flush la toate scrierile în așteptare și iese cu status 0. Fără corupere de stare, chiar și pe un log foarte folosit.
