PyPI
NORA implements the PEP 503 (Simple Repository API) and PEP 691 (JSON Simple API) specifications. Upload packages with twine and install with pip, with transparent proxying from pypi.org.
Client Configuration
Section titled “Client Configuration”Install packages through NORA:
pip install --index-url http://nora.example.com:4000/simple/ my-packagePer-project pip.conf or environment variable:
export PIP_INDEX_URL=http://nora.example.com:4000/simple/Upload packages:
twine upload --repository-url http://nora.example.com:4000/simple/ dist/*Upstream Proxy
Section titled “Upstream Proxy”NORA fetches packages from PyPI when they are not found locally. Download URLs in index pages are rewritten to point through NORA.
config.toml:
[pypi]enabled = trueproxy = "https://pypi.org/simple/"proxy_timeout = 30Environment variables:
| Variable | Description | Default |
|---|---|---|
NORA_PYPI_ENABLED | Enable PyPI registry | true |
NORA_PYPI_PROXY | Upstream registry URL | https://pypi.org/simple/ |
NORA_PYPI_PROXY_AUTH | Upstream auth (user:pass) | — |
NORA_PYPI_PROXY_TIMEOUT | Upstream timeout in seconds | 30 |
Features
Section titled “Features”| Feature | Status | Notes |
|---|---|---|
| Simple index (HTML) | Full | PEP 503 |
| Simple index (JSON) | Full | PEP 691, via Accept header |
| Package versions page | Full | HTML + JSON |
| File download | Full | Wheel, sdist, egg |
twine upload | Full | Multipart form-data |
| SHA256 hashes | Full | In metadata links |
| Case normalization | Full | My-Package becomes my-package |
| JSON API metadata | Full | application/vnd.pypi.simple.v1+json |
| Upstream proxy | Full | Configurable TTL |
| Yanking | — | Not implemented |
| Upload signatures (PGP) | — | Not implemented |
Behind a Reverse Proxy
Section titled “Behind a Reverse Proxy”When NORA runs behind Caddy, Traefik, or Nginx, set NORA_PUBLIC_URL so that download links point to the external address instead of http://0.0.0.0:4000:
NORA_PUBLIC_URL=https://registry.example.comIf the proxy uses a self-signed certificate, pip will silently fail with “No matching distribution found”. Fix with one of:
# Option 1: trust the hostpip install --trusted-host registry.example.com my-package
# Option 2: point pip to the CApip install --cert /path/to/ca.crt my-packageFor permanent config create ~/.pip/pip.conf:
[global]index-url = https://registry.example.com/simple/trusted-host = registry.example.comSee TLS / HTTPS for full reverse proxy examples.
Known Limitations
Section titled “Known Limitations”- Yanking is not supported.
- PGP upload signatures are not supported.