feat(rpm): enable gpgcheck=1 — packages are signed + verified
apple / swift (push) Successful in 54s
ci / rust (push) Successful in 1m5s
ci / web (push) Successful in 30s
android / android (push) Successful in 2m2s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 1m39s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 20s
deb / build-publish (push) Successful in 3m10s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m19s
docker / deploy-docs (push) Successful in 19s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 5m7s
apple / swift (push) Successful in 54s
ci / rust (push) Successful in 1m5s
ci / web (push) Successful in 30s
android / android (push) Successful in 2m2s
ci / docs-site (push) Successful in 31s
ci / bench (push) Successful in 1m39s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 5s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 20s
deb / build-publish (push) Successful in 3m10s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 5m19s
docker / deploy-docs (push) Successful in 19s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 5m7s
The signing rollout is confirmed end to end: the latest published RPM (0.2.0-0.ci1089) carries a header GPG signature (added by `rpm --addsign`) and passed the in-CI `rpmkeys --checksig` self-verify before publishing (a bad/unsigned build fails that gate and never reaches the registry). So flip every .repo snippet from gpgcheck=0 to gpgcheck=1 and add the package-signing public key (served from the generic registry, committed at packaging/rpm/RPM-GPG-KEY-punktfunk) to gpgkey= alongside the Gitea metadata key — dnf/rpm-ostree imports both. Covers rpm/README, packaging/README, the bootc Containerfile, and the docs-site bazzite/fedora-kde install pages; rpm/README's signing section reframed from "dormant/enabling" to active (+ key-rotation notes). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -40,15 +40,16 @@ push), mirroring the [Debian/apt](debian/README.md) setup. Add one repo file, in
|
||||
updates with `rpm-ostree upgrade` — no COPR account needed. Full guide: [`rpm/README.md`](rpm/README.md).
|
||||
|
||||
```sh
|
||||
# unsigned pkgs + Gitea-signed metadata → repo_gpgcheck=1, gpgcheck=0 (see rpm/README.md)
|
||||
# GPG-signed pkgs + Gitea-signed metadata → gpgcheck=1, repo_gpgcheck=1 (see rpm/README.md)
|
||||
sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO'
|
||||
[gitea-unom-bazzite]
|
||||
name=punktfunk (unom, Bazzite)
|
||||
baseurl=https://git.unom.io/api/packages/unom/rpm/bazzite
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key
|
||||
https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk
|
||||
REPO
|
||||
rpm-ostree install punktfunk && systemctl reboot
|
||||
# updates: rpm-ostree upgrade && systemctl reboot
|
||||
|
||||
@@ -20,7 +20,7 @@ FROM ${BASE_IMAGE}
|
||||
# packaging/rpm/README). Use it rather than COPR specifically because it carries the
|
||||
# punktfunk-web management console subpackage, which COPR's mock chroot can't build (no `bun`).
|
||||
# Group "bazzite" == the Fedora 43 base; override for a different base. Gitea signs the repo
|
||||
# metadata (repo_gpgcheck=1); the packages themselves are unsigned (gpgcheck=0).
|
||||
# metadata (repo_gpgcheck=1) and the packages are GPG-signed (gpgcheck=1, the packages@unom.io key).
|
||||
ARG PUNKTFUNK_RPM_GROUP=bazzite
|
||||
|
||||
# RPM Fusion nonfree provides the NVENC-capable ffmpeg-libs punktfunk records/encodes with.
|
||||
@@ -35,8 +35,8 @@ RUN printf '%s\n' \
|
||||
'[gitea-unom-punktfunk]' \
|
||||
'name=punktfunk (unom)' \
|
||||
"baseurl=https://git.unom.io/api/packages/unom/rpm/${PUNKTFUNK_RPM_GROUP}" \
|
||||
'enabled=1' 'gpgcheck=0' 'repo_gpgcheck=1' \
|
||||
'gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key' \
|
||||
'enabled=1' 'gpgcheck=1' 'repo_gpgcheck=1' \
|
||||
'gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk' \
|
||||
> /etc/yum.repos.d/punktfunk.repo \
|
||||
&& dnf5 -y install punktfunk punktfunk-web \
|
||||
&& dnf5 clean all
|
||||
|
||||
+21
-23
@@ -17,18 +17,17 @@ paths — same spec (`punktfunk.spec`) — just self-hosted in Gitea instead of
|
||||
## Install on a Bazzite host (one-time)
|
||||
|
||||
```sh
|
||||
# Add the repo. Our RPMs are unsigned, but Gitea GPG-signs the repo METADATA — so verify that
|
||||
# (repo_gpgcheck=1) and skip the per-package signature check (gpgcheck=0). The signed metadata
|
||||
# carries each package's SHA256, so authenticity still holds. (Don't just curl Gitea's served
|
||||
# bazzite.repo — it sets gpgcheck=1, which fails on unsigned packages.)
|
||||
# Add the repo. Packages are GPG-signed (gpgcheck=1, the packages@unom.io key) AND the repo
|
||||
# metadata is Gitea-signed (repo_gpgcheck=1); gpgkey lists both so dnf/rpm-ostree imports each.
|
||||
sudo tee /etc/yum.repos.d/punktfunk.repo >/dev/null <<'REPO'
|
||||
[gitea-unom-bazzite]
|
||||
name=punktfunk (unom, Bazzite)
|
||||
baseurl=https://git.unom.io/api/packages/unom/rpm/bazzite
|
||||
enabled=1
|
||||
gpgcheck=0
|
||||
gpgcheck=1
|
||||
repo_gpgcheck=1
|
||||
gpgkey=https://git.unom.io/api/packages/unom/rpm/repository.key
|
||||
https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk
|
||||
REPO
|
||||
|
||||
# Layer the host + the web console (pairing/status), then reboot into the new deployment.
|
||||
@@ -41,18 +40,19 @@ systemctl reboot
|
||||
> If `rpm-ostree` can't complete the metadata GPG check non-interactively, set `repo_gpgcheck=0`
|
||||
> (TLS-only trust to the self-hosted registry).
|
||||
|
||||
## Enabling per-package signing (`gpgcheck=1`)
|
||||
## Per-package signing (`gpgcheck=1`, active)
|
||||
|
||||
CI is wired to GPG-sign each RPM (`packaging/rpm/sign-rpms.sh`, run from `rpm.yml`), but it's
|
||||
**dormant** until you provide a signing key — until then packages publish unsigned and the repo
|
||||
above uses `gpgcheck=0`. This is a self-hosted registry served over HTTPS with GPG-signed metadata
|
||||
(`repo_gpgcheck=1`), so per-package signing is hardening, not a correctness fix. (Note: this is a
|
||||
GPG/OpenPGP key — a `step-ca`/X.509 cert can't sign RPMs; step-ca is for the registry/console TLS.)
|
||||
CI GPG-signs every RPM: `packaging/rpm/sign-rpms.sh` (run from `rpm.yml` between build and publish)
|
||||
signs with the dedicated EdDSA key **`packages@unom.io`** (`AF245C506F4E4763`) and self-verifies
|
||||
with `rpmkeys --checksig` before publishing, so an unsigned/bad build never reaches the registry.
|
||||
The public key is served from the registry (the `gpgkey=` URL above) and committed at
|
||||
`packaging/rpm/RPM-GPG-KEY-punktfunk`. (This is a GPG/OpenPGP key — a `step-ca`/X.509 cert can't
|
||||
sign RPMs; step-ca is only for registry/console TLS.)
|
||||
|
||||
One-time setup:
|
||||
How it was set up (and how to rotate the key):
|
||||
|
||||
```sh
|
||||
# 1. Generate a DEDICATED, passphrase-less signing key (separate from the Gitea registry key).
|
||||
# 1. Generate a DEDICATED, passphrase-less signing key (separate from the Gitea metadata key).
|
||||
gpg --batch --gen-key <<EOF
|
||||
%no-protection
|
||||
Key-Type: eddsa
|
||||
@@ -62,19 +62,17 @@ Name-Email: packages@unom.io
|
||||
Expire-Date: 0
|
||||
%commit
|
||||
EOF
|
||||
gpg --armor --export-secret-keys packages@unom.io # -> paste into the CI secret below
|
||||
gpg --armor --export packages@unom.io > RPM-GPG-KEY-punktfunk # the PUBLIC key
|
||||
gpg --armor --export-secret-keys packages@unom.io # -> the RPM_GPG_PRIVATE_KEY CI secret
|
||||
gpg --armor --export packages@unom.io > packaging/rpm/RPM-GPG-KEY-punktfunk # public half
|
||||
|
||||
# 2. In the repo's Gitea Actions secrets, add RPM_GPG_PRIVATE_KEY = the armored PRIVATE key
|
||||
# (and RPM_GPG_PASSPHRASE only if the key has one). The next CI run signs + self-verifies.
|
||||
|
||||
# 3. Publish RPM-GPG-KEY-punktfunk where clients can fetch it, then on each host import it and
|
||||
# flip the repo to gpgcheck=1:
|
||||
sudo rpm --import https://git.unom.io/.../RPM-GPG-KEY-punktfunk
|
||||
sudo sed -i 's/^gpgcheck=0/gpgcheck=1/' /etc/yum.repos.d/punktfunk.repo
|
||||
# 2. Add the armored PRIVATE key as the RPM_GPG_PRIVATE_KEY Gitea Actions secret. Commit the public
|
||||
# half and publish it to the registry so the gpgkey= URL resolves:
|
||||
curl --user "<user>:<write:package-PAT>" --upload-file packaging/rpm/RPM-GPG-KEY-punktfunk \
|
||||
https://git.unom.io/api/packages/unom/generic/punktfunk-keys/1/RPM-GPG-KEY-punktfunk
|
||||
```
|
||||
|
||||
Do **not** flip `gpgcheck=1` before a signed build has published, or installs will fail.
|
||||
Rotating the key means a new generic-registry version (bump `punktfunk-keys/1` → `/2` and the
|
||||
`gpgkey=` URL), since the registry rejects re-uploading an existing file.
|
||||
|
||||
After reboot, as the desktop user:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user