Skip to content

[codex] Add Windows ReFS COW storage support#35

Draft
adamziel wants to merge 2 commits into
trunkfrom
codex/windows-cow-support
Draft

[codex] Add Windows ReFS COW storage support#35
adamziel wants to merge 2 commits into
trunkfrom
codex/windows-cow-support

Conversation

@adamziel
Copy link
Copy Markdown
Contributor

@adamziel adamziel commented May 11, 2026

What it does

Adds the Windows-native COW path and turns it into a click-through setup flow.

On Windows, ForkPress can now use ReFS block cloning through FSCTL_DUPLICATE_EXTENTS_TO_FILE when the site lives on clone-capable ReFS/Dev Drive storage. The release path now builds ForkPressSetup.exe; a fresh Windows user should be able to:

  1. Download ForkPressSetup.exe.
  2. Open it and accept UAC.
  3. Reboot only if Windows asks.
  4. Open Start ForkPress Site.

The installer creates protected program files under %ProgramFiles%\ForkPress, creates a protected VHDX at %ProgramData%\ForkPress\Storage\forkpress-dev-drive.vhdx, mounts it at %USERPROFILE%\ForkPressDevDrive, initializes %USERPROFILE%\ForkPressDevDrive\Sites\My ForkPress Site, and creates shortcuts.

Refs #34 and #6.

Rationale

The Windows path should not ask people to install WSL, Docker, FUSE, WinFsp, Dokany, or a developer storage stack. ReFS block cloning gives ForkPress ordinary Windows paths while still sharing unchanged file contents across branches.

The storage setup is deliberately fail-closed on Windows: if the project directory cannot block-clone, forkpress init tells the user to run ForkPressSetup.exe instead of silently creating a huge full-copy site on NTFS.

Implementation

  • Adds Windows file cloning with FSCTL_DUPLICATE_EXTENTS_TO_FILE, including ReFS alignment/chunk handling and normal copy for the unaligned tail.
  • Teaches the embedded runtime bundle to carry bin/php.exe plus the Windows PHP DLL tree.
  • Adds a Windows release build that downloads the official PHP NTS x64 runtime, writes a php.ini, builds forkpress.exe, packages a zip, and builds ForkPressSetup.exe with Inno Setup.
  • Bundles the VC++ redistributable into the Windows package instead of downloading it on the user's laptop.
  • Runs installer setup from Program Files with admin privileges, not from user-writable script paths.
  • Stores the persistent VHDX under protected ProgramData storage, rejects reparse points, sets exact owner/DACLs, and refuses to reuse a pre-existing VHDX unless it was already protected before setup.
  • Registers auto-mount with a fixed encoded command using System32 PowerShell; it does not execute a mutable script file.
  • Fails tagged Windows releases if signing secrets are missing, and signs forkpress.exe plus ForkPressSetup.exe when WINDOWS_CODESIGN_CERT_BASE64 and WINDOWS_CODESIGN_PASSWORD are configured.

Testing instructions

Local checks run on this branch:

FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo test --workspace
FORKPRESS_RUNTIME_BUNDLE=/dev/null cargo check -p forkpress-cli --target x86_64-pc-windows-msvc
npx --yes prettier --check .github/workflows/ci.yml .github/workflows/release.yml
actionlint .github/workflows/ci.yml .github/workflows/release.yml
git diff --check

The Windows release workflow also smoke-tests the packaged artifact on windows-latest by extracting the zip, running packaged forkpress.exe --version, running packaged install.ps1 against a CI ReFS VHDX, confirming an initialized site exists, and running forkpress storage status against that installed site.

Manual release validation should still include one real fresh Windows 11 x64 laptop click-through of the signed ForkPressSetup.exe, mainly to verify SmartScreen/reboot/shortcut behavior outside GitHub Actions.

@adamziel
Copy link
Copy Markdown
Contributor Author

@JanJakes I pushed the Windows click-through setup path and updated the PR description. The new workflow builds/signs the Windows installer, runs packaged install smoke on a Windows runner, and fails tagged Windows releases if signing secrets are missing.

@JanJakes
Copy link
Copy Markdown
Contributor

Is this one outdated and superseded by #36?

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