# Build configuration

URL: https://edu.chainguard.dev/chainguard/libraries/python/build-configuration.md
Last Modified: April 7, 2025
Tags: Chainguard Libraries, Python

Configuring Chainguard Libraries for Python on your workstation

The configuration for the use of Chainguard Libraries depends on how you&rsquo;ve set up your build tools and CI/CD workflows. At a high level, adopting the use of Chainguard Libraries in your development, build, and deployment workflows involves the following steps:
If you or an administrator have not done so already, set up your organization&rsquo;s repository manager to use Chainguard Libraries for Python. Log into your organization&rsquo;s repository manager and retrieve credentials for the build tool you are configuring. Configure your development or build tool with this information. Remove local caches on workstations and CI/CD pipelines. This step ensures that dependencies are preferentially sourced from Chainguard Libraries. Finally, confirm that your development tools and CI/CD workflows are correctly ingesting dependencies from Chainguard Libraries. These changes must be performed on all workstations of individual developers and other engineers running relevant application builds. They must also be performed on any build tool such as Jenkins, TeamCity, GitHub Actions, or other infrastructure that draws in dependencies.
See the minimal example projects on this page for demonstrations using uv and pip.
Step 1: Retrieve authentication credentials To configure any build tool, you must first access credentials from your organization&rsquo;s repository manager or for direct access.
Cloudsmith The following steps allow you to determine the URL and authentication details for accessing your organization&rsquo;s Cloudsmith repository manager.
Log into Cloudsmith. Select the Repositories tab and click on the python-all repository. Select the Packages tab. Select Push/Pull Packages on the right. Choose the Python format. Select your desired authentication method for Entitlement tokens and copy the URL to use in your build tool - for example https://dl.cloudsmith.io/.../exampleorg/python-all/python/simple/. In the URL ... is replaced with a default token or your personal token depending on your selection and exampleorg is replaced with the name of your organization. The URL contains both the name of the repository python-all as well as python as an identifier for the format. Alternatively, use the API Key and copy the URL to use in your build tool for example https://username:{{apiKey}}@dl.cloudsmith.io/basic/exampleorg/python-all/python/simple/. Replace username and exampleorg with your Cloudsmith details and replace {{apiKey}} with the API key from the Personal API Keys section from the drop down on your username. Note that for use with build tools you must include the simple/ context so that the package index is used successfully.
Google Artifact Registry Use the Google Cloud Artifact Registry documentation to authenticate to your Python Artifact Registry.
JFrog Artifactory The following steps allow you to determine the identity token and URL for accessing your organization&rsquo;s JFrog Artifactory repository manager.
Select Administration in the top navigation bar. Select Repositories in the left hand navigation. Select the Virtual tab in the repositories view. Locate the python-all repository row and press the three dots (&hellip;) in the last column on the right. Select Set Me Up in the dialog. Select Generate Token &amp; Create Instructions Copy the generated token value to use as the password for authentication. Select Generate Settings. Copy the value from one of the URL fields. They are all identical. For example, https://exampleorg.jfrog.io/artifactory/python-all with exampleorg. Note that for use with build tools you must append simple/ to the URL so that the package index is used successfully - https://exampleorg.jfrog.io/artifactory/python-all/simple/. Sonatype Nexus Repository The following steps allow you to determine the URL and authentication details for accessing your organization&rsquo;s Sonatype Nexus repository group.
Click Browse in the Welcome view or the browse icon (cube) in the top navigation bar. Locate the URL column for the python-all repository group and press copy. The URL should take the following format: https://repo.example.com/repository/python-all/. Note that for use with build tools you must append simple/ to the URL so that the package index is used successfully - https://repo.example.com/repository/python-all/simple/. No further configuration is necessary if your repository manager is configured for anonymous access with Security - Anonymous Access - Access - Allow anonymous users to access the server is activated. If authentication is required, you must use the relevant details such as username and password in your build tool configuration. Direct access The build configuration to retrieve artifacts directly from the Chainguard Libraries for Python repositories requires authentication with username and password from a pull token as detailed in access documentation.
Note that there are multiple repositories:
https://libraries.cgr.dev/python/ with the simple index at https://libraries.cgr.dev/python/simple https://libraries.cgr.dev/python-remediated with the simple index at https://libraries.cgr.dev/python-remediated/simple Configuration for multiple index use and authentication varies for each packaging tool. Typically Python tools include support for .netrc.
See examples using uv and pip under Minimal example projects.
Step 2: Configure your build tools Once you have credentials and the index URL from your organization&rsquo;s repository manager, you&rsquo;re ready to set up specific build tools for local development or CI/CD.
Authentication pip, uv, poetry, and other Python build and packaging tools have dedicated support for configuring authentication to the repository manager or the Chainguard Libraries for Python directly. As an alternative that works across tools and is often preferred, use .netrc for authentication.
pip The pip tool is the most widely used utility for installing Python packages. In this section, we use the credentials from your organization&rsquo;s repository manager to configure pip to ingest dependencies from Chainguard Libraries.
First, clear your local pip cache to ensure that packages are sourced from Chainguard Libraries for Python:
pip cache purge Using a repository manager To update pip to use our repository manager&rsquo;s URL globally, create or edit your ~/.pip/pip.conf file. You may need to create the ~/.pip folder as well. For example:
mkdir -p ~/.pip nano ~/.pip/pip.confUpdate this configuration file with the following, replacing &lt;repository-url&gt; with the URL provided by your repository manager including the simple/ context:
[global] index-url = &lt;repository-url&gt;Updating this global configuration affects all projects built on the workstation. Alternately, if your project uses a requirements.txt file in projects, you can add the following to it to configure on a project-by-project basis:
--index-url &lt;repository-url&gt; package-name==versionNote the different syntax for index-url in the two files.
Refer to the official documentation for configuring authentication with pip if you are not using .netrc for authentication.
Using direct access When using direct access to the Chainguard Libraries for Python repository with pip, you must ensure the following are set in your configuration file:
Replace any / in the username value CG_PULLTOKEN_USERNAME with _. Ensure the simple context is used for the URL. The password value CG_PULLTOKEN_PASSWORD remains unchanged. Example for requirements.txt:
--index-url https://CG_PULLTOKEN_USERNAME:CG_PULLTOKEN_PASSWORD@libraries.cgr.dev/python/simple/Example for ~/.pip/pip.conf:
[global] index-url = https://CG_PULLTOKEN_USERNAME:CG_PULLTOKEN_PASSWORD@libraries.cgr.dev/python/simple/Note that pip supports installing Python libraries from one main repository URL specified with index-url and one or more additional repositories specified with extra-index-url without any specific prioritization beyond resolving semantic versions. The following example uses authentication from a local .netrc file and places the remediated repository first as the primary source, falling back to the standard Chainguard Libraries repository when a remediated version is not available:
--index-url https://libraries.cgr.dev/python-remediated/simple/ --extra-index-url https://libraries.cgr.dev/python/simple/If you are using pip and prefer to pull from multiple repositories while prioritizing Chainguard Libraries for Python, we recommend using a repository manager. Alternatively, other Python package managers, detailed in the following sections, provide support for index priority resolution behavior.
See a demonstration using pip under Minimal example projects.
Poetry Poetry helps you declare, manage, and install dependencies of Python projects, and can be used with Chainguard Libraries for Python.&quot;
List the Python package caches used by your Poetry project:
poetry cache listThe following commands clear the default cache, the cache for a repository named pypi, and the cache of packages of the repo python-all from your repository manager as configured in the global configuration:
poetry cache clear --all _default_cache poetry cache clear --all pypi poetry cache clear --all python-all Using a repository manager Set up HTTP authentication to the repository python-all on your repository manager with the username example and the password secret in your project directory:
poetry config http-basic.python-all example secretThe authentication is used for the python-all repository that you add to the pyproject.toml with the following command:
poetry source add python-all https://repo.example.com/../python-all/simple/Example URLs including the required simple context:
JFrog Artifactory: https://example.jfrog.io/artifactory/api/pypi/python-all/simple/ Sonatype Nexus: https://repo.example.com:8443/repository/python-all/simple/ The following configuration is added:
[[tool.poetry.source]] name = &#34;python-all&#34; url = &#34;https://repo.example.com/../python-all/simple/&#34; priority = &#34;primary&#34;Trigger a new download of the dependencies:
poetry installIf necessary, you can fix or even regenerate your poetry.lock file:
poetry lock poetry lock --regenerateProceed to build your project:
poetry build Using direct access For direct access to Chainguard Libraries for Python with Poetry, use your username CG_PULLTOKEN_USERNAME and password CG_PULLTOKEN_PASSWORD values from the pull token creation and the URL with the simple context https://libraries.cgr.dev/python/simple/:
In order to install Python libraries from multiple repositories with Chainguard Libraries for Python as the priority, poetry supports setting a primary package source. You can use this to configure Chainguard Libraries for Python as the first choice for any library access, remediated packages from Chainguard as another choices and a fallback to the PyPI public index for any missing packages:
poetry config http-basic.chainguard CG_PULLTOKEN_USERNAME CG_PULLTOKEN_PASSWORDThe authentication is used for the chainguard repository that you add to the pyproject.toml with the following command:
poetry source add --priority=primary chainguard https://libraries.cgr.dev/python/simple/Optionally, add the remediated Python libraries as supplemental source:
poetry source add chainguard-remediated https://libraries.cgr.dev/python-remediated/simple/If you require a fallback to PyPI, you can add it as supplemental source:
poetry source add PyPIAlternatively, edit the pyproject.toml file directly:
[[tool.poetry.source]] name = &#34;chainguard&#34; url = &#34;https://libraries.cgr.dev/python-remediated/simple&#34; priority = &#34;primary&#34; [[tool.poetry.source]] name = &#34;chainguard-remediated&#34; url = &#34;https://libraries.cgr.dev/python-remediated/simple&#34; [[tool.poetry.source]] name = &#34;PyPI&#34;The Poetry documentation contains more information about your project build, dependencies, versions, and other aspects.
uv uv is a fast Python package and project manager written in Rust. It uses PyPI by default, but also supports the use of alternative package indexes.
Using a repository manager To update your global configuration to use your organization&rsquo;s repository manager with uv, create or edit the ~/.config/uv/uv.toml configuration file. You may also need to create the ~/.config/uv/ folder first. For example:
mkdir -p ~/.config/uv nano ~/.config/uv/uv.tomlAdd the following to your uv global configuration file:
[[tool.uv.index]] name = &#34;&lt;repository-manager-name&gt;&#34; url = &#34;&lt;repository-url&gt;&#34;Add the name for your repository, such as corppypi, within the quotes.
Replace the &lt;repository-url&gt; with the URL provided by your repository manager including the simple/ context.
Note that updating the global configuration affects all projects built on the workstation. Alternately, you can update each project by adding the same configuration in pyproject.toml.
Refer to the official documentation for configuring authentication with uv and using alternative package indexes if you are not using .netrc for authentication.
Using direct access For direct access to Chainguard Libraries for Python with uv, use .netrc or your username CG_PULLTOKEN_USERNAME and password CG_PULLTOKEN_PASSWORD values from the pull token creation and the URL with the simple context https://libraries.cgr.dev/python/simple/:
Example for pyproject.toml:
[[tool.uv.index]] name = &#34;chainguard&#34; url = &#34;https://CG_PULLTOKEN_USERNAME:CG_PULLTOKEN_PASSWORD@libraries.cgr.dev/python/simple/&#34; default = trueExample for uv.toml:
[[index]] url = &#34;https://CG_PULLTOKEN_USERNAME:CG_PULLTOKEN_PASSWORD@libraries.cgr.dev/python/simple/&#34;See a demonstration using uv under Minimal example projects.
Multiple indexes In order to install Python libraries from multiple repositories with Chainguard Libraries for Python as the priority, uv supports searching across multiple indexes.
You can use this to configure Chainguard Libraries for Python as the first choice for any library access, with a fallback to the PyPI public index. In addition, if you are consuming from our remediated Python libraries index, we recommend setting the index-strategy setting to unsafe-best-match. This ensures that index resolution continues to work when remediated libraries have dependencies on non-remediated libraries.
Example pyproject.toml index setup for direct access to remediated and default packages with netrc-based authentication and lowest priority fallback to PyPI. Note that the order of the entries in the configuration file is significant and determines the order for resolving dependencies:
[[tool.uv.index]] name = &#34;cgr-pr&#34; url = &#34;https://libraries.cgr.dev/python-remediated/simple&#34; authenticate = &#34;always&#34; [[tool.uv.index]] name = &#34;cgr-p&#34; url = &#34;https://libraries.cgr.dev/python/simple&#34; authenticate = &#34;always&#34; [[tool.uv.index]] name = &#34;pypi&#34; url = &#34;https://pypi.org/simple/&#34; default = true # important to treat it as lowest prioritySet the index strategy to allow fallback from the remediated package index to the Chainguard index and even PyPI as final fallback in pyproject.toml:
[tool.uv] index-strategy = &#34;unsafe-best-match&#34;Run a build to observe the resolved packages. For example, the declared dependency to flask version 2.0.0 results in the use of version 2.0.0+cgr.1.
Minimal example projects uv Use the following steps to create a minimal example project for uv with Chainguard Libraries for Python. For testing purposes, you can use direct access and environment variables as detailed in the access documentation.
1. Configure credentials
Once the environment variables are set, configure credentials in ~/.netrc:
cat &gt;&gt; ~/.netrc &lt;&lt; EOF machine libraries.cgr.dev login ${CHAINGUARD_PYTHON_IDENTITY_ID} password ${CHAINGUARD_PYTHON_TOKEN} EOF chmod 600 ~/.netrc Note: The machine libraries.cgr.dev entry is shared across ecosystems. Make sure your entry is using a pull token with Python entitlement.
In this example, the global uv index is set to the Chainguard Python repositories without embedded credentials, allowing uv to authenticate automatically using .netrc.
Create the global index file ~/.config/uv/uv.toml then open it in a text editor such as nano:
mkdir -p ~/.config/uv nano ~/.config/uv/uv.tomlUpdate it to include the remediated and standard Chainguard indexes:
[[index]] url = &#34;https://libraries.cgr.dev/python-remediated/simple/&#34; authenticate = &#34;always&#34; [[index]] url = &#34;https://libraries.cgr.dev/python/simple/&#34; authenticate = &#34;always&#34;2. Initialize a new project
This command creates a new directory, moves to the new directory, then initializes it with uv:
mkdir uv-example &amp;&amp; cd $_ uv init3. Edit pyproject.toml
Open pyproject.toml with a text editor, such as nano:
nano pyproject.tomlAdd flask==2.0.0 to the dependencies list in the [project] section, and add the following index configurations for the Python libraries to the end of the file:
[project] name = &#34;uv-example&#34; version = &#34;0.1.0&#34; requires-python = &#34;&gt;=3.9&#34; dependencies = [ &#34;flask==2.0.0&#34;, ] [tool.uv] index-strategy = &#34;unsafe-best-match&#34; # This allows uv to search across multiple indexes to find remediated versions of Python libraries [[tool.uv.index]] name = &#34;cgr-pr&#34; url = &#34;https://libraries.cgr.dev/python-remediated/simple&#34; authenticate = &#34;always&#34; [[tool.uv.index]] name = &#34;cgr-p&#34; url = &#34;https://libraries.cgr.dev/python/simple&#34; authenticate = &#34;always&#34;4. Build the project
Build the project and sync dependencies:
uv syncFollowing this, confirm the patched Chainguard version of flask was resolved:
uv pip list | grep flaskThe output should show flask 2.0.0+cgr.1, confirming the remediated version was installed.
Verify the project works as expected To verify the installed packages were built by Chainguard, use chainctl:
chainctl libraries verify --detailed .venv/A successfully verified project produces output similar to the following:
- flask Status: Verified as built from source Details: Version: 2.0.0&#43;cgr.1 (verified via per-package SBOM - built from source by Chainguard) Python package: flask==2.0.0&#43;cgr.1
pip Use the following steps to create a minimal example project for pip with Chainguard Libraries for Python. For testing purposes, you can use direct access and environment variables as detailed in the access documentation.
1. Update your configuration to point to Chainguard
Once the environment variables are set, update ~/.pip/pip.conf to point to Chainguard Libraries.
You may need to create the ~/.pip directory first:
mkdir -p ~/.pip nano ~/.pip/pip.confIn ~/.pip/pip.conf, add the following:
[global] index-url = https://CHAINGUARD_PYTHON_IDENTITY_ID:CHAINGUARD_PYTHON_TOKEN@libraries.cgr.dev/python/simple/ Note: Replace any / in your CHAINGUARD_PYTHON_IDENTITY_ID&rsquo;s value with _ in the URL. The password value remains unchanged.
2. Create a virtual environment
Create a new directory, navigate to it, and create and activate a virtual environment:
mkdir pip-example &amp;&amp; cd $_ python3 -m venv .venv source .venv/bin/activate3. Add and install dependencies
Create a requirements.txt file:
nano requirements.txtIn the requirements.txt file, add the following:
flask==2.0.0Run the following command to install the dependencies:
pip install -r requirements.txt Verify the project works as expected To verify the installed packages were built by Chainguard, use chainctl:
chainctl libraries verify --detailed .venv/A successfully verified project produces output similar to the following:
Artifact: .venv/ Verification Coverage: 55.56% Verified packages: 5 of 9 ... - flask Status: Verified as built from source Details: Version: 2.0.0 (verified via per-package SBOM - built from source by Chainguard) Python package: flask==2.0.0Adjust the index URL to use your repository manager and add any other desired packages for further testing.

