Documentation

Front another index

In this tutorial you will point velodex at a second upstream, TestPyPI, and serve it two ways: on its own route, and layered with pypi.org under one URL. The same recipe fronts an Artifactory, a GitLab registry, or any other PEP 503 index. It takes about ten minutes.

Why TestPyPI

TestPyPI is the packaging ecosystem's sandbox: public, credential-free for reads, and separate from the real index, which makes it a safe stand-in for "some other index you must serve". It also lacks some of pypi.org's polish, which is the point: you will watch velodex paper over the difference.

Mirror it

# velodex.toml
data_dir = "velodex-data"

[[index]]
name = "testpypi"
cached = "https://test.pypi.org/simple/"
velodex serve --config velodex.toml
uv venv demo
VIRTUAL_ENV=demo uv pip install --index-url http://127.0.0.1:4433/testpypi/simple/ sampleproject

sampleproject is TestPyPI's demonstration package. It installed through your cached index, was verified against the hashes its index page advertised, and is now cached: rerun the install with a fresh environment and it comes from disk.

See the protocol upgrade

Ask your cached index for the page and note what you get back:

curl -s -H "Accept: application/vnd.pypi.simple.v1+json" \
    http://127.0.0.1:4433/testpypi/simple/sampleproject/ | python3 -m json.tool | head

A PEP 691 JSON document with PEP 700 fields, whatever the upstream offered. velodex negotiates the best format the upstream has, canonicalizes it once, and serves the modern stack downstream; an HTML-only Artifactory gets the same treatment (how the degradation works).

Layer it with PyPI

One route that prefers the private-ish index and falls back to the big one:

[[index]]
name = "pypi"
cached = "https://pypi.org/simple/"

[[index]]
name = "both"
layers = ["testpypi", "pypi"]

Restart, then install something that only exists on pypi.org through the combined route:

VIRTUAL_ENV=demo uv pip install --index-url http://127.0.0.1:4433/both/simple/ requests

Resolution walked the layers in order: TestPyPI first (miss), pypi.org second (hit). One index-url, both sources, first match wins per file. With a real private upstream you would add credentials to its [[index]] entry (the guide lists the URL and auth shape for each provider).

Where next

On this page