Configure PyPI with Nexus
Configure PyPI with Nexus
Configure your PyPI clients to connect to and authenticate to a Nexus PyPI repository. Create a PyPI repository in Nexus before you configure your clients. Refer to Create a PyPI Repository for more details.
PyPI can be configured through the following methods:
| Configuration method | Client or file | Best for |
|---|---|---|
| pip configuration | pip.conf or pip.ini |
Install and search packages from a group, proxy, or hosted repository |
| uv configuration | pyproject.toml |
Install packages and sync project dependencies through Nexus |
| Poetry configuration | poetry config or pyproject.toml |
Install dependencies and configure publish targets |
| Twine configuration | .pypirc |
Publish packages to a hosted repository |
Configure pip
Use this configuration method when you want pip to install or search packages through Nexus Repository. Create a pip.conf file on Unix or a pip.ini file on Windows.
[global]
index-url = http://<authentication>@<NEXUS_URL>:<port>/repository/<REPO_NAME>/simple
trusted-host = <NEXUS_HOST>
Where,
<NEXUS_URL>- Your Nexus instance URL.<REPO_NAME>- Name of the target repository in Nexus. Use a group repository when you want one endpoint for proxy and hosted content.<NEXUS_HOST>- Nexus host name used bypipwhen the repository is not served over SSL.
Example with basic authentication:
[global]
index-url = http://adminuser:adminpassword123@example.nexus.com:8081/repository/pypi-all/simple
trusted-host=example.nexus.com
Example with environmental variables:
export PIP_INDEX_URL=http://example.nexus.com:8081/repository/pypi-all/simple
export PIP_TRUSTED_HOST=example.nexus.com
Example for multiple repositories:
[global]
index-url = http://nexus.example.com:8081/repository/pypi-all/simple
extra-index-url =
http://nexus.example.com:8081/repository/pypi-hosted/simple
http://nexus.example.com:8081/repository/pypi-proxy/simple
trusted-host=example.nexus.com
Example with usertoken:
PIP_INDEX_URL=http://build-user:NX_TOKEN_VALUE@example.nexus.com:8081/repository/pypi-all/simple
PIP_TRUSTED_HOST=example.nexus.com
To verify your configuration, run:
pip config list -v
Note
When you use pip, Sonatype recommends serving Nexus Repository over SSL. Otherwise, add --trusted-host to your requests or configure pip to trust your Nexus Repository host.
You can also configure pip with PIP_INDEX_URL and PIP_TRUSTED_HOST or pass --index-url on the command line. To use more than one repository, add extra-index-url entries.
Configure uv
Use this configuration method when you want uv to install packages and sync project dependencies through Nexus Repository.
[[tool.uv.index]]
name = "<INDEX_NAME>"
url = "http://<NEXUS_URL>:<port>/repository/<REPO_NAME>/simple"
default = true
Where,
<INDEX_NAME>- Name of the index entry in yourpyproject.tomlfile.<NEXUS_URL>- Your Nexus instance URL.<REPO_NAME>- Name of the target repository in Nexus.
Example with basic authentication:
[[tool.uv.index]]
name = "nexus"
url = "http://adminusername:adminpassword123@example.nexus.com:8081/repository/pypi-all/simple"
default = true
Example with environmental variables:
export UV_INDEX_URL=http://example.nexus.com:8081/repository/pypi-all/simple
Example for multiple repositories:
[[tool.uv.index]]
name = "nexus-all"
url = "http://example.nexus.com:8081/repository/pypi-all/simple"
default = true
[[tool.uv.index]]
name = "nexus-hosted"
url = "http://example.nexus.com:8081/repository/pypi-hosted/simple"
[[tool.uv.index]]
name = "nexus-proxy"
url = "http://example.nexus.com:8081/repository/pypi-proxy/simple"
Example with usertoken:
uv pip install requests --index-url http://username:NX_TOKEN_VALUE@example.nexus.com:8081/repository/pypi-all/simple
Note
You can also configure uv with UV_INDEX_URL, pass --index-url on the command line, or add multiple [[tool.uv.index]] entries when you need more than one repository. To embed basic authentication, include credentials in the index URL.
Configure Poetry
Use this configuration method when you want Poetry to install dependencies through Nexus Repository and publish packages to a hosted repository.
Using poetry config:
poetry source add --priority=primary <SOURCE_NAME> http://<NEXUS_URL>/repository/<REPO_NAME>/simple
poetry config http-basic.<SOURCE_NAME> <USERNAME> <PASSWORD>
Where,
<SOURCE_NAME>- Source name used by Poetry.<NEXUS_URL>- Your Nexus instance URL.<REPO_NAME>- Name of the target repository in Nexus.<USERNAME>- Your Nexus username.<PASSWORD>- Your Nexus password or user token.
Example using poetry config:
poetry source add --priority=primary nexus http://example.nexus.com/repository/pypi-all/simple
poetry config http-basic.nexus admin admin123
Using pyproject.toml:
[[tool.poetry.source]]
name = "nexus"
url = "http://localhost:8081/repository/pypi-all/simple"
priority = "primary"
Store the authentication in poetry config:
poetry config http-basic.nexus username password
Note
The source add command writes the source entry to pyproject.toml. You can also define the source directly in pyproject.toml.
Example with environmental variables:
export POETRY_REPOSITORIES_NEXUS_URL=http://nexus.example.com:8081/repository/pypi-all/simple
export POETRY_HTTP_BASIC_NEXUS_USERNAME=username
export POETRY_HTTP_BASIC_NEXUS_PASSWORD=password
Example for multiple repositories:
[[tool.poetry.source]]
name = "nexus-all"
url = "http://nexus.example.com:8081/repository/pypi-all/simple"
priority = "primary"
[[tool.poetry.source]]
name = "nexus-hosted"
url = "http://nexus.example.com:8081/repository/pypi-hosted/simple"
priority = "supplemental"
[[tool.poetry.source]]
name = "pypi"
priority = "supplemental"
# Configure authentication for each source
poetry config http-basic.nexus-all username password
poetry config http-basic.nexus-hosted username password
Example with usertoken:
[[tool.poetry.source]]
name = "nexus"
url = "http://example.nexus.com:8081/repository/pypi-all/simple"
priority = "primary"
# Store the authentication in poetry config
poetry config http-basic.nexus adminusername NX_TOKEN_VALUE
Configure twine
Use this configuration method when you want to publish packages to a PyPI hosted repository. The .pypirc file stores the repository endpoint and credentials used for uploads.
[distutils]
index-servers =
<REPOSITORY_ALIAS>
[<REPOSITORY_ALIAS>]
repository: https://<NEXUS_URL>/repository/<REPO_NAME>/
username: <USERNAME>
password: <PASSWORD>
Where,
<REPOSITORY_ALIAS>- Name used bytwineto select the target repository entry, for examplepypi<NEXUS_URL>- URL of your Nexus instance, for exampleexample.nexus.com<REPO_NAME>- Name of the target hosted repository in Nexus, for examplepypi-internal<USERNAME>- Your Nexus username user token name code<PASSWORD>- Your Nexus password or usertoken pass code
Example:
[distutils]
index-servers =
pypi
[pypi]
repository: https://example.nexus.com/repository/pypi-internal/
username: admin
password: admin123
If you have multiple hosted repositories, add one named entry per hosted repository.
Authenticate using .netrc
You can store credentials in a .netrc file so that supported clients authenticate automatically without embedding credentials in repository URLs.
- Add an entry for your Nexus host in
~/.netrcin Linux or macOS and%HOME%\_netrcon Windows.
machine <NEXUS_HOST>
login <USERNAME>
password <PASSWORD>
Where,
<NEXUS_HOST>- Your Nexus instance<USERNAME>- Your Nexus username or usertoken name code<PASSWORD>- Your Nexus password or user token passcode
- Set secure file permissions. The
.netrcfile is ignored if it is world-readable:
chmod 600 ~/.netrc
Client Support
- pip: Reads
~/.netrcautomatically through the underlying HTTP library. Works for both hosted and proxy repositories. - twine: Does not support
.netrc. Use--usernameand--passwordflags or configure~/.pypircfor uploads. - curl: Requires the
.netrcoption to use.netrccredentials. - Ensure that the hostname in
.netrcexactly matches the repository URL host.
SSL Usage for PyPI Repositories
Use HTTPS with proxy, hosted, and group repositories to ensure a secure connection with a self-signed certificate. To set up the repository manager to serve HTTPS, see Configuring SSL.
After Nexus Repository is configured to serve HTTPS, verify the certificate before updating pip.
openssl verify <CERTIFICATE_FILE>
Where,
<CERTIFICATE_FILE>is the certificate file you want to verify beforepipuses it.
Example:
openssl verify nexus.pem
For pip, update pip.conf or pip.ini when the certificate is valid.
[global]
index-url = https://<NEXUS_URL>/repository/<REPO_NAME>/simple
cert = <CERTIFICATE_FILE>
For uv, use the following codeblock:
export UV_INDEX_URL=https://<NEXUS_URL>/repository/<REPO_NAME>/simple
export SSL_CERT_FILE=<CA_BUNDLE_FILE>
For Poetry, use the following codeblock:
poetry config certificates.<SOURCE_NAME>.cert <CA_BUNDLE_FILE>
Example for pip:
[global]
index = https://example.nexus.com/repository/pypi-all/pypi
index-url = https://example.nexus.com/repository/pypi-all/simple
cert = nexus.pem
PEP 658, PEP 691 and PEP 700 Support for PyPI
Nexus Repository supports the following Python packaging standards for PyPI:
- New in 3.93PEP 658: Provides package metadata in the Simple API through the
data-dist-info-metadataattribute. - New in 3.93PEP 691: Provides JSON-based Simple API through content negotiation.
- New in 3.94PEP 700: Adds package version, file size, and upload time metadata to JSON Simple API responses.
- New in 3.95 When you upgrade to Nexus Repository 3.95.0, Nexus Repository automatically repairs the stored
Content-Typefor previously cached PyPI.whl.metadataassets.
No administrator action is required. The repair runs automatically during the upgrade and applies to PyPI hosted and proxy repositories. PyPI group repositories are unaffected because they do not store local assets.
In High Availability deployments using a rolling upgrade, the repair completes after all nodes are upgraded. If the repair timeout is reached before all nodes are upgraded, the repair is retried on the next node startup.
The following are the Python clients that support PEP 658, PEP 691 and PEP 700:
pip 23.1and lateruv 0.1.0and laterPoetry 1.8and later. For PEP 700, usePoetry 2.xto leverage upload-time for audit workflows.
To test PEP 658 and PEP 691 features, use:
curl http://example.nexus.com/repository/pypi-all/simple/requests/ | grep data-dist-info-metadata
curl -H "Accept: application/vnd.pypi.simple.v1+json" http://example.nexus.com/repository/pypi-all/simple/requests/
Python clients that do not support PEP 658 or PEP 691 continue to receive the legacy 503 response.
PEP 700 adds the following fields to JSON package detail responses:
| Field | Description | Notes |
|---|---|---|
meta.api-version |
Identifies the Simple API version used by the JSON response. | Package detail responses use v1.1 when Nexus Repository emits PEP 700 fields. If the response does not meet the v1.1 requirements, Nexus Repository falls back to v1.0. |
versions |
Lists the versions published for the package. | Nexus Repository sorts versions by PEP 440 when it emits the field. |
files[].size |
Shows the package file size in bytes. | Required for Simple API v1.1 package detail responses. |
files[].upload-time |
Shows the package upload time as an ISO 8601 UTC timestamp. | Included when upload time metadata is available. For proxy repository, it displays the time when it was uploaded to the upstream and for hosted repositories, it displays the ingest time. |
Run Repair - Rebuild PyPI Repository Metadata task to add PEP 700 fields to existing hosted repository packages.
To test PEP 700 feature, use:
curl -H "Accept: application/vnd.pypi.simple.v1+json" \
https://<nexus-url>/repository/<repository-name>/simple/<package-name>/
Policy-Compliant Component Selection for PyPI
Policy-compliant component selection for PyPI requires IQ Server version 167 and later. This functionality requires integration with Sonatype Repository Firewall and a Firewall license.
When a user requests a PyPI package without explicitly specifying a version, the PyPI client relies on the package metadata to select a version that satisfies the version constraints. If the selected version has policy violations and is quarantined by the Sonatype Repository Firewall, it will cause a build failure that requires a manual fix of the root cause.
By enabling this option, the Repository Firewall removes quarantined versions from the PyPI package metadata to prevent you from selecting a version with policy violations.
Perform the following steps to enable this behaviour:
Enable the Firewall Audit and Quarantine capability on the proxy repository.
Select Remove Quarantined Versions in Sonatype Nexus Repository settings.