server: refuse unsigned releases and polluted reserved addresses
Self-update now verifies SHA256SUMS.sig (ed25519, relsign package) against a public key baked into the binary; the private key exists only in the CI secret store, so a compromised release host can withhold updates but not inject one. CI signs on every server-v* tag and hard-fails without the secret. Operators with their own pipeline override the key via ECHOLOT_SELF_UPDATE_PUBKEY (mint a pair with release-sign -gen). Startup also now proves 80/443 are actually free on the reserved measurement addresses by asking the OS (throwaway bind), not the config - CheckReserved could never see a stray process, and the adb-beacon receiver on 0.0.0.0:443 was exactly that. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
20cfecf566
commit
a49bef5821
+11
-6
@@ -106,9 +106,7 @@ ECHOLOT_UDP_LISTEN=203.0.113.10:8442,203.0.113.11:8442,[2001:db8::10]:8442,[2001
|
||||
|
||||
Passing `--self-update-api` to `--install-systemd` additionally installs a daily randomized
|
||||
self-update timer (`echolot-server-update.timer`) that restarts the service after a successful
|
||||
update. Updates are checksum-verified against the release's `SHA256SUMS` (integrity, not
|
||||
authenticity — signature verification remains TODO before treating the update source as
|
||||
untrusted).
|
||||
update.
|
||||
|
||||
### Self-update (opt-in, native only)
|
||||
|
||||
@@ -119,8 +117,15 @@ echolot-server --self-update \
|
||||
|
||||
Fetches the newest `server-v*` release asset for this OS/arch and atomically replaces the
|
||||
binary; systemd's `Restart=` brings up the new version. Run it from a systemd timer for
|
||||
unattended updates. TODO before enabling anywhere untrusted: signature verification of the
|
||||
downloaded asset.
|
||||
unattended updates.
|
||||
|
||||
Releases are trusted by signature, not by host: CI signs `SHA256SUMS` with an ed25519 key that
|
||||
exists only in its secret store (`RELEASE_SIGNING_KEY`), and the updater verifies
|
||||
`SHA256SUMS.sig` against the public key baked into the binary before believing any checksum —
|
||||
an unsigned or re-signed release is refused, so a compromised Gitea can withhold updates but not
|
||||
inject one. Running your own release pipeline? Mint a keypair with
|
||||
`go run ./cmd/release-sign -gen`, set the secret, and point `ECHOLOT_SELF_UPDATE_PUBKEY` (or
|
||||
`--self-update-pubkey`) at your public key.
|
||||
|
||||
## First contact
|
||||
|
||||
@@ -144,7 +149,7 @@ go vet ./...
|
||||
|
||||
CI (`.gitea/workflows/build-server.yml`): tests on every push touching `server/`;
|
||||
tagging `server-v1.2.3` builds + pushes the container image to the Gitea registry and
|
||||
attaches static linux amd64/arm64 binaries (+ SHA256SUMS) to a release — the same
|
||||
attaches static linux amd64/arm64 binaries (+ signed SHA256SUMS) to a release — the same
|
||||
artifacts `--self-update` consumes.
|
||||
|
||||
## TLS for the admin UI
|
||||
|
||||
Reference in New Issue
Block a user