fix(fail2ban): native backend does not depend on role order for auth.log; verify it runs #239

Merged
jfraeys merged 1 commit from jfraeys/fix/fail2ban-native-needs-authlog into main 2026-10-16 17:24:15 -04:00
Owner

Found on the OVH rehearsal web node: fail2ban.service failed (journal: 'Have not found any log file for sshd jail') although the play ended ok=110 failed=0.

Cause: playbooks/web.yml runs the fail2ban role (line ~180) before hardening (~194), and hardening installs rsyslog, which creates /var/log/auth.log (created 17:05:43; fail2ban started 17:03-17:04). Debian cloud images log to the journal only. Production web never showed this because the file already existed. The systemd 'started' state is reported even when the daemon exits right after, so the play passed.

Fix (native backend only): install and start rsyslog and create /var/log/auth.log (root:adm 0640, not overwritten) before starting fail2ban, then check 'systemctl is-active fail2ban' with retries so a dead daemon fails the play. ansible-lint passes on the role.

Not tested here: a real run on a fresh node. The staging web node may already have rsyslog from the prebaked image, so staging may not reproduce the original failure; the next fresh node (or re-running the fail2ban tag on ovh-web) is the real test.

roles/ is a staged path: staging, promotion; deploy with --tags fail2ban --limit web (production web is unaffected: rsyslog and auth.log exist).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ

Found on the OVH rehearsal web node: fail2ban.service failed (journal: 'Have not found any log file for sshd jail') although the play ended ok=110 failed=0. Cause: playbooks/web.yml runs the fail2ban role (line ~180) before hardening (~194), and hardening installs rsyslog, which creates /var/log/auth.log (created 17:05:43; fail2ban started 17:03-17:04). Debian cloud images log to the journal only. Production web never showed this because the file already existed. The systemd 'started' state is reported even when the daemon exits right after, so the play passed. Fix (native backend only): install and start rsyslog and create /var/log/auth.log (root:adm 0640, not overwritten) before starting fail2ban, then check 'systemctl is-active fail2ban' with retries so a dead daemon fails the play. ansible-lint passes on the role. Not tested here: a real run on a fresh node. The staging web node may already have rsyslog from the prebaked image, so staging may not reproduce the original failure; the next fresh node (or re-running the fail2ban tag on ovh-web) is the real test. roles/ is a staged path: staging, promotion; deploy with --tags fail2ban --limit web (production web is unaffected: rsyslog and auth.log exist). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
fix(fail2ban): native backend installs rsyslog and creates auth.log first, and fails the play if the daemon is not running
All checks were successful
Lint / lint (pull_request) Successful in 2m48s
Secret scan / scan (pull_request) Successful in 16s
0ec6510552
On the fresh OVH web node fail2ban started before hardening installed rsyslog, so /var/log/auth.log did not exist
('Have not found any log file for sshd jail'), exited, and the play still reported ok. Production web never showed it because the
file already existed. The role no longer depends on role order, and a dead daemon now fails the play.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ge5tovcwdEUBtPwUktsZZZ
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
jfraeys/infra!239
No description provided.