Skip to main content

TUI toolkit for maintaining a PyPI mirror on an airgapped network

Project description

pypi-pigeon

A toolkit for maintaining a PyPI mirror on an airgapped network. Packages are brought over via sneakernet (DTA — physically moving drives between networks).

Uses bandersnatch for the base mirror and a supplement workflow for packages that need full dependency resolution. Features a Textual TUI for interactive use and --plain mode for scripting.

Running in a true airgap? See docs/airgap-workflow.md for the full operational workflow — including one-time server setup, the security-wipe transfer model, and pigeon-merge.py, a standalone merge script that runs on the airgapped server with no dependencies beyond Python 3.6.

Install

pip install pypi-pigeon
# or with uv:
uv tool install pypi-pigeon

Workflow

Internet-connected machine

pigeon setup      # one-time wizard: configure pigeon.toml + generate bandersnatch.conf
pigeon dry-run    # optional: estimate mirror size before committing (takes hours, resumable)
pigeon sync       # run bandersnatch + fetch supplement packages

DTA the following to your airgapped server:

  • <mirror-dir>/web/ — the base mirror
  • supplement/dist/ — supplement wheels (if you used pigeon add)

Airgapped server

pigeon merge      # fold supplement wheels into the mirror's simple/ index
# or on servers without pigeon installed:
python3 pigeon-merge.py --mirror /your/mirror --dist supplement/dist

Re-run after every sync — bandersnatch overwrites simple/<pkg>/index.html for packages it manages, wiping supplement links for those packages. Both merge commands are idempotent and fast.

Commands

Command Description
pigeon setup TUI wizard — configure pigeon.toml and generate bandersnatch.conf
pigeon dry-run Fetch PyPI metadata to estimate mirror size before syncing
pigeon sync Run bandersnatch + fetch supplement packages
pigeon mirror Alias for sync (bandersnatch's own term)
pigeon update Alias for sync with update framing; --check checks supplement packages for newer versions without syncing
pigeon merge Fold supplement/dist/ into the mirror's simple/ index
pigeon add <pkg> Append packages to the supplement list
pigeon status Show mirror health — package count, last sync time, cached wheels, and an outdated check against PyPI

--plain flag — add to dry-run, sync/mirror, or merge to stream plain stdout instead of launching the TUI. Useful for scripting and CI.

--config PATH — available on all commands. By default pigeon searches up the directory tree for pigeon.toml (git-style), so you can run commands from any subdirectory of your mirror workspace.

Config

pigeon setup creates pigeon.toml:

[mirror]
dir = "/path/to/mirror"   # where bandersnatch writes; nginx serves web/ from here
workers = 10              # hard max 10 (bandersnatch limit)
keep_releases = 3
diff_file = ""            # path to write a changed-file list each sync; "" = disabled

[filter]
python_versions = ["3.10"]
platforms = ["linux-manylinux-x86_64"]
include_sdists = false
include_prereleases = false
allowlist_packages = []   # mirror only these packages; empty = mirror everything
blocklist_packages = []

[supplement]
dist_dir = "supplement/dist"
packages_file = "requirements.txt"

Edit directly or re-run pigeon setup anytime to reconfigure.

Supplement packages

The base mirror uses aggressive filtering (specific Python version, platform, latest N releases). For packages outside those filters — or pinned versions you need — use the supplement:

pigeon add requests numpy==1.26.0
# or edit supplement/packages.txt directly (standard requirements.txt format)

During pigeon sync, supplement packages are fetched via pip download --only-binary :all: with full transitive dependency resolution. The result is a self-contained closure of wheels — no missing dependencies on the airgapped side.

Supported platforms

The setup wizard lets you pick any combination of:

  • Linux manylinux x86_64 / aarch64 / i686
  • Linux musllinux x86_64 / aarch64 (Alpine)
  • Windows AMD64 / x86 / ARM64
  • macOS x86_64 (Intel) / ARM64 (Apple Silicon)

Bandersnatch gotchas

Plugin names changed in 7.xblocklist_release_files and keep_only_latest_releases no longer exist and are silently ignored. pigeon generates the correct config automatically; don't hand-edit bandersnatch.conf for anything covered by pigeon.toml.

Workers hard max = 10 — bandersnatch raises an exception above 10. The setup wizard enforces this.

Test runs — to verify filters before committing to a full sync, temporarily add an [allowlist] section to bandersnatch.conf. Expected results: numpy → only cp310-manylinux-x86_64 wheels; cryptography → only abi3-manylinux-x86_64; requests → only py3-none-any. Zero .tar.gz files. Remove the allowlist before re-running pigeon setup — it regenerates bandersnatch.conf from scratch.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypi_pigeon-0.3.0.tar.gz (32.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pypi_pigeon-0.3.0-py3-none-any.whl (30.6 kB view details)

Uploaded Python 3

File details

Details for the file pypi_pigeon-0.3.0.tar.gz.

File metadata

  • Download URL: pypi_pigeon-0.3.0.tar.gz
  • Upload date:
  • Size: 32.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pypi_pigeon-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d5184902eb00f2f5db37bd47d77760714f97aaa82e4e4455ecdd7b91425b5597
MD5 9b5b5c9c47bcd0b5e1f640ffc06c689d
BLAKE2b-256 042adc62876e8a967ffc3742097925f1fcbc80a7b24fce3f954847e4b971e6d2

See more details on using hashes here.

File details

Details for the file pypi_pigeon-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pypi_pigeon-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 30.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pypi_pigeon-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 622ee695fccfcb12541fcd32988563cd3803033fe156a89b2aba7728bebcf6cc
MD5 0b9b8dc70a02b298181666ba99e43e8b
BLAKE2b-256 3cbc6a3ad6ee64d7e776b002a9f3e794026284dcd346d110d6ade6433442cdba

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page