Two-layer structure: Sources (raw notes) + Wiki (compile output) Four domains: Dev (40), Venture (3), Homelab (23), Reference (0) Includes CLAUDE.md spec, index pages at all levels, compile log Co-Authored-By: Lovebug <lovebug@herbylab.dev>
3.8 KiB
3.8 KiB
| created | path | project | status | tags | type | updated | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2026-04-07 | Sources/Dev | wordpress-log-monitor | active |
|
Tech/Projects | 2026-04-07 |
WordPress Log Monitor
Goal
Build a security monitoring pipeline that parses WordPress Docker logs, stores metrics in MySQL, and visualizes trends in Streamlit. Replaces manual log grepping with an automated dashboard and Google Chat alerts.
Problem Being Solved
- 11,000+ brute force hits on wp-login.php went undetected for days
- No visibility into what traffic actually reaches the server vs what Cloudflare blocks
- Memory crashes caused by Apache worker exhaustion were mysterious without log data
- Manual grepping is not sustainable as site grows
Architecture
Docker WordPress Logs → Python Parser → MySQL → n8n Orchestration → Streamlit Dashboard ↓ Google Chat Alerts
Data To Capture
wp-login.php metrics
- Timestamp, IP address, HTTP method (GET vs POST), response code
- User agent string
- Hourly/daily hit counts
- POST attempts (actual login attempts) vs GET (page loads)
General security metrics
- 404 hit counts by IP (bot scanning indicator)
- Response code distribution
- Top IPs by request volume
- Slowest requests (response time > 5 seconds)
Apache health metrics
- Active worker count over time (correlate with memory spikes)
- Request rate per minute
- Memory usage correlation
Implementation Plan
Phase 1: Python Log Parser
- Use UV + venv, managed in PyCharm
- Parse WordPress Docker logs via docker logs command or log file mount
- Extract: timestamp, ip, method, uri, status, response_size, response_time, user_agent
- Store raw events in MySQL pbs_security_events table
- Run on schedule via n8n (every 5-15 minutes)
Phase 2: MySQL Schema
- pbs_security_events: raw parsed log entries
- pbs_security_summary: hourly aggregates for dashboard performance
- pbs_blocked_ips: known bad actors for reference
Phase 3: n8n Orchestration
- Schedule Python collector every 15 minutes
- Alert workflow: if wp-login.php hits > threshold in last hour → Google Chat alert
- Daily summary workflow → Google Chat digest with key metrics
Phase 4: Streamlit Dashboard
- wp-login.php hits over time (line chart)
- Top attacking IPs (table)
- Response code distribution (bar chart)
- Apache worker count vs memory usage (correlation chart)
- Cloudflare vs server hit comparison (manual input or CF API)
MySQL Schema (Draft)
CREATE TABLE pbs_security_events ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, logged_at DATETIME NOT NULL, ip_address VARCHAR(45) NOT NULL, method VARCHAR(10), uri TEXT, status_code SMALLINT, response_size INT, response_time_ms INT, user_agent TEXT, event_type VARCHAR(50), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_logged_at (logged_at), INDEX idx_ip (ip_address), INDEX idx_uri (uri(100)) );
Alert Thresholds (Starting Points)
- wp-login.php hits > 20 in any hour → Google Chat alert
- Any single IP > 50 requests in 10 minutes → Google Chat alert
- WordPress response time > 10 seconds → Google Chat alert
- Memory usage > 1.5GiB sustained 10 minutes → Google Chat alert
Future Expansion
- Pull Cloudflare Security Events via API for comparison
- Correlate Apache worker count with memory stats
- Auto-block IPs in Wordfence via API when threshold exceeded
- Feed data into broader PBS Content Intelligence Platform
Notes
- Use docker logs --since flag to avoid reprocessing old entries
- Store last processed timestamp in MySQL to handle restarts cleanly
- Keep collector lightweight — this runs every 15 minutes
- PyCharm Professional for development, UV for package management