pypi/warehouse: running the software behind PyPI yourself
The Python Package Index
At a glance
- What is it?
- Warehouse is the Python application that serves pypi.org, and the repository ships a Docker-based path to run it locally. The interesting part is not the code but the operational surface: Postgres, Redis, Celery, a file server and a simple API that clients depend on.
- Who is it for?
- Adopt Warehouse if you are contributing to PyPI itself or need a faithful local copy of the index to test packaging clients against, and verify first that docker-compose.yml's WEB_PORT default of 80 is free on your machine and that the dev database seed file dev/example.sql.xz is present, since the compose file mounts it.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Warehouse actually is, and who ends up running it
Warehouse is the server-side application behind pypi.org. The README opens by saying it is "the software that powers PyPI", which is a precise claim: this is not a library you import, it is a web application with a database, background workers and a public HTTP surface. The audience is correspondingly narrow. Packaging tool authors who need to test against the real index behaviour, contributors to PyPI, and people studying how a large Python web service is assembled are the natural users. If your goal is to publish your own packages to your own index, the repository is the wrong starting point, because nothing in the README describes a supported self-hosted production path. The documentation links point to warehouse.pypa.io, including an architectural overview, a roadmap and a getting-started guide, and those are where the project expects you to go before touching code.
The service topology visible in docker-compose.yml
The compose file is the clearest statement of how Warehouse is put together. A traefik:v3.7 container handles routing and exposes three entrypoints: web on port 80, a camo image proxy on 9000 and a file server on 9001. The web entrypoint is addressable at http://localhost/ by default, and the compose file lets you override it through the WEB_PORT environment variable. Traefik's dashboard is switched on with --api.insecure=true and bound to 8080, again overridable via TRAEFIK_DASHBOARD_PORT. Behind that sits a postgres:17.5 container whose host port is 5433 rather than 5432, with a comment noting that 5432 may already be in use by another PostgreSQL on the host. The compose file also declares named volumes for packages, packages-archive, simple, caches, redis_data, rstuf-metadata, pgdata, cachedata, node_modules and mailpit_data. Those names tell you the shape of the system without reading a line of Python: uploaded distributions, an archive of them, the Simple API's rendered output, a cache layer, Redis state, and RSTUF metadata for the index's signing infrastructure. A separate gunicorn-uploads.conf.py at the repository root suggests uploads run under their own Gunicorn configuration rather than sharing the main one.
Getting a local Warehouse running with Docker
The README is explicit that you run Warehouse locally with docker and directs you to the Getting started page at warehouse.pypa.io/development/getting-started/ for the instructions, so the authoritative steps live in the documentation rather than the README. What the repository does give you is the compose file those instructions build on. The compose file itself is the only command source here; it defines the services, ports and volumes. With the defaults, the web application answers at http://localhost/ and the Traefik dashboard at http://localhost:8080. The camo proxy listens on 9000 and the file server on 9001. The compose file reads the web host port from the WEB_PORT variable, defaulting to 80, so if port 80 is taken on your machine you set that variable before starting the stack. The database container publishes on host port 5433, not 5432, so an existing local PostgreSQL does not collide with it. The compose file mounts ./dev/example.sql.xz into the database container as a seed, along with ./dev/db/docker-entrypoint-initdb.d and ./dev/db/post-migrations.sql, which means the first start loads example data rather than an empty schema. Expect the initial start to take a while for that reason. The README's testing section points at the running tests and linters section of the documentation; the repository's own test entry points are a pytest suite under tests/ and a Jest suite configured in package.json, whose test script runs jest --coverage with the experimental VM modules flag.
Where the compose defaults will bite you
The development configuration is deliberately unsafe, and the file says so. The db service sets POSTGRES_HOST_AUTH_METHOD: trust with the inline comment "never do this in production!", and it passes POSTGRES_INITDB_ARGS with --no-sync, fsync=off and full_page_writes=off, which trades crash durability for seed speed. That is fine for a throwaway container and disqualifying for anything holding real packages. The traefik service also mounts /var/run/docker.sock from the host, which gives the proxy control over the Docker daemon; acceptable on a laptop, not something to copy into a shared machine. There is a further operational detail worth noticing: the traefik service depends on web with the condition service_started and a comment that there is no healthcheck yet, so startup ordering is loose and you may see the proxy come up before the application can answer. None of this is a defect in the project. It is a development stack, and the compose file reads as one.
Warehouse against a lighter private index
The obvious alternative for anyone who wants their own index is a purpose-built lightweight server such as devpi or a static file tree served over HTTP, and the difference in approach is the whole point. Warehouse implements the full pypi.org surface: the Simple API templates under warehouse/templates/api/simple/, upload handling, an archive of distributions, camo for proxying external images in rendered project pages, and RSTUF metadata for signing. A lightweight index implements a subset of the Simple API and stops there. If you need to test how a client behaves against the real index, only Warehouse gives you the real index. If you need somewhere to push internal wheels, Warehouse gives you a Postgres cluster, Redis, Celery workers, object storage and a reverse proxy, which is a large amount of machinery to serve files that a directory listing could serve. The repository also carries an admin interface (admin-lte is a dependency, and warehouse/admin/static/js exists) and a translation pipeline via Weblate and Babel, both of which only matter if you are operating the public index.
Licence, contribution and the cost of keeping up
Warehouse is Apache-2.0, and package.json repeats that identifier, so the licence is consistent across the repository. Apache-2.0 permits commercial use and modification and includes a patent grant; it also requires that you preserve notices and state changes. That is a general description of the licence, not legal advice, and if you plan to redistribute a modified Warehouse you should read the LICENSE file at the root yourself. On maintenance, the last push to the default branch was on 2026-09-23, and the repository is not archived, so the codebase is being worked on. For anyone running a fork, that is the cost that matters: PyPI changes continuously, and a fork drifts. The README routes issues to the GitHub issue tracker and discussion to IRC on Libera in #pypa and #pypa-dev, the PyPA Discord, and the Packaging category on Discourse. Contributors are expected to follow the PSF Code of Conduct. There are no retrieved releases, which is consistent with Warehouse being deployed from the main branch rather than published as a versioned artifact.
Editorial conclusion
Adopt Warehouse if you are contributing to PyPI itself or need a faithful local copy of the index to test packaging clients against, and verify first that docker-compose.yml's WEB_PORT default of 80 is free on your machine and that the dev database seed file dev/example.sql.xz is present, since the compose file mounts it. Do not adopt it as a private package index for a company: the compose file hardcodes POSTGRES_HOST_AUTH_METHOD: trust and comments that you should never do this in production, and the project documents no supported self-hosted production deployment.
Frequently asked questions
What is pypi/warehouse?
It is the software that powers PyPI, according to the README, and it is a Python web application rather than a library. The canonical deployment runs in production at pypi.org.
How do I install or run pypi/warehouse locally?
The README says you can run Warehouse locally in a development environment using docker and points to the Getting started documentation for the setup instructions. The repository supplies docker-compose.yml, which starts Traefik, PostgreSQL, Redis and the web application.
Which port does a local pypi/warehouse listen on?
The compose file gives the web entrypoint port 80, addressable at http://localhost/, with the host port overridable through the WEB_PORT environment variable. The camo image proxy uses 9000, the file server 9001, and the Traefik dashboard 8080.
What licence does pypi/warehouse use?
The licence is Apache-2.0, and package.json carries the same identifier. The LICENSE file at the repository root is the text to read if you plan to redistribute a modified copy.
Can I use pypi/warehouse as my company's private package index?
Nothing in the README describes a supported self-hosted production deployment, and the compose file sets POSTGRES_HOST_AUTH_METHOD: trust with a comment saying never to do this in production. The development stack is built for local use.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pypi-warehouse)