diff --git a/phase2-tasks.md b/phase2-tasks.md new file mode 100644 index 0000000..a24d826 --- /dev/null +++ b/phase2-tasks.md @@ -0,0 +1,135 @@ +# Phase 2 Migration Task List +## Sibiu Independent — May 2026 + +Generated: 2026-05-29 +Scope: Web node (zamolxis) — Phase 2 + repo wrap-up + +--- + +## Tasks + +### TASK-001 +**Subject:** rsync WP files from dracula to zamolxis +**Active form:** Rsyncing WP files +**Description:** +rsync all WordPress files from root@100.99.157.56 port 79 (/www/wwwroot/sibiuindependent.ro/) to zamolxis (/var/www/sibiuindependent.ro/), excluding cache and w3tc-config. Fix ownership to www:www. + +**Command reference:** +```sh +rsync -avz --progress \ + -e "ssh -i /root/.ssh/id_ed25519 -p 79" \ + --exclude="wp-content/cache/" \ + --exclude="wp-content/w3tc-config/" \ + root@100.99.157.56:/www/wwwroot/sibiuindependent.ro/ \ + /var/www/sibiuindependent.ro/ + +chown -R www:www /var/www/sibiuindependent.ro +``` + +**Status:** [ ] Pending + +--- + +### TASK-002 +**Subject:** Update wp-config.php on zamolxis +**Active form:** Updating wp-config.php +**Description:** +Update DB_HOST to 100.67.166.29, DB credentials to sql_sibiuindepen user, add WP_REDIS_PATH and WP_REDIS_SCHEME constants for unix socket Redis. + +**Changes required in /var/www/sibiuindependent.ro/wp-config.php:** +```php +define( 'DB_HOST', '100.67.166.29' ); + +// Add before "That's all, stop editing": +define( 'WP_REDIS_PATH', '/var/run/redis/redis.sock' ); +define( 'WP_REDIS_SCHEME', 'unix' ); +``` + +**Status:** [ ] Pending + +--- + +### TASK-003 +**Subject:** Remove W3TC and install Redis Object Cache +**Active form:** Replacing W3TC with Redis Object Cache +**Description:** +Remove W3TC plugin dir and its drop-ins (advanced-cache.php, object-cache.php). Install Redis Object Cache plugin (Till Kruss) if not already present. + +**Command reference:** +```sh +rm -rf /var/www/sibiuindependent.ro/wp-content/plugins/w3-total-cache +rm -f /var/www/sibiuindependent.ro/wp-content/advanced-cache.php +rm -f /var/www/sibiuindependent.ro/wp-content/object-cache.php + +# Check if Redis Object Cache already exists from dracula sync: +ls /var/www/sibiuindependent.ro/wp-content/plugins/redis-cache/ + +# If not present, install via WP-CLI: +wp --path=/var/www/sibiuindependent.ro --allow-root \ + plugin install redis-cache --activate +``` + +**Status:** [ ] Pending + +--- + +### TASK-004 +**Subject:** Run pre-cutover checklist on zamolxis +**Active form:** Running pre-cutover checklist +**Description:** +Verify: site responds on port 80, DB connection works from zamolxis to decebal, Redis connected, PHP extensions present (imagick, redis, pdo_mysql, opcache, intl, soap, sodium), nginx fastcgi_cache working (MISS then HIT on second request). + +**Command reference:** +```sh +# 1. Site responds +curl -sk -o /dev/null -w "%{http_code}" \ + http://100.115.128.41/ \ + -H "Host: sibiuindependent.ro" +# Expected: 200 + +# 2. DB connection +mysql -h 100.67.166.29 \ + -u sql_sibiuindepen -p \ + --get-server-public-key \ + -e "SELECT COUNT(*) FROM wp_posts WHERE post_status='publish';" + +# 3. Redis object cache status +wp --path=/var/www/sibiuindependent.ro --allow-root redis-cache status + +# 4. PHP extensions +php85 -m | grep -E "imagick|redis|pdo_mysql|opcache|intl|soap|sodium" + +# 5. nginx fastcgi_cache — first: MISS, second: HIT +curl -sI http://100.115.128.41/ -H "Host: sibiuindependent.ro" | grep X-Cache-Status +curl -sI http://100.115.128.41/ -H "Host: sibiuindependent.ro" | grep X-Cache-Status +``` + +**Status:** [ ] Pending + +--- + +### TASK-005 +**Subject:** Push final README update to repo +**Active form:** Updating repo +**Description:** +Update README with Phase 2/3 completion status and push to Gitea. + +**Steps:** +1. Update Open Items checklist in README.md — mark Phase 2 tasks complete +2. Update Deployment Status table if applicable +3. `git add README.md && git commit -m "docs: mark Phase 2 complete"` +4. `git push` + +**Status:** [ ] Pending + +--- + +## Execution Order + +| # | Task ID | Subject | Blocker | +|---|---|---|---| +| 1 | TASK-001 | rsync WP files | None — run first | +| 2 | TASK-002 | Update wp-config.php | TASK-001 (files must be present) | +| 3 | TASK-003 | Remove W3TC / install Redis Object Cache | TASK-001 (files must be present) | +| 4 | TASK-004 | Pre-cutover checklist | TASK-002, TASK-003 | +| 5 | TASK-005 | Push README update | TASK-004 (checklist must pass) | diff --git a/sibiuindependent.ro.MD b/sibiuindependent.ro.MD index f7fd490..e692405 100644 --- a/sibiuindependent.ro.MD +++ b/sibiuindependent.ro.MD @@ -39,7 +39,8 @@ Both VMs are on separate bare-metal Proxmox hosts. All inter-service traffic run | Media | wp-content/uploads local (6.5GB), S3 offload via WPS3Media to `s3.palmasolutions.net/sibiuindependent` (101,145 files in `ddf44d_as3cf_items`) | | Login URL | `/intrarepresa` (Perfmatters custom login — `/wp-login.php` and `/wp-admin` return 403) | | WP prefix | `ddf44d_` | -| Firewall | pf — HTTP only from NPM (100.89.238.4), SSH only from mgmt + Tailscale | +| Firewall | pf — HTTP open to all (WAF on NPM), SSH only from mgmt + Tailscale | +| Real IP | nginx `real_ip_header X-Real-IP` from NPM — access log and plugins see true client IPs | **Active PHP extensions:** bcmath, curl, exif, fileinfo, gd, imagick, intl, mbstring, mysqli, opcache, pcntl, pdo_mysql, pecl-redis, posix, simplexml, soap, sockets, sodium, xml, xmlreader, xmlwriter, xsl, zip @@ -662,6 +663,24 @@ The static file location regex did not include `webp`. WPS3Media serves WebP var Fix: added `webp|mp4|webm|ogv` to the static location regex. +### 9. Login blocked for all users — ASE Limit Login Attempts locked NPM's IP + +All traffic passes through NPM (Tailscale 100.89.238.4). nginx passed `REMOTE_ADDR = 100.89.238.4` to PHP. The Admin Site Enhancements plugin's Limit Login Attempts feature tracked all failed logins against this single IP. After multiple users tried and failed, the 24h lockout triggered — blocking everyone from `/intrarepresa`. + +Fix (immediate): ASE deactivated. + +Fix (permanent): nginx `real_ip_header X-Real-IP` + `set_real_ip_from 100.89.238.4` configured. `$remote_addr` now reflects true client IP from NPM's `X-Real-IP` header. Access log and all PHP plugins see real per-user IPs. If ASE is re-enabled, Limit Login Attempts will work correctly per-user. + +### 10. pf HTTP restriction opened — WAF on NPM handles filtering + +HTTP was restricted to NPM's Tailscale IP only. Opened to all: `pass in proto tcp from any to any port 80 keep state`. WAF rules on NPM handle filtering upstream. + +### 11. Stale nginx cache on homepage for anonymous (mobile) users + +No cache invalidation on post publish. Anonymous users (typically mobile) got the nginx-cached homepage for up to 24h after new posts were published. Logged-in users (desktop) bypassed cache via `wordpress_logged_in` cookie. + +Fix: `si_purge_nginx_homepage_cache()` hook added to `sibiu-independent-tweaks/sb.php`. On `transition_post_status` (publish/unpublish), it calculates the homepage cache file path (MD5 of `httpGETsibiuindependent.ro/`, nginx `levels=1:2`) and deletes it. Next organic request regenerates the cache. PHP `www` user has write access to nginx cache files (same owner). + --- ## Current Performance (2026-05-31)