feat(release): signed SHA256SUMS.txt for the Linux downloads (#36)

The .deb and .pkg.tar.zst are not signed packages, and the in-app
update prompt has users install them by hand, so nothing checked them.
A new checksums job hashes the Linux downloads into SHA256SUMS.txt,
signs it with the updater's minisign key (tauri signer) and uploads
SHA256SUMS.txt + SHA256SUMS.txt.minisig. The README shows the
verify-then-install command.

Refs #36

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
This commit is contained in:
Lotus CI
2026-10-19 00:35:30 -04:00
co-authored by Claude Opus 5.5
parent 4019cbaef1
commit 4b9f3c092d
2 changed files with 62 additions and 0 deletions
+46
View File
@@ -351,6 +351,52 @@ jobs:
-H "Content-Type: application/octet-stream" \
--data-binary @"$PKG"
# [cinny-desktop #36] The .deb / .pkg.tar.zst aren't signed packages, and
# the in-app update prompt has users install them by hand. Publish a
# SHA256SUMS.txt for the Linux downloads, signed with the updater's minisign
# key, so the install command can verify before installing.
checksums:
needs: [prepare, build-linux, build-arch]
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Hash, sign and upload SHA256SUMS.txt
env:
TOKEN: ${{ secrets.RELEASE_TOKEN }}
RELEASE_ID: ${{ needs.prepare.outputs.release_id }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_PRIVATE_KEY_PASSWORD: ''
run: |
set -euo pipefail
BASE="$GITEA_URL/LotusGuild/cinny-desktop/releases/download/latest"
mkdir -p sums && cd sums
for f in LotusChat-x86_64.deb LotusChat-x86_64.pkg.tar.zst LotusChat-x86_64.AppImage; do
curl -sfL -o "$f" "$BASE/$f"
done
sha256sum LotusChat-x86_64.deb LotusChat-x86_64.pkg.tar.zst LotusChat-x86_64.AppImage > SHA256SUMS.txt
cat SHA256SUMS.txt
# The Tauri signer writes <file>.sig (base64 of a minisign signature)
# and needs a file extension. Publish the decoded .minisig so users
# can run `minisign -Vm` directly.
npx --yes @tauri-apps/cli@2.7.1 signer sign SHA256SUMS.txt
base64 -d SHA256SUMS.txt.sig > SHA256SUMS.txt.minisig
for NAME in SHA256SUMS.txt SHA256SUMS.txt.minisig; do
OLD=$(curl -sf "$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets" \
-H "Authorization: token $TOKEN" \
| python3 -c "import sys,json; print(next((str(a['id']) for a in json.load(sys.stdin) if a['name']=='$NAME'), ''))" 2>/dev/null || true)
[ -n "$OLD" ] && curl -sf -X DELETE \
"$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets/$OLD" \
-H "Authorization: token $TOKEN" || true
curl -sf -X POST \
"$GITEA_URL/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=$NAME" \
-H "Authorization: token $TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @"$NAME"
done
update-manifest:
needs: [prepare, build-windows, build-linux]
runs-on: ubuntu-latest
+16
View File
@@ -19,6 +19,22 @@ Builds are published on this repo's releases page:
There is no macOS build at the moment.
### Verify a Linux download
Each release has a `SHA256SUMS.txt`, signed with the same key as the updater
(below). Check the signature, then the file, then install, e.g. for Arch:
```sh
B=https://code.lotusguild.org/LotusGuild/cinny-desktop/releases/download/latest
curl -LO $B/LotusChat-x86_64.pkg.tar.zst -LO $B/SHA256SUMS.txt -LO $B/SHA256SUMS.txt.minisig
minisign -Vm SHA256SUMS.txt -P RWRZZdyii05/NUcz337A5SAbiZK+NPVDWuiL2mM5Jk1p/LfRmNfiZ/6l \
&& sha256sum -c --ignore-missing SHA256SUMS.txt \
&& sudo pacman -U ./LotusChat-x86_64.pkg.tar.zst
```
For Debian / Ubuntu use `LotusChat-x86_64.deb` and `sudo apt install ./LotusChat-x86_64.deb`.
`minisign` is in both distributions' repositories.
### Updates and signatures
The app updates itself from