- Python 92.8%
- Jinja 7.2%
Run uv sync after the patch bump so uv.lock reflects the updated project version and environment state. |
||
|---|---|---|
| .vscode | ||
| apt_mirror | ||
| docs | ||
| tests | ||
| .bumpversion.toml | ||
| .gitignore | ||
| .python-version | ||
| AGENTS.md | ||
| LICENSE | ||
| projects.yaml | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
DEB Party
DEB Party turns a short list of GitHub projects into a tidy .deb mini-mirror. It fetches the latest release for each project, grabs the right package (or repackages the upstream binary into a .deb), prunes old versions, and optionally drops the result straight into an Aptly repo.
Highlights
- Incremental runs: only download or build when a newer version is published.
- Regex-driven asset selection with musl/glibc awareness per project.
- Optional repackaging pathway that converts upstream tarballs/zips into
.debfiles. - Automatic pruning so only the most recent
Nversions stay on disk. - Integrates with Aptly via CLI, REST API, or a dry-run mode that stages packages locally.
- Simple flock-based locking prevents concurrent runs from stomping the pool.
Prerequisites
- Python 3.11+
aptlyinstalled on the host when using--aptly-mode cli.gnupginstalled when signing snapshots with--aptly-gpg-key.- For build-mode projects, packaging uses Docker +
dpkg-deb(insidedebian:bookworm); no Rust toolchain required. - A GitHub personal access token (PAT) exported as
GITHUB_TOKENis strongly recommended to avoid rate limits
Configuration
Project definitions live in projects.yaml (with projects.json still supported for backward compatibility). Each entry links a friendly name to a GitHub repo and either:
type: "deb"withpatterns: regexes used to pick the desired.debasset (placeholders like{arch}are filled in at runtime), ortype: "build"for projects packaged from an upstream tarball/zip; providepatternsthat match the desired archive or binary name. Useextra_filesto declare additional assets that should ship in the Debian package:
"extra_files": [
{ "source": "archive", "path": "**/completions/bash/tool", "dest": "usr/share/bash-completion/completions/tool" },
{ "source": "repo", "path": "LICENSE", "dest": "usr/share/doc/{package}/LICENSE" }
]
source may be archive (copy from the extracted release using glob support) or repo (download a file from the repository at the release tag). dest is relative to the package root.
Adjust patterns when upstream changes release naming, and keep the list ordered from most- to least-preferred assets (e.g., musl first).
One-time setup
For full first-time host setup (Aptly repository, passphrase-protected GPG key, systemd-creds, service and timer), see docs/first-time-setup.md.
For manual Aptly operations (repo/snapshot/publish lifecycle), see docs/aptly-usage.md.
For web serving examples (Caddy and Nginx), see docs/http-server-config.md.
Running the Mirror
uv sync # once, to materialise the virtualenv
export GITHUB_TOKEN=ghp_your_token
export KEY_ID=YOUR_KEY_ID
uv run python -m apt_mirror \
--config projects.yaml mirror \
--out /srv/deb/pool/upstream \
--arch amd64 \
--arch arm64 \
--versions 5 \
--aptly-mode cli \
--aptly-repo upstream \
--aptly-component main \
--aptly-architectures amd64 --aptly-architectures arm64 \
--aptly-gpg-key "$KEY_ID"
Tip: the console script apt-mirror installed by uv exposes the same CLI, so uv run apt-mirror --config projects.yaml mirror ... works too.
Key flags:
--archmay be repeated to mirror multiple architectures in one run.--aptly-mode nonekeeps everything local and skips Aptly integration (ideal for dry runs).--aptly-mode api --aptly-endpoint filesystem:srvdeb:.uploads throughaptly api serveand issues a publish/update.--aptly-component,--aptly-architectures, and--aptly-gpg-keyfine-tune snapshot publishing when running in CLI mode.--build-missingenables the packaging flow for entries markedtype: "build".--onlyand--skipfilter the project list for targeted refreshes.
Outputs land in the directory passed to --out. When Aptly CLI integration is enabled, new packages are added to the repo in one batch, a snapshot named <repo>-YYYYMMDD-HHMMSS-ffffff is created, and the publication is created or switched automatically.
Aptly Workflow
In CLI mode, all new packages gathered across the requested architectures are staged and added to the repository in one batch, a timestamped snapshot (<repo>-YYYYMMDD-HHMMSS-ffffff) is created whenever changes occur, and the snapshot is published. The first run uses aptly publish snapshot, subsequent runs switch the live publication with aptly publish switch. Provide --aptly-architectures (defaults to the canonical arches you mirrored) and --aptly-gpg-key to match your signing setup.
Housekeeping
Old packages are pruned after every run so only the latest --versions remain. A lock file in the output directory keeps simultaneous runs from colliding. Check stderr for messages such as + downloading, + built, or - pruned when triaging issues. All temporary build clones live under /tmp and are deleted automatically.
Development
Core logic now lives inside the root apt_mirror/ package (cli.py for Click parsing, pipeline.py for release processing, aptly.py for publishing, package.py for dpkg repackaging, projects.py for config loading); keep new functionality there. See AGENTS.md for contributor guidance. Use uv for workflows: uv run python -m apt_mirror --help to verify new options, uv run python -m compileall apt_mirror for a quick syntax check, uv run ruff check apt_mirror to lint, and uv run bump-my-version bump patch (or minor/major) when updating the version.