diff --git a/.gitea/scripts/fdroid.sh b/.gitea/scripts/fdroid.sh deleted file mode 100755 index 5f9a71b..0000000 --- a/.gitea/scripts/fdroid.sh +++ /dev/null @@ -1,126 +0,0 @@ -#!/bin/sh -set -eu -version=${1:-} -here=$(pwd) -root=${PACKAGES_ROOT:-/var/www/packages.arasaka.software} -keep=${FDROID_KEEP:-3} -url=https://packages.arasaka.software/fdroid/repo -fingerprint=5F52CFF4F52F4E0B6DA6CD044BFCEAF78D1D42DB24F2470602DB7F19CBFDF846 -id=software.arasaka.meweb -if [ -z "${MEWEB_KEYSTORE_B64:-}" ] || [ -z "${MEWEB_KEYSTORE_PASS:-}" ]; then - echo "::error::the repository secrets MEWEB_KEYSTORE_B64 and MEWEB_KEYSTORE_PASS are not set" - exit 1 -fi -if [ -n "$version" ]; then - apk=$here/releases/$version/MeWeb-$version-android.apk - test -f "$apk" - major=$(echo "$version" | cut -d. -f1) - minor=$(echo "$version" | cut -d. -f2) - patch=$(echo "$version" | cut -d. -f3) - code=$((major * 10000 + minor * 100 + patch)) -elif [ ! -e "$root/fdroid/repo" ]; then - echo "no repository at $root/fdroid/repo yet: the first release makes it" - exit 0 -fi - -tools/setup.sh --group fdroid -tools=$(cd "$here/tools/fdroid/linux-x64" && pwd -P) -uv=$tools/uv-x86_64-unknown-linux-gnu/uv -python=$(command -v python3) -JAVA_HOME=$(ls -d "$here"/tools/jdk/linux-x64/*/ | head -n 1) -ANDROID_HOME=$here/tools/android-sdk -PATH=$JAVA_HOME/bin:$PATH -export JAVA_HOME ANDROID_HOME PATH - -exec 9>>"$root/.lock" -flock -w 2700 9 -work=$(mktemp -d) -trap 'rm -rf "$work"' EXIT -keyless() { - env -u MEWEB_KEYSTORE_B64 -u MEWEB_KEYSTORE_PASS UV_CACHE_DIR="$tools/cache" "$@" -} - -if [ -n "$version" ] && "$tools/current/bin/fdroid" --version > /dev/null 2>&1; then - install=$(readlink -f "$tools/current") -else - settled=$(date -u -d '14 days ago' +%Y-%m-%dT%H:%M:%SZ) - echo fdroidserver | keyless "$uv" pip compile -q --python "$python" --exclude-newer "$settled" --generate-hashes \ - --no-header --no-annotate -o "$work/lock.txt" - - install=$tools/fdroidserver-$(sha256sum < "$work/lock.txt" | cut -c1-12) - if ! "$install/bin/fdroid" --version > /dev/null 2>&1; then - rm -rf "$install" - keyless "$uv" venv -q --python "$python" "$install" - keyless "$uv" pip sync -q --python "$install/bin/python" "$work/lock.txt" - cp "$work/lock.txt" "$install/lock.txt" - fi -fi -tool=$("$install/bin/fdroid" --version) -stamp=$( { cat "$install/lock.txt"; cd packaging/fdroid && find config.yml icon.png metadata -type f | LC_ALL=C sort | xargs sha256sum; } | sha256sum | cut -d' ' -f1) -if [ -z "$version" ] && [ "$(cat "$(readlink -f "$root/fdroid/repo")/../built-from" 2>/dev/null)" = "$stamp" ]; then - echo "nothing new: the repository is already built with fdroidserver $tool and this listing" - exit 0 -fi -echo "fdroidserver $tool, $(basename "$install")" - -(umask 077 && printf '%s' "$MEWEB_KEYSTORE_B64" | base64 -d > "$work/meweb.keystore") -MEWEB_KEYSTORE=$work/meweb.keystore -export MEWEB_KEYSTORE MEWEB_KEYSTORE_PASS -unset MEWEB_KEYSTORE_B64 -held=$(keytool -J-Duser.language=en -list -v -keystore "$MEWEB_KEYSTORE" -storepass:env MEWEB_KEYSTORE_PASS -alias meweb | sed -n 's/^.*SHA256: *//p' | tr -d ':') -test "$held" = "$fingerprint" - -state=$root/.fdroid -snap=$state/$(date -u +%Y%m%d%H%M%S)-${version:-tools} -mkdir -p "$snap/repo" "$snap/metadata" "$snap/tmp" -if [ -e "$root/fdroid/repo" ]; then - prior=$(readlink -f "$root/fdroid/repo")/.. - for file in "$prior"/repo/*.apk; do - [ -e "$file" ] && ln "$file" "$snap/repo/" - done - for icons in "$prior"/repo/icons*; do - [ -d "$icons" ] && cp -a "$icons" "$snap/repo/" - done - cp -a "$prior/metadata/." "$snap/metadata/" - cp "$prior/repo/index-v2.json" "$snap/repo/" - if [ -f "$prior/tmp/apkcache.json" ]; then cp "$prior/tmp/apkcache.json" "$snap/tmp/"; fi -fi -cp packaging/fdroid/config.yml "$snap/config.yml" -chmod 600 "$snap/config.yml" -cp packaging/fdroid/icon.png "$snap/icon.png" -cp -r packaging/fdroid/metadata/. "$snap/metadata/" -if [ -n "$version" ]; then - rm -f "$snap/repo/${id}_$code.apk" - cp "$apk" "$snap/repo/${id}_$code.apk" -fi -(cd "$snap/repo" && ls "$id"_*.apk | sed 's/.*_\([0-9]*\)\.apk$/\1/' | sort -n | head -n "-$keep" | while read -r old; do - rm -f "${id}_$old.apk" -done) -newest=$(cd "$snap/repo" && ls "$id"_*.apk | sed 's/.*_\([0-9]*\)\.apk$/\1/' | sort -n | tail -n 1) - -(cd "$snap" && "$install/bin/fdroid" update) -rm -rf "$snap/repo/status" -chmod -R u=rwX,go=rX "$snap/repo" -echo "$stamp" > "$snap/built-from" - -mkdir -p "$root/fdroid" -ln -sfn "../.fdroid/$(basename "$snap")/repo" "$root/fdroid/repo.new" -mv -T -f "$root/fdroid/repo.new" "$root/fdroid/repo" -ls -1d "$state"/*/ | sort | head -n -3 | while read -r old; do - find "$old" -maxdepth 0 -mmin +1440 -exec rm -rf {} + -done -echo "published $root/fdroid/repo, newest ${id}_$newest.apk, with fdroidserver $tool" - -if [ "$root" = /var/www/packages.arasaka.software ]; then - curl -fsS "$url/entry.jar" -o "$work/entry.jar" - signed=$(keytool -J-Duser.language=en -printcert -jarfile "$work/entry.jar" | sed -n 's/^.*SHA256: *//p' | head -n 1 | tr -d ':') - test "$signed" = "$fingerprint" - curl -fsS "$url/index-v2.json" | grep -Eq "\"versionCode\": ?$newest\b" - curl -fsSI "$url/${id}_$newest.apk" > /dev/null - echo "live at $url: newest $id $newest" -fi - -ln -sfn "$(basename "$install")" "$tools/current.new" -mv -T -f "$tools/current.new" "$tools/current" -for old in "$tools"/fdroidserver-*; do - [ "$old" = "$install" ] || rm -rf "$old" -done diff --git a/.gitea/scripts/packages.sh b/.gitea/scripts/packages.sh deleted file mode 100755 index 17c10a9..0000000 --- a/.gitea/scripts/packages.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/bin/sh -set -eu -version=${1:-} -root=${PACKAGES_ROOT:-/var/www/packages.arasaka.software} -keep=${PACKAGES_KEEP:-5} -url=https://packages.arasaka.software -fingerprint=F92C166E9B1C13EDD1629E76888DCF969D133FB2 -if [ -n "$version" ]; then - releases=$(pwd)/releases/$version - deb=$releases/MeWeb-$version-linux-x64.deb - rpm=$releases/MeWeb-$version-linux-x64.rpm - test -f "$deb" - test -f "$rpm" -elif [ ! -e "$root/apt" ] || [ ! -e "$root/rpm" ]; then - echo "no repositories at $root yet: the first release makes them" - exit 0 -fi -tools=$(dpkg-query -W -f '${Package} ${Version}\n' apt-utils createrepo-c dpkg gnupg rpm) -named=$(echo "$tools" | paste -sd, - | sed 's/,/, /g') -stamp=$( { echo "$tools"; cat "$0"; } | sha256sum | cut -d' ' -f1) - -exec 9>>"$root/.lock" -flock -w 2700 9 -if [ -z "$version" ] && [ "$(cat "$(readlink -f "$root/apt")/../built-from" 2>/dev/null)" = "$stamp" ]; then - echo "nothing new: the repositories are already built with $named" - exit 0 -fi -echo "$named" - -keys=$(mktemp -d) -trap 'rm -rf "$keys"' EXIT -export GNUPGHOME="$keys" -printf '%s\n' "$PACKAGES_SIGNING_KEY" | gpg --batch --quiet --import -gpg --batch --with-colons --list-secret-keys | grep -q "^fpr:::::::::$fingerprint:$" -gpg --batch --armor --export "$fingerprint" > "$keys/public.asc" - -if [ -n "$version" ]; then - rpmsign --define "__gpg /usr/bin/gpg" --define "_gpg_name $fingerprint" --define "_gpg_path $keys" --addsign "$rpm" >/dev/null - rpmkeys --dbpath "$keys/rpmdb" --import "$keys/public.asc" - rpmkeys --dbpath "$keys/rpmdb" -K "$rpm" | grep -q 'digests signatures OK' - - full=$(dpkg-deb -f "$deb" Version) - test "$(dpkg-deb -f "$deb" Package)" = meweb - test "${full%-*}" = "$version" - debname=meweb_${full}_$(dpkg-deb -f "$deb" Architecture).deb - rpmname=$(rpm -qp --nosignature --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' "$rpm") - test "$(rpm -qp --nosignature --qf '%{NAME} %{VERSION}' "$rpm")" = "meweb $version" -fi - -snap=$root/.snap/$(date -u +%Y%m%d%H%M%S)-${version:-tools} -mkdir -p "$snap/apt/pool/main" "$snap/rpm" -if [ -d "$root/apt/pool/main" ]; then cp -al "$root/apt/pool/main/." "$snap/apt/pool/main/"; fi -if [ -d "$root/rpm" ]; then - for folder in "$root"/rpm/*/; do - [ "$(basename "$folder")" = repodata ] || cp -al "$folder" "$snap/rpm/" - done -fi -mkdir -p "$snap/apt/pool/main/m/meweb" "$snap/rpm/meweb" -if [ -n "$version" ]; then - rm -f "$snap/apt/pool/main/m/meweb/$debname" "$snap/rpm/meweb/$rpmname" - cp "$deb" "$snap/apt/pool/main/m/meweb/$debname" - cp "$rpm" "$snap/rpm/meweb/$rpmname" -fi -for folder in "$snap/apt/pool/main/m/meweb" "$snap/rpm/meweb"; do - ls "$folder" | sed -E 's/^meweb[_-]([0-9.]+)-.*/\1/' | sort -uV | head -n "-$keep" | while read -r old; do - rm -f "$folder/meweb_$old-"* "$folder/meweb-$old-"* - done -done -if [ -z "$version" ]; then - debname=$(ls "$snap/apt/pool/main/m/meweb" | sort -V | tail -n 1) - rpmname=$(ls "$snap/rpm/meweb" | sort -V | tail -n 1) - full=$(dpkg-deb -f "$snap/apt/pool/main/m/meweb/$debname" Version) -fi - -binary=$snap/apt/dists/stable/main/binary-amd64 -mkdir -p "$binary" -(cd "$snap/apt" && apt-ftparchive packages pool) > "$binary/Packages" -gzip -9nc "$binary/Packages" > "$binary/Packages.gz" -(cd "$snap/apt/dists/stable" && apt-ftparchive \ - -o APT::FTPArchive::Release::Origin=Arasaka -o APT::FTPArchive::Release::Label=Arasaka \ - -o APT::FTPArchive::Release::Suite=stable -o APT::FTPArchive::Release::Codename=stable \ - -o APT::FTPArchive::Release::Architectures=amd64 -o APT::FTPArchive::Release::Components=main \ - -o APT::FTPArchive::Release::NotAutomatic=yes -o APT::FTPArchive::Release::ButAutomaticUpgrades=yes \ - -o "APT::FTPArchive::Release::Description=Arasaka packages" release .) > "$keys/Release" -mv "$keys/Release" "$snap/apt/dists/stable/Release" -gpg --batch --yes --local-user "$fingerprint" --clearsign -o "$snap/apt/dists/stable/InRelease" "$snap/apt/dists/stable/Release" -gpg --batch --yes --local-user "$fingerprint" --armor --detach-sign -o "$snap/apt/dists/stable/Release.gpg" "$snap/apt/dists/stable/Release" - -createrepo_c --quiet "$snap/rpm" -repodata=$snap/rpm/repodata -gpg --batch --yes --local-user "$fingerprint" --armor --detach-sign -o "$repodata/repomd.xml.asc" "$repodata/repomd.xml" -cp "$keys/public.asc" "$repodata/repomd.xml.key" -if [ -f "$root/rpm/repodata/repomd.xml" ]; then - grep -o 'repodata/[^"]*' "$root/rpm/repodata/repomd.xml" | while read -r href; do - [ -e "$snap/rpm/$href" ] || cp "$root/rpm/$href" "$snap/rpm/$href" - done -fi -chmod -R u=rwX,go=rX "$snap" -echo "$stamp" > "$snap/built-from" - -for part in apt rpm; do - ln -sfn ".snap/$(basename "$snap")/$part" "$root/$part.new" - mv -T -f "$root/$part.new" "$root/$part" -done -ls -1d "$root"/.snap/* | sort | head -n -3 | while read -r old; do - find "$old" -maxdepth 0 -mmin +1440 -exec rm -rf {} + -done -echo "published $root/apt and $root/rpm, newest $debname and $rpmname" - -if [ -n "$version" ]; then - (cd "$releases" && for file in $(ls | LC_ALL=C sort); do [ "$file" = SHA256SUMS.txt ] || sha256sum "$file"; done) > "$keys/sums" - mv "$keys/sums" "$releases/SHA256SUMS.txt" -fi - -if [ "$root" = /var/www/packages.arasaka.software ]; then - curl -fsS "$url/apt/dists/stable/main/binary-amd64/Packages" | grep -qx "Version: $full" - curl -fsS "$url/apt/dists/stable/InRelease" > "$keys/InRelease" - gpg --batch --quiet --verify "$keys/InRelease" - curl -fsS "$url/rpm/repodata/repomd.xml" > "$keys/repomd.xml" - curl -fsS "$url/rpm/repodata/repomd.xml.asc" > "$keys/repomd.xml.asc" - gpg --batch --quiet --verify "$keys/repomd.xml.asc" "$keys/repomd.xml" - curl -fsSI "$url/rpm/meweb/$rpmname" > /dev/null - echo "live at $url: meweb $full" -fi diff --git a/.gitea/scripts/prepare.sh b/.gitea/scripts/prepare.sh index c0abafd..138ca93 100755 --- a/.gitea/scripts/prepare.sh +++ b/.gitea/scripts/prepare.sh @@ -8,7 +8,7 @@ fi echo "VERSION=$version" >> "$GITHUB_ENV" echo "COMMIT=$(echo "$GITHUB_SHA" | cut -c1-8)" >> "$GITHUB_ENV" keep="$HOME/.cache/meweb" -for dir in tools/cache tools/jdk tools/packaging tools/android-sdk tools/fdroid; do +for dir in tools/cache tools/jdk tools/packaging tools/android-sdk; do mkdir -p "$keep/$dir" rm -rf "$dir" ln -s "$keep/$dir" "$dir" diff --git a/.gitea/scripts/sign-rpm.sh b/.gitea/scripts/sign-rpm.sh new file mode 100755 index 0000000..b0c009e --- /dev/null +++ b/.gitea/scripts/sign-rpm.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -eu +version=$1 +releases=$(pwd)/releases/$version +rpm=$releases/MeWeb-$version-linux-x64.rpm +fingerprint=F92C166E9B1C13EDD1629E76888DCF969D133FB2 +test -f "$rpm" +keys=$(mktemp -d) +trap 'rm -rf "$keys"' EXIT +export GNUPGHOME="$keys" +printf '%s\n' "$PACKAGES_SIGNING_KEY" | gpg --batch --quiet --import +gpg --batch --with-colons --list-secret-keys | grep -q "^fpr:::::::::$fingerprint:$" +gpg --batch --armor --export "$fingerprint" > "$keys/public.asc" +rpmsign --define "__gpg /usr/bin/gpg" --define "_gpg_name $fingerprint" --define "_gpg_path $keys" --addsign "$rpm" > /dev/null +rpmkeys --dbpath "$keys/rpmdb" --import "$keys/public.asc" +rpmkeys --dbpath "$keys/rpmdb" -K "$rpm" | grep -q 'digests signatures OK' +(cd "$releases" && for file in $(ls | LC_ALL=C sort); do [ "$file" = SHA256SUMS.txt ] || sha256sum "$file"; done) > "$keys/sums" +mv "$keys/sums" "$releases/SHA256SUMS.txt" +echo "signed $(basename "$rpm") with $fingerprint" diff --git a/.gitea/workflows/fdroid.yml b/.gitea/workflows/fdroid.yml deleted file mode 100644 index 957dd17..0000000 --- a/.gitea/workflows/fdroid.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: F-Droid tools - -on: - schedule: - - cron: '23 5 * * *' - workflow_dispatch: - -jobs: - refresh: - name: The newest F-Droid tools, tried on the repository - runs-on: nuvola - steps: - - uses: actions/checkout@v4 - - - name: Prepare - run: .gitea/scripts/prepare.sh - - - name: Rebuild the repository on packages.arasaka.software when the tools or the listing changed - env: - MEWEB_KEYSTORE_B64: ${{ secrets.MEWEB_KEYSTORE_B64 }} - MEWEB_KEYSTORE_PASS: ${{ secrets.MEWEB_KEYSTORE_PASS }} - run: .gitea/scripts/fdroid.sh diff --git a/.gitea/workflows/packages.yml b/.gitea/workflows/packages.yml deleted file mode 100644 index 6a00ece..0000000 --- a/.gitea/workflows/packages.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Package tools - -on: - schedule: - - cron: '43 5 * * *' - workflow_dispatch: - -jobs: - refresh: - name: The box's updated package tools, tried on the apt and rpm repositories - runs-on: nuvola - steps: - - uses: actions/checkout@v4 - - - name: Check that the box brought the tools up to date this morning - run: | - systemctl show packages-tools -p Result -p ExecMainExitTimestamp - systemctl is-active --quiet packages-tools.timer - test "$(systemctl show packages-tools -p Result --value)" = success - - - name: Rebuild the apt and rpm repositories on packages.arasaka.software when the tools changed - env: - PACKAGES_SIGNING_KEY: ${{ secrets.PACKAGES_SIGNING_KEY }} - run: .gitea/scripts/packages.sh diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 91a6119..b93acd0 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -43,21 +43,14 @@ jobs: MEWEB_KEYSTORE_PASS: ${{ secrets.MEWEB_KEYSTORE_PASS }} run: .gitea/scripts/android.sh - - name: The deb and rpm on packages.arasaka.software, the rpm signed + - name: The rpm signed with the Arasaka packages key if: ${{ github.ref_type == 'tag' }} env: PACKAGES_SIGNING_KEY: ${{ secrets.PACKAGES_SIGNING_KEY }} - run: .gitea/scripts/packages.sh "$VERSION" + run: .gitea/scripts/sign-rpm.sh "$VERSION" - name: Publish the release if: ${{ github.ref_type == 'tag' || inputs.publish == 'true' }} env: RELEASE_TOKEN: ${{ secrets.GITEA_TOKEN }} run: .gitea/scripts/release.sh "v$VERSION" releases/"$VERSION"/* - - - name: The APK in the F-Droid repository on packages.arasaka.software - if: ${{ github.ref_type == 'tag' }} - env: - MEWEB_KEYSTORE_B64: ${{ secrets.MEWEB_KEYSTORE_B64 }} - MEWEB_KEYSTORE_PASS: ${{ secrets.MEWEB_KEYSTORE_PASS }} - run: .gitea/scripts/fdroid.sh "$VERSION" diff --git a/.gitignore b/.gitignore index cb3af86..4ef3d9c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ appsettings.*.local.json /tools/packaging/ /tools/android-sdk/ /tools/cache/ -/tools/fdroid/ /tools/logs/ /.claude/settings.local.json /artifacts/ diff --git a/CLAUDE.md b/CLAUDE.md index d3671ba..09ffe2a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -44,9 +44,8 @@ is root-owned, so CI uses the runner user's own `~/.dotnet` (passolo's `tools/re | `MEWEB_KEYSTORE` | release step | a temporary file in `$RUNNER_TEMP` decoded by `.gitea/scripts/android.sh`, removed on exit | `build.yml` runs on every push to `master`; `release.yml` on a `v*` tag (publishes the Gitea release) or by hand -(`publish: false` builds every platform and deploys the server only); `fdroid.yml` daily at 05:23 UTC or by hand -(the F-Droid tools, below); `packages.yml` daily at 05:43 UTC or by hand (the deb and rpm tools, below). All four -run on the Arasaka org runner `nuvola`, +(`publish: false` builds every platform and deploys the server only). Both run on `nuvola`, the instance-wide runner +on the box (since 1 Nov 2026 it also takes the jobs labelled `build`), user `gitea-runner`, home `/var/lib/gitea-runner`: `tools/sdk.sh` installs the SDK from `global.json` into its `~/.dotnet` (the system SDK in `/opt/dotnet` is older and root-owned), and the JDK, nfpm and the Android SDK are cached in `~/.cache/meweb`. There is deliberately no `pull_request` trigger: the runner is the production box. @@ -161,58 +160,26 @@ The Android release key: alias `meweb`, certificate SHA-256 the network and the block without the publisher's server. A change to any knowledge file's format bumps `KnowledgeFeeder.Format` and the `"format":N` that `wait-knowledge.sh` waits for: the feeder rebuilds only when a source changes or the format differs, and a release must not embed the previous build. -- **The deb and rpm reach packages.arasaka.software from this repository's own release job.** On tags, - `.gitea/scripts/packages.sh` runs on the `nuvola` runner (host mode, user `gitea-runner`, which owns - `/var/www/packages.arasaka.software`). It imports the org secret `PACKAGES_SIGNING_KEY` into a throwaway - `GNUPGHOME`, refuses any key but `F92C166E…3FB2`, signs the rpm in place, hard-links the current pool into a new - `.snap/` folder, adds this version, keeps the newest five, rebuilds and signs the apt (`InRelease`, `Release.gpg`) - and rpm (`repomd.xml.asc`) metadata, carries over the files the previous `repomd.xml` named so a client mid-refresh - still finds them, swaps the `apt` and `rpm` links, rewrites `SHA256SUMS.txt` for the signed rpm, and checks the live - site. Never copy a package over a pool file: the pools are hard links into older snapshots, so it is `rm` then `cp`. - `PACKAGES_ROOT` and `PACKAGES_KEEP` exist for a test against a copy. YoloCICD, which used to do this, was erased on - 23 Oct 2026. `packaging/arasaka-repository.sh` is written into both maintainer scripts by `tools/release.cs`; it is - now maintained here by hand, and any change to a file it writes needs the old content's SHA-256 kept in - `arasaka_repository_known`, or installed copies are treated as edited by hand and left alone. The package owns - `/usr/share/arasaka-repository/meweb`, the marker that keeps the repository configured while any Arasaka package - is installed. The signing key's only copies are that secret and the owner's Nextcloud backup. - **The tools that build these two repositories are the box's own Ubuntu packages** (`apt-utils` for - `apt-ftparchive`, `createrepo-c`, `dpkg`, `gnupg`, `rpm`), and **a daily job keeps them current** (owner, 31 Oct - 2026: the same daily update as the F-Droid tools). The runner cannot install packages, so the update is a root - timer on the box, `packages-tools.timer` at 05:13 UTC (source and setup in arasaka.software, - `deploy/packages.arasaka.software/`). It upgrades only those packages, from Ubuntu's updates and security - fixes, with package lists of its own, so it never brings the rest of the box forward. There is no two-week wait, - as there is for fdroidserver: Ubuntu reviews and signs these updates itself. `packages.yml` follows at 05:43 UTC. It fails if - the morning's update failed (it reads the result with `systemctl show`, which needs no rights), then runs this - script with no version. When the tools' versions or this script differ from what the live repositories were built - from (`built-from` beside each snapshot), it rebuilds and re-signs both from the current pools with no new package, - swaps the links and checks the live site; otherwise it says "nothing new" and names the versions. Unlike - fdroidserver, these tools cannot be kept beside an older copy, so a release uses whatever is installed; an update - that breaks them fails the next morning's job first. -- **The APK reaches an F-Droid repository on packages.arasaka.software from the same job** (31 Oct 2026), after the - release is published, so the repository can lag the release page but never lead it. `.gitea/scripts/fdroid.sh` - installs fdroidserver with uv from `setup.json` (its download cache in `tools/fdroid`, cached like the JDK), because - the box has no `ensurepip` and the apt package would bring 242 others. **Nothing pins fdroidserver; a daily job - keeps it current** (owner, 31 Oct 2026: a daily service, not patching it from time to time). `fdroid.yml` runs the - same script with no version at 05:23 UTC: it resolves the newest fdroidserver, and the newest of everything it - needs, published at least 14 days earlier (a bad upload has usually been pulled by then), against the box's own - `python3`, into a hash-locked list; a new list gets its own install, `fdroidserver-` in the cache's - real path (an install's scripts carry the absolute path they were made at; 0.15.1 failed with `fdroid: not found` on - one made from a deleted folder). When that list or the listing in `packaging/fdroid/` differs from what the live - repository was built from (`built-from` beside each snapshot), it rebuilds the repository with it, and only once - that is live and verified does the install become `current` and the older ones go. A release uses `current` and - downloads nothing, so a new fdroidserver that breaks fails the daily job, never a release; the job's log names the - version. Every install runs with the signing key out of its environment. - It signs the repository with the APK's own key (`MEWEB_KEYSTORE_B64` and `MEWEB_KEYSTORE_PASS`, alias `meweb`), so - the F-Droid fingerprint is the certificate's `5F52CFF4…FDF846` and there is no second key to lose; it refuses any - other. It builds a new snapshot in - `/var/www/packages.arasaka.software/.fdroid/` from the live one (the APKs as hard links, so `rm` then `cp` as above; - the metadata, the icons, `apkcache.json` and the previous `index-v2.json`, which is where fdroidserver reads each - APK's first date; without the icons a rebuild with no new APK fails, because the cache skips extracting them), adds - this version (a release) or nothing (the daily job), keeps the newest three, runs `fdroid update`, deletes `repo/status/` (it names the - build machine's paths and `/etc/issue.net`), swaps the `fdroid/repo` link and checks the live signature. The key - was already never to be regenerated; now everyone who added the repository trusts only its fingerprint too. `packaging/fdroid/` holds the - repository's settings, its icon (the Arasaka emblem) and the app's listing in English and Italian; the download - page links to it and to Obtainium (`Endpoints.FDroid`, source `FDroidRepo`). +- **packages.arasaka.software is fed from outside this repository** (since 1 Nov 2026). The private repository + `thepra/packages.arasaka.software` lists this app in `apps/meweb.yml`, reads every `v*` release from the Releases + tab every 15 minutes, and publishes the newest five debs and rpms, the newest three APKs in the F-Droid repository + and the newest Windows and macOS files under `/download/meweb/`, all signed with keys that live as `thepra`'s own + secrets. Its README is the reference. What this repository still owes it: + - **The release must carry every file named in that entry and list each in `SHA256SUMS.txt`**, or the publisher + leaves the version out and keeps serving the previous one. Renaming a release file means changing `apps/meweb.yml` + in the same hour. + - **The rpm is signed here, before the release is published**, by `.gitea/scripts/sign-rpm.sh` with the Arasaka org + secret `PACKAGES_SIGNING_KEY` (it refuses any key but `F92C166E…3FB2`), which then rewrites `SHA256SUMS.txt`, so + the README's promise holds for the file on the release page too; the publisher sees the signature and keeps it. + - **The F-Droid listing stays in `packaging/fdroid/metadata/`** (English and Italian); the publisher reads it at the + release's tag. The repository's own settings and icon moved there. + - **The APK's signing key also signs the F-Droid index**, so `MEWEB_KEYSTORE_B64` exists twice: here, to sign the + APK, and as `thepra`'s `FDROID_KEYSTORE_B64`. The publisher refuses an APK signed by anything but `5f52cff4…f846`. + - `packaging/arasaka-repository.sh` is written into both maintainer scripts by `tools/release.cs`; it is + maintained here by hand, and any change to a file it writes needs the old content's SHA-256 kept in + `arasaka_repository_known`, or installed copies are treated as edited by hand and left alone. The package owns + `/usr/share/arasaka-repository/meweb`, the marker that keeps the repository configured while any Arasaka package + is installed. The portal app (`arasaka.software`, `arasaka-portal`) carries a byte-identical copy; change both. - **The server cannot ping**: `NoNewPrivileges` drops `ping`'s file capability and `ping_group_range` is closed, so the trace back to a caller uses `tracepath` (UDP, unprivileged) and keeps only public hops outside `Probe:Refuse`, so the box's own network never reaches an app. diff --git a/packaging/fdroid/config.yml b/packaging/fdroid/config.yml deleted file mode 100644 index b34e364..0000000 --- a/packaging/fdroid/config.yml +++ /dev/null @@ -1,11 +0,0 @@ -repo_url: https://packages.arasaka.software/fdroid/repo -repo_name: Arasaka -repo_description: >- - Apps published by Arasaka di Hvozdikov Yevheniy, Busto Arsizio, Italy, such as “me-web?”. - Each app here is the same signed file as on its release page. -repo_icon: icon.png -archive_older: 0 -repo_keyalias: meweb -keystore: {env: MEWEB_KEYSTORE} -keystorepass: {env: MEWEB_KEYSTORE_PASS} -keypass: {env: MEWEB_KEYSTORE_PASS} diff --git a/packaging/fdroid/icon.png b/packaging/fdroid/icon.png deleted file mode 100644 index f8e333e..0000000 Binary files a/packaging/fdroid/icon.png and /dev/null differ diff --git a/tools/setup.json b/tools/setup.json index fddc5e6..f07a348 100644 --- a/tools/setup.json +++ b/tools/setup.json @@ -47,18 +47,6 @@ "kind": "tar", "dest": "tools/jdk/osx-arm64", "check": "tools/jdk/osx-arm64/jdk-21.0.12+8/Contents/Home/bin/java" - }, - { - "name": "uv", - "group": "fdroid", - "version": "0.13.1", - "license": "MIT or Apache-2.0 (build tool, not distributed)", - "rid": "linux-x64", - "url": "https://github.com/astral-sh/uv/releases/download/0.13.1/uv-x86_64-unknown-linux-gnu.tar.gz", - "sha256": "eadd9d27c134ab5ac1ffd4473b97a741407f3ea238288f03121fc4deddf90220", - "kind": "tar", - "dest": "tools/fdroid/linux-x64", - "check": "tools/fdroid/linux-x64/uv-x86_64-unknown-linux-gnu/uv" } ] }