Documentation

From static and legacy setups

A family of small solutions covers pieces of the job. Each is fine at its piece; the migrations below are for when the pieces stop composing.

dumb-pypi

dumb-pypi generates a static PEP 503 index from a list of filenames; the files live wherever a URL can reach (S3, nginx), and having no server is the design. Publishing means regenerating the site; PyPI itself still needs --extra-index-url; name normalization is your web server's problem. In velodex, uploads are the write path (twine upload, index updated transactionally) and the same process mirrors PyPI, so clients keep one index-url. Migration is a one-time twine loop over the bucket's files.

Plain directories and python -m http.server

pip's --find-links accepts a directory listing, and --index-url accepts any PEP 503-shaped tree, so a shared folder works with zero tooling. It also serves whole wheels to every resolve (no PEP 658 metadata), lists everything in one flat page, offers no fallback to PyPI, and authenticates nobody. It remains the right tool for a laptop and a handful of wheels.

pip2pi

pip2pi snapshots a requirements set into a static index; its last release and commit are from August 2021. The workflow it automated (resolve on a connected side, carry the result) is the air-gap guide with a cache instead of a script: the carried data directory keeps hashes, metadata, and the JSON API.

nginx caching proxies

nginx_pypi_cache is an nginx config that reverse-proxies pypi.org and files.pythonhosted.org with proxy_cache: the read-through half of the job in one file, with the upstreams hard-coded and no uploads or private packages. velodex adds the index-aware half: digest verification, Cache-Control-driven refresh with a background sweep, private hosting, and usage counters. (Flask-Pypi-Proxy, sometimes cited alongside it, last released in 2014 and predates every modern index PEP.)

The renames

Setupvelodex
dumb-pypi regenerate + S3twine upload to a hosted index
--find-links /shared/wheels--index-url http://host:4433/{route}/simple/
pip2pi snapshot + rsyncwarm the cache, carry data_dir
nginx proxy_cache configa cached index
On this page