Tagdeploy

How did I set up blog.sh on my shared hosting

Pavel moved a WordPress blog off a shared host and onto blog.sh, over plain FTP. The write-up goes step by step: the WXR export, the import, rclone, a dry run, the deploy.

Worth a read if your site lives on a host that gives you FTP and nothing else.

#blogsh #wordpress #staticsite

The build doesn't know where it's going

Somebody builds a whole site on a laptop, imports a decade of old posts into it, previews every page — and none of it has gone anywhere yet. Nothing in env.sh says where, and nothing else is waiting on that: the build runs, the archive checks out, every page renders at localhost. The build doesn't know where the site is supposed to end up, and it doesn't need to.

The same build can start on a laptop, move to a rented VPS a year later, and land on a Cloudron instance after that. Nothing in the content pipeline changes between any of those moves. What changes is the answer to one question — where should the files go — and six things can answer it.

What decides it

DEPLOY_BACKEND in env.sh names the target; the values under it depend on which one. Everything past that line is identical across all six. Each backend keeps its own manifest — the SHA-256, size and modification time of every file it has already uploaded — so a deploy only ever sends what changed since the last one. deploy-web.sh --dry-run reads that manifest without touching anything.

Here's what that prints, run just now against this site's own backend:

Read more

Deploy in your own language

The wizards were translated from the start; the narration around them was not. A Czech site watched its own deploy go by in English, one line above a Czech sentence — build warnings, announcement failures, import errors, the queue's repair instructions, all of it. Not broken, exactly. Just a house where half the rooms answer in a different language.

Sixty sentences moved home

1.4 finishes the job: the deploy's whole narration — header, progress, the closing tally, every degradation notice — plus all eleven build warnings, every Bluesky and Mastodon failure, and the sentences an import prints when a source dies. English, Czech and German carry the same set, and the suite enforces the parity, so a key cannot exist in one language and abort in another.

What stays as it arrived

The diagnostics inside the sentences do not get translated: an HTTP code, a server's raw answer, an exception's text. Those are evidence, and evidence is quoted, not paraphrased — the sentence around them is the site's, the thing inside it is the network's.

Read more

The guard that switched itself off

This site's deploy has two guards. If a build suddenly has far fewer files than what's live, or far fewer bytes, the deploy stops. They exist because a broken build looks exactly like a deliberate one to rsync --delete, and a static site is only ever one confident sync away from being erased.

In 1.0 they could turn themselves off. Permanently. Silently. Here is how, because the shape of this mistake is more useful than the fix.

The reference was the wrong thing

The guards compared the new build against the deploy manifest — a record of what's on the target. Reasonable, until an upload fails. A failed upload leaves the manifest out of true, and a guard measuring against a record it knows is wrong would fire on every subsequent run.

So there was a marker: after a failed run, stand the guards down until a clean run comes along and restores the reference.

Read more

A deploy that refuses to nuke your site

Petr
I ran --prune after a broken build.
Pavel
So your site is empty.
Petr
No. The deploy refused.
Pavel
…I want that.

That's the whole feature: the deploy assumes a large change is a bug until you say otherwise.

How it works

Every deploy keeps a manifest — SHA-256, size and mtime for each uploaded file. The next deploy diffs against it and only touches what actually changed. Fast, boring, correct.

The interesting part is what happens before anything uploads. If the file count dropped by more than 20% since the last deploy, the whole thing stops. This is real output from this very site — I parked half the build's folders out of sight for a minute and asked for a deploy:

❌ Stopped: public.nosync/ has 28 files, but 62 were uploaded last time.
   That's a 55% drop -- looks like a broken build.
   Check the build output. If the drop is expected (you deleted a lot of posts), run again with --force.
Read more