Ship yay, wire up LUKS disk encryption, self-signed Secure Boot, release signing

yay (yay-bin, AUR-only like calamares/bibata) republished to [breadway] via
the same PKGBUILD + Forgejo workflow pattern, so users can reach the wider
AUR beyond bakery's bread ecosystem.

Disk encryption: Calamares' partition module already has LUKS support
enabled by default, but the checkbox led nowhere — no cryptsetup on the
live/target image, no mkinitcpio encrypt hook, no GRUB cryptodisk wiring.
An encrypted install would partition fine and then never boot. Added
cryptsetup, pinned luksGeneration to luks1 (GRUB doesn't support LUKS2 +
Argon2id), and post-install.sh now detects an encrypted root (lsblk TYPE
== crypt) and conditionally adds the encrypt hook + GRUB_ENABLE_CRYPTODISK +
--modules="cryptodisk luks luks2" on both grub-install passes. No effect on
a normal unencrypted install.

Secure Boot: self-signed via sbctl (shipped in packages.x86_64). BOS can't
ship a Microsoft-signed shim without going through Microsoft's own paid
UEFI CA process, so post-install.sh enrolls BOS's own keys automatically
only when the firmware is already in Setup Mode (sbctl status --json),
signs the kernel/bootloader, and leaves it alone otherwise — sbctl's own
pacman hook re-signs on every future kernel/GRUB update, no further
wiring needed.

Release signing: generated a dedicated Ed25519 "BOS Release Signing" key
(not reused from anything else), stored as the GPG_PRIVATE_KEY Forgejo
Actions secret. release-iso.yml now generates SHA256SUMS and a detached
SHA256SUMS.asc signature alongside every ISO upload; public key committed
at KEYS.asc with verification instructions in the README.

README updated: fixed a stale "greetd + tuigreet" line (breadgreet since
round 3), documented yay/encryption/secure-boot/verification.
This commit is contained in:
Breadway 2026-07-04 10:39:44 +08:00
parent 489d472240
commit 5aaf71e80a
8 changed files with 282 additions and 35 deletions

View file

@ -7,8 +7,13 @@ name: Build and release ISO
# (GitHub releases cannot host files larger than 2 GB).
#
# Required secrets:
# RELEASE_TOKEN — Forgejo API token with write:repository scope
# MIRROR_TOKEN — GitHub personal access token with repo scope (already used by mirror.yml)
# RELEASE_TOKEN — Forgejo API token with write:repository scope
# MIRROR_TOKEN — GitHub personal access token with repo scope (already used by mirror.yml)
# GPG_PRIVATE_KEY — armoured secret key for the dedicated "BOS Release Signing"
# identity (releases@breadway.dev); public half is committed
# at KEYS.asc for verification. No passphrase (CI-only key,
# access controlled via the Forgejo secret store, not a
# passphrase nobody could type non-interactively anyway).
on:
push:
@ -129,14 +134,35 @@ jobs:
bash build-local.sh
ls -lh /bos-out/*.iso
- name: Create Forgejo release and upload ISO
- name: Checksum and sign
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
set -euo pipefail
VERSION="${{ steps.vars.outputs.version }}"
ISO=$(ls /bos-out/*.iso | head -1)
ISO_NAME="bos-${VERSION}-x86_64.iso"
cd /bos-out
mv "$(basename "$ISO")" "$ISO_NAME"
sha256sum "$ISO_NAME" > SHA256SUMS
cat SHA256SUMS
pacman -Sy --noconfirm --needed gnupg
export GNUPGHOME=/tmp/gnupg-release
mkdir -m 700 -p "$GNUPGHOME"
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
gpg --batch --yes --local-user releases@breadway.dev \
--detach-sign --armor -o SHA256SUMS.asc SHA256SUMS
echo "Signed SHA256SUMS -> SHA256SUMS.asc"
- name: Create Forgejo release and upload assets
env:
FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }}
run: |
set -euo pipefail
TAG="${{ steps.vars.outputs.tag }}"
VERSION="${{ steps.vars.outputs.version }}"
ISO=$(ls /bos-out/*.iso | head -1)
ISO_NAME="bos-${VERSION}-x86_64.iso"
# Use an existing release for this tag if one exists (e.g. created
@ -157,35 +183,41 @@ jobs:
\"tag_name\": \"${TAG}\",
\"name\": \"BOS ${TAG}\",
\"prerelease\": false,
\"body\": \"ISO image attached below.\\n\\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.\"
\"body\": \"ISO image attached below. Verify with SHA256SUMS + SHA256SUMS.asc (signed by the BOS Release Signing key — see KEYS.asc in the repo).\\n\\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.\"
}")
RELEASE_ID=$(echo "${RELEASE}" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")
fi
echo "Using release ID: ${RELEASE_ID}"
# Remove any existing asset with the same name before uploading
ASSET_ID=$(curl -sf \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets" \
| python3 -c "
upload_asset() {
local file="$1" name
name="$(basename "$file")"
local asset_id
asset_id=$(curl -sf \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets" \
| python3 -c "
import json,sys
assets=json.load(sys.stdin)
match=[a['id'] for a in assets if a['name']=='${ISO_NAME}']
match=[a['id'] for a in assets if a['name']=='${name}']
print(match[0] if match else '')
" 2>/dev/null || true)
if [ -n "${ASSET_ID}" ]; then
curl -fsS -X DELETE \
if [ -n "${asset_id}" ]; then
curl -fsS -X DELETE \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets/${asset_id}"
echo "Removed existing ${name} asset"
fi
curl -fsS -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
echo "Removed existing ${ISO_NAME} asset"
fi
-F "attachment=@${file};filename=${name}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets"
echo "Uploaded: ${name}"
}
curl -fsS -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-F "attachment=@${ISO};filename=${ISO_NAME}" \
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets"
echo "Uploaded: ${ISO_NAME}"
upload_asset "/bos-out/${ISO_NAME}"
upload_asset "/bos-out/SHA256SUMS"
upload_asset "/bos-out/SHA256SUMS.asc"
- name: Create GitHub release
env:
@ -196,7 +228,7 @@ jobs:
VERSION="${{ steps.vars.outputs.version }}"
FORGEJO_URL="https://git.breadway.dev/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
printf '**Download ISO:** %s\n\nGitHub releases cannot host files >2 GB; the `bos-%s-x86_64.iso` (~2.5 GB) is on Forgejo.\n\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.' \
printf '**Download ISO:** %s\n\nGitHub releases cannot host files >2 GB; the `bos-%s-x86_64.iso` (~2.5 GB), SHA256SUMS, and SHA256SUMS.asc (signed by the BOS Release Signing key — public half at [KEYS.asc](https://github.com/Breadway/bos/blob/main/KEYS.asc)) are all on Forgejo.\n\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.' \
"${FORGEJO_URL}" "${VERSION}" > /tmp/gh-release-notes.md
gh release create "${TAG}" \