Files
shater/ci/gen-apk-key.sh
T
omarandClaude Opus 5 f86501bf77 ci!: drop the opkg lane — apk only, and fix the stale rolling release
Both routers are past opkg: mini_router runs ImmortalWrt 25.12.1 and
main_router OpenWrt 25.12.0, both with apk-tools 3.0.5, and main_router has
no `opkg` binary at all. The 24.10 lane was building and signing a feed no
device could consume.

Removed jobs `build` and `release` with the scripts only they called
(ci/build-feed.sh, ci/sdk-build.sh, ci/make-index.sh, ci/install-usign.sh)
and the usign trust anchor dist/shater-feed.pub. A committed public key is
an instruction: it invites the old install path for a feed that is no longer
produced. The key is retired, not revoked -- git history keeps it, KEY_BUILD
still holds the secret half, and a usign secret contains its own public half,
so the identity is reconstructible if a 24.10 device ever needs serving.
D7 is marked SUPERSEDED by the new D22 rather than deleted.

Separately: the rolling `apk-latest-<arch>` release was frozen at 0.2.0 from
2026-07-24 while every tag run published its versioned release correctly.
The publish loop was an either/or -- `TAG=apk-latest-<arch>` when VER=latest
(workflow_dispatch only), ELSE `TAG=apk-<ver>-<arch>` -- so a `v*` tag run
never touched the rolling pointer. Asset replacement was never the problem;
ci/gitea-release.sh already deletes before recreating. A router pinned to
the rolling URL sat on 0.2.0 while `apk update` reported success: silent
staleness, the failure mode this repo keeps having to close.

The rolling pointer is now published on EVERY run, tag runs included, and a
new assert reads the release back over the API afterwards: our three
tag-versioned packages at the built version plus the index and the key must
be present (exit 13), and no package asset at any other version may survive
(exit 14). Same class of check as sdk-build-apk.sh's package-version assert,
added for the same reason -- the previous failure mode was silent.

KEY_BUILD can now be deleted from the Gitea repo secrets; nothing references
it. Docs state plainly that mini_router is deliberately pinned to a
versioned URL and that the hand-edit per release is the price of pinning.

Known consequence: the x86_64 QEMU testbed is still OpenWrt 24.10.3 and can
no longer install our packages. Its 25.12 rebuild is in flight separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H4PcWfrBRyg4eWN58axaGN
2026-07-25 18:46:21 +03:00

49 lines
2.1 KiB
Bash
Executable File

#!/bin/sh
# ci/gen-apk-key.sh — generate the Shater **apk** feed signing keypair (25.12 lane).
#
# apk (OpenWrt/ImmortalWrt 25.12+) verifies package indexes with EC keys
# (prime256v1 PEM). This is the ONLY feed identity shater has since the opkg
# lane was removed (D22) — the old usign key is history, not a second lane.
#
# dist/shater-apk.key EC PRIVATE key. NEVER commit (dist/ is gitignored).
# Paste its full PEM contents into the Gitea repo secret
# KEY_APK. Then delete the local file (or keep it in a
# password manager as the offline backup — losing it
# means every deployed router must re-trust a new key).
# dist/shater-apk.pem PUBLIC key. Commit it:
# git add -f dist/shater-apk.pem
# (-f because /dist/ is gitignored). Routers install it
# as /etc/apk/keys/shater-apk.pem.
#
# Run ONCE. Refuses to overwrite: regenerating the key invalidates the trust of
# every router that already installed shater-apk.pem (see D22).
set -eu
REPO="$(cd "$(dirname "$0")/.." && pwd)"
SEC="$REPO/dist/shater-apk.key"
PUB="$REPO/dist/shater-apk.pem"
command -v openssl >/dev/null 2>&1 || { echo "[apk-key] ERROR: openssl not found" >&2; exit 1; }
if [ -e "$SEC" ] || [ -e "$PUB" ]; then
echo "[apk-key] ERROR: $SEC or $PUB already exists." >&2
echo " Regenerating would invalidate every deployed router's trust." >&2
echo " Delete BOTH files manually if you REALLY mean to rotate the key." >&2
exit 1
fi
mkdir -p "$REPO/dist"
umask 077
# prime256v1 EC key — the exact form the OpenWrt 25.12 buildsystem generates for
# BUILD_KEY_APK_SEC and `apk mkndx --sign` consumes.
openssl ecparam -name prime256v1 -genkey -noout -out "$SEC"
openssl ec -in "$SEC" -pubout -out "$PUB" 2>/dev/null
chmod 0644 "$PUB"
echo "[apk-key] generated:"
echo " private: $SEC (-> Gitea secret KEY_APK; do NOT commit)"
echo " public : $PUB (-> git add -f dist/shater-apk.pem; routers: /etc/apk/keys/shater-apk.pem)"
echo
echo "[apk-key] public key:"
cat "$PUB"