Files
Fenris/docs/research/gitea-package-registry.md
xavierk b005049733 docs: release & packaging spec + ADR 0007 amending 0004 (map #33, task #42)
- docs/spec/release-packaging.md: decision-complete spec — compat matrix,
  Gitea 1.27.1 registry channel, nfpm toolchain, signing/key policy,
  release mechanics, package layout/ownership, maintainer-script
  contracts, initial config, make-install migration runbook.
- docs/adr/0007: package delivery amends ADR 0004 (delivery/ownership
  only; runtime semantics inherited verbatim). 0004 status updated.
- docs/research/: toolchain, gitea-registry, obs findings merged from
  research branches (assets of map tickets #34/#35/#36).
- CONTEXT.md: Release + Rollback glossary terms (ticket #43).
2026-09-03 01:44:37 +05:30

8.3 KiB
Raw Permalink Blame History

Research: Gitea 1.27 Debian + RPM package registry feasibility

Issue: Fenris deb + rpm release plan → Research: Gitea 1.27 Debian + RPM package registry feasibility Verified 2026-09-03 against live instance https://git.bongbetic.com (reports 1.27.1 via /api/v1/version) and primary sources: docs.gitea.com 1.27 Debian/RPM registry pages and Gitea v1.27.1 source (go-gitea/gitea tag).

Verdict: feasible. Every publish/consume path tested live with throwaway packages fenris-regtest (all deleted afterward; package list verified empty).

1. Publish paths (verified live, HTTP 201)

Debian (.deb)

curl --user xavierk:$TOKEN --upload-file fenris_0.3.0_amd64.deb \
  "https://git.bongbetic.com/api/packages/xavierk/debian/pool/{distribution}/{component}/upload"
  • distribution and component are free-form path segments chosen at upload time (e.g. bookworm/main, noble/main). Gitea derives apt suites from what was uploaded — verified: same .deb published to pool/bookworm/main and pool/noble/main (both 201), both then served in dists/bookworm/ and dists/noble/ with correct Suite:/Codename: headers.
  • Republish of identical name+version+distribution+component+architecture → 409 Conflict (verified). Must delete first.

RPM (.rpm)

# no group (flat repo)
curl --user xavierk:$TOKEN --upload-file fenris-0.3.0-1.el9.x86_64.rpm \
  "https://git.bongbetic.com/api/packages/xavierk/rpm/upload"
# with group (distro tag, nestable)
curl --user xavierk:$TOKEN --upload-file fenris-0.3.0-1.fc40.x86_64.rpm \
  "https://git.bongbetic.com/api/packages/xavierk/rpm/el9/upload"   # e.g. el9, rocky/el9, fc40
  • Group = free-form nesting used to partition repos per distro/track. Verified: publish to root group and el9 group (both 201), duplicate → 409.
  • Owner can be the user (xavierk) or an org; packages under a public owner are readable anonymously (verified: metadata fetches without auth succeeded).

2. Consumer setup (exact commands)

apt clients

sudo mkdir -p /etc/apt/keyrings
sudo curl -o /etc/apt/keyrings/gitea-xavierk.asc \
  https://git.bongbetic.com/api/packages/xavierk/debian/repository.key
echo "deb [signed-by=/etc/apt/keyrings/gitea-xavierk.asc] https://git.bongbetic.com/api/packages/xavierk/debian bookworm main" \
  | sudo tee /etc/apt/sources.list.d/gitea.list   # one line per distribution
sudo apt update
apt install fenris            # or fenris=0.3.0
# private owner variant: https://{user}:{token}@git.bongbetic.com/api/packages/... in the URL

dnf clients

sudo dnf config-manager --add-repo https://git.bongbetic.com/api/packages/xavierk/rpm/el9.repo
# private owner: add user:token into the baseurl inside /etc/yum.repos.d/gitea-xavierk-el9.repo afterwards
sudo dnf install fenris       # or fenris-0.3.0

The served .repo (verified live) sets gpgcheck=1 and points gpgkey at …/rpm/repository.key, so dnf auto-imports on first use.

3. Metadata signing: native, not passthrough

Gitea signs generated metadata itself with per-instance auto-generated PGP keys. Client-side signing config is limited to trusting the served keys.

  • Debian: dists/{suite}/InRelease is clearsigned; Release.gpg detached sig also served. Key (RSA) fetched from …/debian/repository.key, uid literally (Automatically generated Debian Registry Key; created …).
  • RPM: repodata/repomd.xml.asc detached ASCII-armored signature, uid (RPM Registry). Key from …/rpm/repository.key.
  • Both verified with gpg --verify → Good signature (keys are self-generated; the "not certified" warning is expected and handled by the signed-by/keyring flow above).
  • The apt Release also advertises Acquire-By-Hash: yes with MD5/SHA1/SHA256/SHA512 indexes of Packages/.gz/.xz (verified live). RPM repomd carries sha256 checksums for primary/filelists/other.xml.gz.

There is no bring-your-own-signing-key config for these registries in 1.27 — trust anchor is the instance's auto keys. For Fenris this is acceptable; TOFU over TLS via the key URLs above.

4. Multi-distro metadata

  • Debian: distributions/suites are implicit — whatever {distribution} path segments appear on upload become dists/{distribution}/ trees with Suite:/Codename: set to the segment. No server-side list to maintain; adding a new distro = upload with new segment + one more deb … sources line. Components likewise (main, etc.). Architectures come from each .deb's control stanza (index served as dists/{dist}/{component}/binary-{arch}/Packages).
  • RPM: same via {group} path segments (el9, rocky/el9, …); each group gets its own repodata/. No basearch filtering — clients pick the group; Gitea publishes whatever RPM arch was uploaded.

5. Version retention

  • Default: all versions retained indefinitely; nothing auto-deletes. Old versions stay installable (apt install fenris=0.2.9, dnf install fenris-0.2.9).
  • Republishing an existing name+version (deb: same dist/component/arch; rpm: same file name in group) → 409; overwrite requires delete-then-upload.
  • Optional cleanup rules exist (per owner + package type): KeepCount, KeepPattern, RemoveDays, RemovePattern, MatchFullName (source: models/packages/package_cleanup_rule.go, executed by scheduled CleanupTask in services/packages/cleanup/cleanup.go). In 1.27.1 they are configurable only in the web UI (owner → Packages → Cleanup Rules); no v1 REST route (verified by route table grep of routers/api/v1/api.go — probes of /api/v1/packages/{owner}/cleanuprules… return 404/409-style errors).
  • Deletes: format-specific DELETE …/debian/pool/{dist}/{component}/{name}/{version}/{arch} and DELETE …/rpm/{group}/package/{name}/{version}/{arch} (both verified, 204). Deleting last file removes the version. Generic fallback: DELETE /api/v1/packages/{owner}/{type}/{name}/{version}.

6. Release attachment: not supported

Gitea 1.27.1 has no package↔release linkage. Release assets (…/releases/{id}/assets) are standalone file uploads; the package model has no release field and no route links them (verified against v1.27.1 source: routers/api/v1/repo/release_attachment.go, models/packages/). Options for Fenris releases:

  1. Publish .deb/.rpm to the registry (real apt/dnf install UX) and reference the registry URLs in release notes.
  2. Additionally upload tarballs/SHA256SUMS as plain release attachments.
  3. Generic registry (PUT /api/packages/{owner}/generic/{name}/{version}/{filename}) if an untyped artifact store is needed.

7. Caveats for the release plan

  • Owner choice matters: publish under an org (e.g. fenris) if multiple maintainers need write; xavierk user owner works today (token owner is admin).
  • Metadata access follows owner visibility — public owner → anonymous consumers, no token in URLs (current state, verified). Keep owner public for frictionless installs, or embed user:token in sources/baseurl.
  • apt distro naming should match OS release names (bookworm, trixie, noble) purely for client convention; server accepts anything.
  • RPM groups should mirror $distver (e.g. el9, fc40) so .repo selection is obvious per target.

8. Test log (live, 2026-09-03)

Step Result
PUT debian/pool/bookworm/main/upload 201
PUT debian/pool/noble/main/upload (multi-dist) 201
PUT debian duplicate 409 (expected)
PUT rpm/upload (no group) 201
PUT rpm/el9/upload (group) 201
PUT rpm duplicate 409 (expected)
GET debian/repository.key / rpm/repository.key PGP public keys (200)
GET dists/bookworm/{Release,InRelease,Packages} correct; gpg --verify Good signature
GET rpm{,/el9}/repodata/repomd.xml{,.asc} 200; Good signature
GET rpm{,/el9}.repo generated repo files with gpgcheck=1
Cleanup-rules REST probes 404 (not in v1 API — UI only)
DELETE all four test entries 204 ×4; package list then empty

Sources: docs.gitea.com 1.27 Debian registry, docs.gitea.com 1.27 RPM registry, Gitea source tag v1.27.1 (routers/api/v1/api.go, models/packages/package_cleanup_rule.go, services/packages/cleanup/cleanup.go), live instance git.bongbetic.com.