Publish the .debs as a signed apt repo on GitHub Pages - #12
Merged
Conversation
Publish the built .debs as a GPG-signed static apt repository (bookworm, component main, arches armhf/arm64/amd64). scripts/publish-apt.sh drives aptly: create a throwaway repo, carry every .deb from the previously published pool/ forward, add the new .debs, snapshot, and publish with a detached+inline GPG signature (Release/Release.gpg + InRelease). The published dists/ + pool/ tree is the only state that matters -- aptly's own database is never persisted. Because an aptly repo holds multiple versions of a package, pool/ accumulates every version ever published and the indices list them all, so apt can install or roll back to any prior version. That is the apt-side rollback story. Signing uses a dedicated GPG archive key, used ONLY for the apt Release/InRelease -- separate from the RFC-0013 minisign release key, which stays the trust root for waypointd and reference data. apt's trust model requires GPG, hence the second key. The public key is committed dearmored as waypoint-archive-keyring.gpg and is served from the Pages site so images and docs can fetch it; the private key lives only in CI secrets. apt/waypoint.sources is the deb822 client source (consumed by the image in a later PR); apt/index.html is the install/downgrade snippet page served at the Pages root. Signed-off-by: Clint Chance <clintchance@gmail.com>
Publish the apt repo to GitHub Pages (gh-pages branch) after each successful "Build stack" run on main, or on manual workflow_dispatch with a build run id. The job downloads the three per-arch .deb artifact sets, imports the signing key from the APT_SIGNING_KEY / APT_SIGNING_PASSPHRASE secrets into a throwaway GNUPGHOME (asserting it matches the committed keyring), recovers the previous gh-pages tree so pool/ versions carry forward, runs publish-apt.sh, copies the keyring + sources + install page into the site, and deploys with peaceiris/actions-gh-pages using an orphan branch to keep gh-pages bounded. Signed-off-by: Clint Chance <clintchance@gmail.com>
Add an "Installing from the apt repo" section: keyring fetch, the deb822 sources file, apt-get update/install. Document that the repo intentionally retains prior versions in pool/ and show the daemon downgrade command (apt-get install <pkg>=<version>). Add a two-key table making the scopes explicit -- the GPG archive key signs only the apt Release/InRelease, while the RFC-0013 minisign key remains the trust root for waypointd and reference data -- and point at the publish script and workflow. Also drop a stale paragraph that a main merge reintroduced: it described the removed armv6 debootstrap base and referenced armv6-base.sh, which no longer exists after the ARMv6 pipeline was dropped. Signed-off-by: Clint Chance <clintchance@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Publishes the nfpm
.debsfrom #11 as a GPG-signed static apt repository on GitHub Pages, using aptly. Validated end-to-end on real armhf hardware.Design decisions
aptly state / rollback model — reconstruct from the published tree (not a state branch). aptly's database is never persisted. Each publish recreates a throwaway repo, re-adds every
.debfrom the previously publishedpool/, adds the new.debs, snapshots, and republishes. An aptly repo holds multiple versions of a package, sopool/accumulates every version ever shipped and the indices list them all — apt can install or downgrade to any of them. The publisheddists/+pool/tree is the single source of truth; losing the aptly db costs nothing. This is simpler than persisting a boltdb in a side branch and has no way to silently drop a prior version.Two signing keys, two scopes (documented in the README):
Release/InRelease.The GPG key was generated for this repo (fingerprint
1523 696F 24FB 1B2A 9524 3013 41D9 59A8 25C3 D240). Public key committed dearmored aswaypoint-archive-keyring.gpg(also served from Pages); private key + passphrase set as theAPT_SIGNING_KEY/APT_SIGNING_PASSPHRASEActions secrets (both set on the repo).Pages deploy:
peaceiris/actions-gh-pagesto an orphangh-pagesbranch — a branch is trivially checkout-able, which is exactly what the "recover previouspool/" step needs; orphaning keeps the branch from growing unbounded sincepool/already carries the full history forward.What's here
scripts/publish-apt.sh— aptly add → snapshot → publish, GPG-signed, carries priorpool/forward..github/workflows/publish-apt.yml—workflow_runon a successfulmain"Build stack", orworkflow_dispatchwith a run id → download artifacts → publish → deploy Pages. (actionlint clean.)apt/waypoint.sources(deb822 client source for the image PR),apt/index.html(install page served at the Pages root),waypoint-archive-keyring.gpg.debootstrapparagraph that amainmerge reintroduced (it referenced the deletedarmv6-base.sh).Local validation (aptly 1.6.2)
--previous) adding a+wp2repackage:pool/and the armhfPackagesindex retain bothwp1andwp2. Signature verifies (gpgvagainst the committed keyring) — good signature on bothInReleaseand detachedRelease.gpg.binary-amd64,binary-arm64,binary-armhfeach list 12 packages; 34 pool files (12×3 − 2 duparch: allmetapackages).Bench validation (pi-star@172.16.50.13,
wpsd, armhf/trixie)Served the signed tree from the box's own localhost (my host and the Pi are on different subnets), configured
/usr/share/keyrings/waypoint-archive-keyring.gpg+/etc/apt/sources.list.d/waypoint.sources.Signed
apt-get update:apt-get install waypoint-stack(metapackage 0.2.0) — all 12 packages install, daemons run:Downgrade — daemon level (two versions retained;
apt-cache madisonlistswp2andwp1):Downgrade — whole stack (0.2.0 → 0.1.0):
Restore: purged all packages, removed the sources file + keyring, stopped the local server, removed temp files. Final state: 0 waypoint packages, 8 waypointd services running, MMDVM-Host live on
/dev/ttyAMA0.One finding worth flagging
Under apt's new 3.0 solver (trixie), a stack-level downgrade (
apt-get install waypoint-stack=0.1.0) needs the changed daemon named explicitly (… waypoint-nxdnparrot=<wp1>) — the solver won't auto-downgrade an already-installed newer dependency to satisfy an older metapackage. Daemon-level downgrade (the task's requirement) works directly. The README documents the daemon-level command; the metapackage pins exact versions, so in normal operation a daemon bump ships with a matching metapackage bump (demonstrated above withwaypoint-stack0.2.0).To go live (follow-ups, need repo-admin / merge order)
main.gh-pagesbranch) — currentlyhas_pages: false. First workflow run creates the branch.build.ymlmust run onmainfor theworkflow_runtrigger to fire (or dispatch manually with a run id).