Files
LiHaohuaandClaude Opus 4.7 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

90 lines
3.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
- [`AdityaGarg8/t2-ubuntu-repo`](https://github.com/AdityaGarg8/t2-ubuntu-repo)
— flat gh-pages layout, `apt-ftparchive` + GPG sign in Actions, no LFS.
- [`ryanfortner/box64-debs`](https://github.com/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.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"](https://securitylab.github.com/resources/github-actions-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.