Skip to main content

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 by pip when the repository is not served over SSL.

Example with basic authentication:

[global]
index-url = http://adminuser:[email protected]: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:[email protected]: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 your pyproject.toml file.

  • <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:[email protected]: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:[email protected]: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 by twine to select the target repository entry, for example pypi

  • <NEXUS_URL> - URL of your Nexus instance, for example example.nexus.com

  • <REPO_NAME> - Name of the target hosted repository in Nexus, for example pypi-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.

  1. Add an entry for your Nexus host in ~/.netrc in Linux or macOS and %HOME%\_netrc on 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

  2. Set secure file permissions. The .netrc file is ignored if it is world-readable:

    chmod 600 ~/.netrc

Client Support

  • pip: Reads ~/.netrc automatically through the underlying HTTP library. Works for both hosted and proxy repositories.

  • twine: Does not support .netrc. Use --username and --password flags or configure ~/.pypirc for uploads.

  • curl: Requires the .netrc option to use .netrc credentials.

  • Ensure that the hostname in .netrc exactly 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 before pip uses 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.93 PEP 658: Provides package metadata in the Simple API through the data-dist-info-metadata attribute.

  • New in 3.93 PEP 691: Provides JSON-based Simple API through content negotiation.

  • New in 3.94 PEP 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-Type for previously cached PyPI .whl.metadata assets.

    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 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.1 and later

  • uv 0.1.0 and later

  • Poetry 1.8 and later. For PEP 700, use Poetry 2.x to 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:

  1. Enable the Firewall Audit and Quarantine capability on the proxy repository.

  2. Select Remove Quarantined Versions in Sonatype Nexus Repository settings.