Decisions
Why the relay is hosted the way the runbook describes.
Where do public downloads come from?
From a public releases repo that CI publishes to, woodpav/link-releases,
plus https://local.link/install.sh. Installs, the install script and
upgrades all need anonymous downloads, so servers and users need no
credentials to fetch a release.
Where does server state live when servers are disposable?
Everything on a server can be rebuilt from the repo except one small set of state files, and that set is backed up. A DigitalOcean reserved IP stays with the service, so replacing a server never touches DNS, takes one command and loses nothing.
Why are certificates part of the backed-up state?
Let's Encrypt allows about 50 new certificates a week for local.link.
Rebuilding a server with empty certificate storage would re-issue all of
them, so Caddy's data goes into the snapshot and is restored with it.
Do deploys push or pull?
They pull. Each server polls the public releases repo every 5 minutes with a systemd timer, verifies the release's signature and checksum, swaps the binary and restarts, and rolls back if the health check fails. It works for any number of servers, needs no SSH secrets in CI, and a new server updates itself.
Why does bootstrap run from the operator's checkout?
Bootstrap runs as root and installs the key the updater trusts, so it
can't come from the releases repo it is there to check. The operator
pipes it over SSH from their own checkout, and it carries the release
key, kept the same as src/shared/release-signers by a test, as
install.sh does. It installs the release's deploy files only after
checking them against the signed SHA256SUMS, and installs its own copy
of the key, never the release's. Releases don't carry bootstrap.sh or
the key, so there is no copy to run by mistake. Re-running bootstrap from
a checkout without a leaked key removes that key from a server, and a
snapshot restored on the way never puts it back: bootstrap writes the key
after the import, and the import keeps the server's own.
Why does a server keep a relay version floor?
A signed release stays signed: whoever holds the releases repo could put
an older signed set back, with the units, updater and relay of that
time. The updater refuses a relay older than the one installed, but a
new server has none. So bootstrap takes the checkout's version
(--min-version, which create-droplet.sh passes), refuses a release
older than it, and leaves it in /etc/link/min-relay-version, which the
updater holds to with or without a relay installed. The version is
read from the relay binary itself, which the signed sums cover, so no
separate version file has to be signed.
How do backups leave the server?
link-state backup encrypts each snapshot with age to public keys held
off the server, then uploads it with curl --aws-sigv4 to any
S3-compatible bucket (Cloudflare R2, Backblaze B2, DigitalOcean Spaces,
AWS, or Google Cloud Storage through its S3 interoperability). A stolen
server can't read its own old backups, since it holds no private key;
rclone's crypt would need a password on the server. The backups don't
go through the bucket engine: every bucket a single relay needs already
speaks S3, and running rclone or lnk-bucket there would add a program
to the server and blur the rule that the server never depends on local
code.
