Add fail2ban DB index management and socket-based path resolution

- New get_fail2ban_db_path() in setup_service resolves DB path from configured socket path
- New ensure_fail2ban_indexes() creates missing performance indexes on bans table
- Call ensure_fail2ban_indexes on every startup before first ban query
- Remove completed tasks from Docs/Tasks.md
- Update Docs/PERFORMANCE.md with index findings
This commit is contained in:
Copilot
2026-05-03 12:17:31 +02:00
committed by Lukas
parent 0133489920
commit 22db607875
6 changed files with 189 additions and 50 deletions

View File

@@ -95,4 +95,52 @@ Use `EXPLAIN QUERY PLAN` to verify index usage:
EXPLAIN QUERY PLAN SELECT ip, COUNT(*) FROM history_archive WHERE timeofban >= ? GROUP BY ip;
```
Expected: `USING INDEX idx_history_archive_timeofban` in the output.
Expected: `USING INDEX idx_history_archive_timeofban` in the output.
---
## Fail2ban Database Indexes
BanGUI reads from fail2ban's SQLite database (`/var/run/fail2ban/fail2ban.db`). Query performance degrades without appropriate indexes.
### Current fail2ban bans Indexes
Fail2ban creates these indexes on the `bans` table:
- `bans_jail_timeofban_ip` — composite (jail, timeofban, ip)
- `bans_jail_ip` — composite (jail, ip)
- `bans_ip` — single (ip)
**Missing**: standalone index on `timeofban` alone.
### BanGUI Automatic Index Creation
On startup, BanGUI calls `ensure_fail2ban_indexes()` to add missing indexes idempotently:
```python
# From fail2ban_db_utils.py
CREATE INDEX IF NOT EXISTS idx_bans_timeofban_desc ON bans(timeofban DESC);
```
This improves queries like:
```sql
SELECT * FROM bans WHERE timeofban >= ? ORDER BY timeofban DESC;
```
### Verifying Index Usage
Check if a query uses the index:
```sql
EXPLAIN QUERY PLAN SELECT * FROM bans WHERE timeofban >= 1700000000 ORDER BY timeofban DESC;
-- With index: SEARCH USING INDEX idx_bans_timeofban_desc
-- Without: SCAN TABLE bans
```
### Adding Indexes to Migrations
For BanGUI's own `history_archive` table, indexes go in migrations via `_ Migration.add_table_indexes()`:
```python
def _add_history_archive_indexes(m: Migration) -> None:
m.add_index("history_archive", ["timeofban"], unique=False, if_not_exists=True)
m.add_index("history_archive", ["jail", "timeofban"], unique=False, if_not_exists=True)
```