Skip to content

Stand up apt.wheels.dev / yum.wheels.dev native Linux repositories (Phase 2) #2605

@bpamiri

Description

@bpamiri

Background

Phase 1 of Linux distribution is shipped: release.yml builds .deb and .rpm packages on every release via nfpm and uploads them to GitHub Releases alongside the existing zip artifacts. Users can install with:

```bash
WHEELS_VERSION=$(curl -fsSL https://api.github.com/repos/wheels-dev/wheels/releases/latest \
| sed -nE 's/.*"tag_name": "v([^\"]+)"./\1/p')
curl -fsSLO "https://github.com/wheels-dev/wheels/releases/download/v\${WHEELS_VERSION}/wheels_\${WHEELS_VERSION}_amd64.deb\"
sudo apt install "./wheels_${WHEELS_VERSION}_amd64.deb"
```

Phase 1 docs land in #2604.

Phase 2 stands up native apt/yum repositories so users can run `sudo apt install wheels` once and `apt update && apt upgrade wheels` thereafter — no manual re-download per release. End-user UX:

```bash

Debian / Ubuntu

curl -fsSL https://apt.wheels.dev/wheels.gpg \
| sudo tee /usr/share/keyrings/wheels.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/wheels.gpg] https://apt.wheels.dev stable main" \
| sudo tee /etc/apt/sources.list.d/wheels.list
sudo apt update && sudo apt install wheels

Fedora / RHEL

sudo dnf config-manager --add-repo https://yum.wheels.dev/wheels.repo
sudo dnf install wheels
```

Implementation plan

Fully sketched in tools/distribution-drafts/linux-packages/README.md § Phase 2. High-level:

  • Mint a GPG signing key for the Wheels project. Private half goes in 1Password under the existing `Infrastructure` vault. Public half ships as `tools/distribution-drafts/linux-packages/wheels-public.gpg` and is published at `apt.wheels.dev/wheels.gpg`.
  • Create `wheels-dev/apt-wheels-dev` repo — Cloudflare Pages site at `apt.wheels.dev`. Holds the static apt metadata tree (`Packages.gz`, `Release`, `Release.gpg`, `pool/*.deb`).
  • Create `wheels-dev/yum-wheels-dev` repo — Cloudflare Pages site at `yum.wheels.dev`. Holds the static yum metadata (`repodata/repomd.xml`, `pool/*.rpm`).
  • Author the metadata-generator workflow in each bucket repo. Listens for `repository_dispatch` from `wheels-dev/wheels`'s release workflow, downloads the new `.deb`/`.rpm` from the GitHub Release, regenerates the metadata (`apt-ftparchive` / `createrepo_c`), signs with GPG, commits, CF Pages auto-deploys.
  • Add CI secrets to `wheels-dev/wheels`:
    • `LINUX_REPO_GPG_PRIVATE_KEY` — ASCII-armored private key
    • `LINUX_REPO_GPG_PASSPHRASE` — passphrase for the private key
    • `LINUX_REPO_DISPATCH_TOKEN` — fine-grained PAT with write access to the two bucket repos
  • Wire the dispatch step in `release.yml` — extend the existing downstream-package-managers dispatch block (currently fires at `homebrew-wheels` and `scoop-wheels`) to also fire at `apt-wheels-dev` and `yum-wheels-dev`.
  • Update docs — once `apt.wheels.dev` resolves, replace the GitHub-Release download snippet in start-here/installing.mdx and command-line-tools/installation.mdx with the sources.list/yum.repo setup, and remove the "native apt/yum repos coming" ``.

Filename gotcha to handle in the metadata generator

GitHub Releases silently rewrites `` to `.` in uploaded asset filenames, so a `.deb` written to disk as `wheels_4.0.1snapshot.1700_amd64.deb` becomes `wheels_4.0.1.snapshot.1700_amd64.deb` at the URL. The metadata generator must compute the `.`-form to actually fetch the asset, then either rename to the canonical ``-form in `pool/` or accept the `.`-form and stay consistent. Either way works — the version field inside the package preserves `` so `dpkg`/`rpm` orders correctly. Documented in build-linux-packages.sh line 167-180.

Why two subdomains instead of one

Per the draft README: `packages.wheels.dev/apt/...` would work but produces uglier `sources.list` lines (`deb https://packages.wheels.dev/apt stable main`) vs the cleaner `deb https://apt.wheels.dev stable main`. Most projects (Docker, Caddy, Tailscale) use the two-subdomain pattern so Linux admins recognize the form.

Why this is a follow-up, not a v4.0 blocker

Phase 1 (download-then-install from GitHub Release) is fully working on Linux and ships with v4.0 GA via #2604. Phase 2 is a UX upgrade — users still get to wheels, just need to re-curl on each version bump until Phase 2 is live. The blocking work is mostly operational (mint key, set up CF Pages, store secrets) rather than code, which is why this fits better as a 4.0.x follow-up than a GA blocker.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions