I run The DJ Calendar - about 1,000 pages of PHP/MySQL on shared cPanel hosting. No shell. No SSH. No deploy pipeline. LiteSpeed caches HTML for 5 minutes, and opcache serves stale output for a minute after every write.
Pasting a code change into a production file through a browser file manager is how sites die. So over months of live deploys I built a worker pattern that makes that kind of deploy survivable - and I open-sourced it: guarded-deploy-workers.
What a "worker" actually is
A worker is a single PHP file I upload to the web root and hit once with a secret token. The skeleton is ~100 lines:
<?php
if (!isset($_GET['t']) || $_GET['t'] !== TOKEN) {
http_response_code(404);
include '404.php'; exit; // real 404 - never leak the worker
}
$src = file_get_contents($file);
if (strpos($src, 'PATCH-MARKER') !== false) exit; // idempotency
foreach ($needles as $n) // counted anchors
if (substr_count($src, $n) !== 1) exit;
copy($file, $file . '.bak');
$src = str_replace($needles, $replacements, $src);
file_put_contents($file, $src);
exec('php -l ' . escapeshellarg($file), $o, $rc);
if ($rc !== 0) { copy($file . '.bak', $file); exit; } // auto-restore
unlink($file . '.bak');
unlink(__FILE__); // self-delete
Every rule in that skeleton is there because a deploy taught me why.
The bugs that taught me the most
- A verifier that checked for an unchanged file length when the patch legitimately removed 2 bytes. It restored a correct patch. My own safety check fired on a good deploy.
- A needle string that appeared twice in the file. The patch landed in both places. Now every needle is counted, not assumed.
- opcache serving the old file long after the disk was correct - the default explanation for "the patch did not work" on shared hosting, and the reason live verification always cache-busts.
- Uppercase characters in a preg lowercase filter - the string shredder that ate a slug. Always lowercase before the character-class filter.
- A sitemap whose disk bytes did not match the served bytes - byte-exact needles false-failed until the insert walked back to the nearest
<url>tag instead of trusting whitespace. - A verifier demanding a marker the patch never wrote - false BUILD FAIL, auto-restore, no damage. The verifier must check exactly what the patch writes.
The full list is an 18-rule pre-flight checklist in the repo.
When NOT to use this
If you have a real deployment pipeline, use it. This pattern is for the world a lot of us actually live in: a cPanel box, FTP credentials, a production site that pays the bills, and no infrastructure team coming to save you.
Repo is MIT licensed: github.com/bryanhamiltondev/guarded-deploy-workers
Question for the comments: what's your survivability trick when you have zero shell access and a production fire? Genuinely collecting these for a follow-up piece.
Top comments (0)