Setting Up a Private PyPI Registry (devpi) for Python Teams
When a Python team grows the number of internal libraries — utilities, SDKs for APIs, analytical tools — they need to be centrally stored and distributed via pip install. Copying .whl files over the network or storing them in the repository is a direct path to version and dependency chaos. A private PyPI registry solves this problem: without it, each new CI/CD build risks getting incompatible dependency versions, and build time increases due to repeated downloads.
We deploy devpi — a lightweight Python server compatible with PyPI. Unlike heavy Nexus (requires 4+ GB RAM and JVM), devpi runs on 256 MB RAM and one CPU. It not only stores your packages but also caches public ones, accelerating CI and saving traffic. Below is how it works in practice.
How devpi helps accelerate CI/CD
Imagine your CI pipeline downloads pandas, requests, and scikit-learn from pypi.org on every build. That takes minutes and depends on external bandwidth. With devpi, packages are fetched from PyPI the first time, then served from the local cache. For a team of 50 developers, build time savings can reach 70%, and traffic costs can drop by up to $200 per month (at $0.12/GB). When scaling to 100+ developers, average monthly savings range from $300 to $500.
We use devpi in a Docker container with a persistent volume for the cache.
Ready-to-use docker-compose.yml for quick start
---
services:
devpi:
image: muccg/devpi:latest
container_name: devpi
ports:
- "3141:3141"
volumes:
- devpi-data:/data
environment:
- DEVPI_SERVERDIR=/data
command: devpi-server --host 0.0.0.0 --port 3141 --serverdir /data
restart: unless-stopped
volumes:
devpi-data:After launch, initialize the server and create an index with upstream to PyPI:
devpi use http://devpi.company.ru:3141
devpi login root --password=""
devpi user -m root password=SecureRootPass
devpi user -c deploy password=DeployPass
devpi login deploy
devpi index -c company/prod bases=root/pypi volatile=False
devpi use company/prodThe parameter volatile=False prevents deletion of uploaded packages — critical for reproducible builds.
Publishing internal packages
For publication, we use twine. Example package configuration:
[project]
name = "company-utils"
version = "1.2.0"
description = "Internal utilities"
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.backends.legacy:build"Build and upload commands:
python -m build
twine upload --repository-url http://devpi.company.ru:3141/company/prod/ --username deploy --password ${DEVPI_PASSWORD} dist/*
In GitLab CI this looks like:
---
publish-pypi:
image: python:3.12-slim
script:
- pip install build twine
- python -m build
- twine upload --repository-url ${DEVPI_URL}/company/prod/ --username deploy --password ${DEVPI_PASSWORD} dist/*
only:
- tags
Why devpi wins over Nexus for Python teams
Devpi deploys 3 times faster than Nexus and consumes 6 times less memory. Comparison:
| Criteria | Devpi | Nexus |
|---|---|---|
| Size and complexity | Lightweight Python application | Heavy Java (requires JVM) |
| Supported formats | PyPI only | Maven, npm, Docker, PyPI, etc. |
| Caching | Built-in, deduplication | Yes, but shared storage |
| Deployment time | 1–2 hours (Docker) | 3–5 hours (with tuning) |
| Resource consumption | 256 MB RAM, 1 CPU | 4+ GB RAM, 2+ CPU |
For a pure Python team, devpi wins on simplicity and resources. According to devpi documentation and user feedback.
What is included in a turnkey devpi setup
- Installation of devpi in Docker or on bare metal with persistent storage.
- SSL configuration via nginx (HTTPS is mandatory in a corporate environment). We use Let's Encrypt.
- Creation of indices: production index with PyPI cache and dev index for testing.
- Generation of
pip.conffor developers (Linux/macOS/Windows). - CI pipeline templates (GitLab CI / GitHub Actions) for publishing packages.
- Preloading of popular packages into the cache for air-gapped environments.
- Documentation and team training (1–2 hours).
- Post-deployment support: health monitoring, backup, version updates.
Typical results after deployment:
| Metric | Before deployment | After deployment |
|---|---|---|
| Package installation time in CI | 2–5 min | 10–30 sec |
| Traffic usage | 5–10 GB/month | 1–2 GB/month |
| Build reproducibility | 90% | 99.9% |
| Time to publish packages | 30 min | 5 min |
Process of work
- Analysis: audit of existing packages, index requirements, versioning policy.
- Design: index schema, role model, mirroring.
- Deployment: server setup, SSL, reverse proxy (nginx).
- Integration: connecting CI/CD, pip configuration, testing.
- Handover: instructions, credentials, training.
Timelines and pricing
Estimated: 1 to 3 days for basic deployment. Pricing is calculated individually based on infrastructure complexity and required SLA. Get a consultation for an accurate estimate for your project — we will select the configuration for your infrastructure.
Practical experience
Over the years, we have deployed devpi for 20+ companies — from startups with one team to enterprises with hundreds of developers. We guarantee stable operation: MTTR of incidents does not exceed 2 hours. We use a GitOps approach for configuration management and automatic tests on publication. Reducing CI/CD infrastructure costs by 20–30% is a typical result.
Order the setup of a private PyPI registry — eliminate Python package chaos and get a reliable system that saves developer hours every day. Contact us to discuss your project details.







