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>
3.4 KiB
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 100–500 .deb files at 1–20 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+InReleasetext files. These are small (KB per package). Pages' soft bandwidth limit is 100 GB/month, comfortable forapt updatetraffic. - Releases host the
.debbinaries as assets. Asset size limit is 2 GB, no documented hard quota on total asset storage, and release bandwidth is tracked separately from LFS. Packagesindices point tohttps://github.com/OWNER/REPO/releases/download/<tag>/<file>.deb, soaptdownloads the binary directly from Releases.
Prior art
AdityaGarg8/t2-ubuntu-repo— flat gh-pages layout,apt-ftparchive+ GPG sign in Actions, no LFS.ryanfortner/box64-debs— 4 years of daily CI commits, nightly arm64 builds, no LFS, repo stays under 100 MB.
Both use apt-ftparchive + dpkg-scanpackages + crazy-max/ghaction-import-gpg.
Workflow separation (security-critical)
validate-submission.ymlruns onpull_request. No secrets available,GITHUB_TOKENis read-only. Can build, test, inspect. Cannot sign or push.publish.ymlruns onpushtomain(i.e. after merge). Has access tosecrets.GPG_PRIVATE_KEY, can push togh-pagesbranch, 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:
Packagestext: ~1 KB per app × 300 = 300 KBPackages.gz: compressed, ~100 KB totalRelease/InRelease: small, ~5 KBKEY.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:
- Multi-repo split — one repo per component (apps / SDKs / firmware).
- Cloudflare R2 — egress is free; mirror
.debassets there while keeping this repo as the source of truth. - deb-s3 — full migration to S3-backed hosting; minimal client impact
since the
sources.listURL changes but signing/layout do not.