Getting started
In this tutorial you will install velodex, start it with no configuration, install packages through it with pip and uv, publish a package of your own, then yank and delete it. It takes about ten minutes.
Prerequisites
You need Python with pip or uv to act as the client, and a velodex binary. Pick
whichever install channel fits; installation lists them all:
# standalone binary, no Python involved
curl -LsSf https://github.com/tox-dev/velodex/releases/latest/download/velodex-installer.sh | sh
uv tool install velodex
pip install velodex
# needs a Rust toolchain (https://rustup.rs); rust-toolchain.toml pins the version
git clone https://github.com/tox-dev/velodex.git
cd velodex
cargo build --release
Start velodex
Start the server. It needs no configuration; the defaults give you a pypi.org cached index with a private hosted store,
combined by a virtual index in front of them, served at root/pypi:
velodex serve # ./target/release/velodex serve when built from source
velodex is now listening on 127.0.0.1:4433. Leave it running and use a second terminal for the rest of the tutorial.
Install through the cache
Point any installer at the index URL. The first install fetches from pypi.org, verifies each artifact against its sha256, and caches it; repeat installs come from disk.
uv venv demo
VIRTUAL_ENV=demo uv pip install --index-url http://127.0.0.1:4433/root/pypi/simple/ requests
or with pip:
python -m venv demo
demo/bin/pip install --index-url http://127.0.0.1:4433/root/pypi/simple/ requests
Both clients use the PEP 658 metadata fast path through velodex: they resolve
dependency trees by fetching small .metadata files rather than whole wheels. You can see this on the metrics endpoint:
curl -s http://127.0.0.1:4433/metrics | grep metadataBrowse the web UI
velodex serves its own web interface on the same port. Open http://127.0.0.1:4433/ for a live
dashboard of the configured indexes and request counters, click an index to get a searchable project list, and click a
project for a pypi.org-style page: description, dependencies, classifiers, files with hashes, and a browser for the
contents of each supported archive. The contents links are shareable: the URL carries the file's sha256, display
filename, member path, and chunk offset separately, so filenames with spaces or URL punctuation still open the right
archive.
Publish a private package
Uploads are disabled until you set a token. Stop velodex, write a minimal config that adds one, and restart:
# velodex.toml
[[index]]
name = "pypi"
cached = "https://pypi.org/simple/"
[[index]]
name = "hosted"
upload_token = "demo-secret"
[[index]]
name = "root/pypi"
layers = ["hosted", "pypi"]
upload = "hosted"./target/release/velodex serve --config velodex.toml
Now publish a wheel with twine or uv (any username; the token is the password):
uv publish --publish-url http://127.0.0.1:4433/root/pypi/ -u __token__ -p demo-secret dist/*
Your package installs from the same URL as everything else: the virtual index serves your upload and pypi.org side by side, and your file shadows any upstream file with the same name.
Yank and delete it
Mark a version yanked (PEP 592) so resolvers skip it while pinned installs still work, then delete it outright:
curl -X PUT -u __token__:demo-secret http://127.0.0.1:4433/root/pypi/mypkg/1.0.0/yank
curl -X DELETE -u __token__:demo-secret http://127.0.0.1:4433/root/pypi/mypkg/
The same actions live in the web UI: open the project page, expand "Manage uploads", and enter the token.
After the delete, the upstream version of mypkg (if one exists on pypi.org) is visible again.
See what it served
The dashboard's index cards count pages, downloads, and bytes as you use them; the usage link drills down to
per-project and per-file numbers. The same counters are JSON at /+stats and Prometheus at /metrics; see
monitoring.
Where next
- How-to guides for specific tasks like proxying an Artifactory upstream or composing virtual indexes.
- Configuration reference for every TOML key.
- The index model to understand cached, hosted, and virtual indexes in depth.