Skip to content

[codex] Add remote WordPress COW mount experiment#9

Draft
adamziel wants to merge 39 commits into
trunkfrom
codex/remote-wp-cow-experiment
Draft

[codex] Add remote WordPress COW mount experiment#9
adamziel wants to merge 39 commits into
trunkfrom
codex/remote-wp-cow-experiment

Conversation

@adamziel
Copy link
Copy Markdown
Contributor

@adamziel adamziel commented May 1, 2026

What it does

Adds experiments/remote-wp-cow, a Linux-only lab for running a remote WordPress site locally without copying the whole site first.

wp-cow serve \
  --ssh user@example.com \
  --path /home/user/public_html \
  --remote-url https://example.com \
  --local-url http://localhost:9481

That command creates or reuses a clone descriptor, mounts a lazy FUSE filesystem, starts the local DB control/proxy layer, and launches PHP/FrankenPHP. Remote files are the lower layer, local edits live in upper/, cached reads live in file-cache/, and DB writes route to the local materialized layer instead of production.

Docker wrappers are included for macOS testing through docker compose exec wp-cow-lab bash.

cc @JanJakes

Rationale

A 500 GB WordPress site cannot be cloned by eagerly copying files or dumping every table. The useful shape is a local runtime where production is a lazy lower layer and only files, rows, and tables touched by local requests become materialized.

The branch explores the hard parts directly: avoiding browser hangs during cold start, refusing to treat the WordPress installer as success, keeping production DB writes impossible, preserving local-only edits, and avoiding arbitrary production plugin side effects.

Implementation

The experiment wires together:

  • FUSE lower/upper filesystem with whiteouts, copy-up-on-write, persistent file bytes, positive metadata, and negative metadata.
  • Bounded runtime code packing for executable WordPress files; wp-content/uploads and wp-config.php stay lazy.
  • Generated wp-config.php, wp-content/db.php, router, and safety mu-plugin that point URLs/DB locally and reject installer/runtime failure pages.
  • Local DB materialization for schema, options bootstrap reads, row-level WordPress COW cases, fallback table promotion, and local-only inserts/updates/deletes.
  • A local MySQL protocol proxy so plugins that connect through DB_HOST still hit the COW routing layer.
  • wp-cow sever, which writes run/offline.json, stops remote lower reads, can set a local-only admin password, and keeps already materialized local edits refreshable offline.
  • WPCOW_PLUGIN_MODE=auto, which starts with production plugins disabled, smoke-boots active plugin candidates one at a time, admits passing plugins, and quarantines failing plugins locally.
  • PHP side-effect guards for process spawning, mail(), raw sockets, cURL execution, URL includes, cron, WordPress HTTP API calls, and indexing headers by default.
  • SiteGround visual-runtime preservation: reuse the combined CSS, localize production upload URLs inside it, enqueue lazysizes.min.js, preserve SG lazyload image markup, localize menu/content URLs, and suppress WP emoji assets to match the optimized frontend.

This is still an experiment. The default path is designed to be safe and lazy, but WPCOW_PLUGIN_MODE=full is an escape hatch rather than a guarantee that every arbitrary production plugin is safe or fast.

Measured on the real SiteGround site:

Latest visual parity run:
  local URL: http://foo.ai-sandbox-49184.kostka.zielinscy.dev
  screenshot viewport: 1365x2200
  local-vs-remote pixel diff: 0.0353% of pixels > 12 channel delta
  diff bounding box: [733,1392,768,1427] (YouTube badge iframe nondeterminism)
  SG combined CSS localized: yes
  SG lazysizes runtime present: yes
  content image data-src rewritten to local clone: yes
  production-domain URLs in rendered content: 0
  warm rerenders after visual assets cached: 1.34s, 1.43s, 1.56s

Earlier real SiteGround run, WPCOW_PLUGIN_MODE=auto:
  first real WordPress render: passed a 60s acceptance budget
  second render: passed a 12s acceptance budget
  file cache: 1,866 files / 24,015,022 bytes (~22.9 MiB)
  uploads mirrored: no
  offline refresh after sever: passed
  local admin login after sever: passed
  local-only page remote mutation check: passed

Local harness at e681a3e:
  strict runtime/admin/offline harness: 5.36s
  strict production FUSE/control/offline harness: 7.02s

Testing instructions

Run the standard checks:

cd experiments/remote-wp-cow
cargo test --locked
scripts/strict-harness.sh

Run the Docker lab from macOS:

cd experiments/remote-wp-cow
WPCOW_HTTP_PORT=9481 docker compose up -d --build
docker compose exec wp-cow-lab bash
wp-cow-lab-serve

Real-site acceptance template:

WPCOW_PLUGIN_MODE=auto \
WPCOW_PLUGIN_ADMISSION=1 \
WPCOW_NAME='calm-cottage-auto-admission' \
WPCOW_SSH='wp-cow-real-calm-cottage' \
WPCOW_PATH='/home/u2199-yx4tznmyunag/www/calm-cottage-mindfulness.com/public_html' \
WPCOW_REMOTE_URL='https://calm-cottage-mindfulness.com' \
WPCOW_LOCAL_URL='http://127.0.0.1:9481' \
WPCOW_HTTP='127.0.0.1:9481' \
WPCOW_HTTP_PORT=9481 \
WPCOW_ACTUAL_TIMEOUT_SECS=180 \
WPCOW_SECOND_TIMEOUT_SECS=12 \
WPCOW_EXPECT_TEXT='My WordPress' \
scripts/live-site-acceptance.sh

@JanJakes
Copy link
Copy Markdown
Contributor

@adamziel Is this one outdated and superseded by #40?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants