steid

@jamesgill /

build: release 0.2.0, and target AWS Lightsail

Bumps the version before anything is downloadable. A 0.1.0 tarball existed twice
today with different bytes — once before the security headers and profile
rebuild, once after — and republishing different contents under one version is
the confusing kind of wrong once a URL is public. Nothing was ever served, so
this costs nothing now and would have cost a support conversation later.

The unpublished 0.1.0 artefacts are deleted rather than kept: they predate the
security headers, and the rsync in the runbook globs dist/*.tar.gz, so leaving
them would have uploaded a build with no CSP alongside one that has it.

The runbook now targets Lightsail rather than Hetzner, after Hetzner's signup
asked for identity verification and an AWS account already existed. Lightsail
rather than EC2 because it is AWS's actual VPS product; EC2 would mean
assembling the same box from a VPC, security groups, EBS and an Elastic IP with
per-GB egress on top.

Three Lightsail specifics are written down because each fails silently: a
Lightsail instance takes a new public IP on stop/start unless a static IP is
attached, so a reboot breaks DNS and certificate renewal with nothing obvious to
blame; only port 22 is open by default and Let's Encrypt validates over 80, so
allowing 443 alone fails at issuance rather than at first request; and snapshots
are whole-disk and same-account, so they are not backups.

Both artefacts verified on Debian 11: health check, apex redirect to the owner's
profile, CSP present, and __Host-session with Secure.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JZwc7URWKVhkAuRTWiDmjA
JamesPatrickGill authored 1 day agoparentbd13b12Browse files7fb0b5e48d0dfa3adce904b16d570ce0a063cb87

4 files changed+21 −9

Cargo.lock+1 −1View file
@@ -1897,7 +1897,7 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
18971897
18981898 [[package]]
18991899 name = "steid"
1900version = "0.1.0"
1900+version = "0.2.0"
19011901 dependencies = [
19021902 "argon2",
19031903 "base64 0.22.1",
Cargo.toml+1 −1View file
@@ -1,6 +1,6 @@
11 [package]
22 name = "steid"
3version = "0.1.0"
3+version = "0.2.0"
44 edition = "2024"
55
66 [dependencies]
install.sh+1 −1View file
@@ -50,7 +50,7 @@ RELEASE_BASE_URL="${STEID_RELEASE_BASE_URL:-https://jpgilldev.com/jamesgill/repo
5050 # The version to install. Pinned rather than "latest" because there is no
5151 # redirect to resolve "latest" against, and a pinned default makes the upgrade
5252 # path explicit: `--version 0.2.0`.
53VERSION="${STEID_VERSION:-0.1.0}"
53+VERSION="${STEID_VERSION:-0.2.0}"
5454 # ----------------------------------------------------------------------------
5555
5656 # The build target to fetch. musl is preferred — one static binary that does not
plans/runbook.md+18 −6View file
@@ -257,12 +257,24 @@ and the place everyone else downloads Steid from.
257257
258258 ### Order matters
259259
2601. **Provision** — Hetzner, Debian 12. **CX** (x86) or **CAX** (Ampere ARM) both work:
261 releases are built for `x86_64` and `aarch64`, and `install.sh` picks between them
262 from `uname -m`. Hetzner has no UK region — Falkenstein, Nuremberg or Helsinki are the
263 EU options, and the extra latency matters only for your own pushes.
264
265 Open **22, 80 and 443**. Port 80 is not optional: Let's Encrypt validates over it.
260+1. **Provision — AWS Lightsail**, Debian 12 blueprint. Lightsail rather than EC2
261+ deliberately: it *is* AWS's VPS product, where EC2 makes you assemble the same box out
262+ of a VPC, security groups, an EBS volume and an Elastic IP, with per-GB egress on top.
263+ Either architecture works — releases are built for `x86_64` and `aarch64`, and
264+ `install.sh` picks between them from `uname -m`, so a Graviton instance is fine.
265+
266+ Three Lightsail-specific things, each of which breaks the deployment silently if
267+ missed:
268+
269+ - **Attach a static IP.** A Lightsail instance takes a *new* public IP on stop/start.
270+ Without one, a reboot changes the address, DNS points at nothing, and Caddy's
271+ certificate renewals start failing with no obvious cause. Free while attached to a
272+ running instance.
273+ - **Open 80 and 443** in the instance's Networking tab. Only 22 is open by default,
274+ and **Let's Encrypt validates over port 80** — a firewall that allows 443 alone
275+ fails at certificate issuance, not at first request.
276+ - **Snapshots are not backups.** They are whole-disk and live in the same AWS account.
277+ The two state paths still want copying somewhere else.
266278 2. **DNS first, then install.** `dig +short jpgilldev.com` must return the box's IP
267279 *before* `install.sh` runs. Caddy requests a certificate on startup; if DNS has not
268280 propagated it fails and backs off, and the resulting error points nowhere useful.