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>
128 lines
3.8 KiB
Markdown
128 lines
3.8 KiB
Markdown
---
|
|
created: 2026-04-07
|
|
path: Sources/Dev
|
|
project: wordpress-log-monitor
|
|
status: active
|
|
tags:
|
|
- security
|
|
- docker
|
|
- python
|
|
- mysql
|
|
- streamlit
|
|
- n8n
|
|
- monitoring
|
|
type: Tech/Projects
|
|
updated: 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 |