Files
LiHaohua 774d9a86fa Bootstrap apt repository structure
This is the initial shape of the CardputerZero deb repository. The design
follows the GitHub Pages (metadata) + Releases (deb assets) pattern that
sibling projects like ryanfortner/box64-debs and AdityaGarg8/t2-ubuntu-repo
use successfully — it deliberately avoids Git LFS because the free plan's
1 GB/1 GB storage+bandwidth limits apply to public repos too.

Files landing here:

- README.md / docs/ARCHITECTURE.md / docs/MAINTAINERS.md explain the flow
  for users, the design tradeoffs, and the maintainer runbook (including
  GPG key setup).
- .github/workflows/validate-submission.yml runs on pull_request with a
  read-only token and no secrets, verifying any incoming/*.deb is a valid
  arm64 package. Safe to run on external contributor PRs.
- .github/workflows/publish.yml runs on push to main (after merge). It
  uploads incoming/*.deb to a rolling "apt-pool" GitHub Release, rebuilds
  Packages/Release/InRelease with apt-ftparchive, GPG-signs if
  GPG_PRIVATE_KEY is set (warns loudly otherwise), and publishes the
  metadata tree to gh-pages.
- incoming/czrepo-hello_0.1-1_arm64.deb is a 784-byte sentinel package
  used to exercise the publish pipeline end-to-end on this very first
  PR merge.

The workflow is intentionally safe-by-default: without a GPG key
configured it will still produce a usable (unsigned) apt index so the
plumbing can be validated before trusted signing keys are generated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:56:07 +08:00

3.4 KiB
Raw Permalink Blame History

CardputerZeroRepository architecture

Design notes and tradeoffs for hosting a Debian .deb repository on a single public GitHub repo.

Why this shape

Not LFS

GitHub Large File Storage on the free plan is:

Free plan
Single file 2 GB
Total storage 1 GB
Bandwidth / month 1 GB
Public repo exempt from bandwidth? No

For an apt repo with 100500 .deb files at 120 MB each and <10k downloads per month, LFS storage would be exhausted before any download traffic, and the first few dozen apt install calls would exceed the monthly bandwidth quota. Data packs cost $5/month per 50 GB.

GitHub Pages + Releases

  • Pages serves the dists/.../Packages* + Release + InRelease text files. These are small (KB per package). Pages' soft bandwidth limit is 100 GB/month, comfortable for apt update traffic.
  • Releases host the .deb binaries as assets. Asset size limit is 2 GB, no documented hard quota on total asset storage, and release bandwidth is tracked separately from LFS.
  • Packages indices point to https://github.com/OWNER/REPO/releases/download/<tag>/<file>.deb, so apt downloads the binary directly from Releases.

Prior art

Both use apt-ftparchive + dpkg-scanpackages + crazy-max/ghaction-import-gpg.

Workflow separation (security-critical)

  • validate-submission.yml runs on pull_request. No secrets available, GITHUB_TOKEN is read-only. Can build, test, inspect. Cannot sign or push.
  • publish.yml runs on push to main (i.e. after merge). Has access to secrets.GPG_PRIVATE_KEY, can push to gh-pages branch, can move debs to Releases.

Never use pull_request_target with checkout of the PR head. That combination grants secrets to arbitrary PR code — multiple public projects have been pwned this way (see GitHub Security Lab: "Preventing pwn requests").

Repository size budget

Assuming 300 apps, weekly updates, metadata only in git:

  • Packages text: ~1 KB per app × 300 = 300 KB
  • Packages.gz: compressed, ~100 KB total
  • Release / InRelease: small, ~5 KB
  • KEY.gpg: 3 KB
  • CI logs accumulate in Actions (not in repo)

Repository should stay well under 100 MB across years of history; deb assets live in Releases and don't count toward repo size.

Public-repo Actions economics

  • Free unlimited minutes for public repos (official).
  • Concurrency: ~20 concurrent jobs free tier.
  • Job timeout: 6 hours.
  • Workflow timeout: 35 days.

A single PR validation completes in <2 minutes; a full re-sign on merge in <3 minutes. Room to grow.

Upgrade path

If this repo hits growth that strains GitHub:

  1. Multi-repo split — one repo per component (apps / SDKs / firmware).
  2. Cloudflare R2 — egress is free; mirror .deb assets there while keeping this repo as the source of truth.
  3. deb-s3 — full migration to S3-backed hosting; minimal client impact since the sources.list URL changes but signing/layout do not.