|
| 1 | +--- |
| 2 | +layout: src/layouts/Default.astro |
| 3 | +pubDate: 2026-06-16 |
| 4 | +modDate: 2026-06-16 |
| 5 | +title: Python feeds |
| 6 | +description: Configuring PyPI repositories as Octopus Feeds |
| 7 | +navOrder: 52 |
| 8 | +--- |
| 9 | + |
| 10 | +:::div{.success} |
| 11 | +Python feeds are supported from version **Octopus 2026.2.9957**. |
| 12 | +::: |
| 13 | + |
| 14 | +Python repositories can be configured as an external feed in Octopus Deploy, allowing you to consume packages from pypi.org or private PyPI-compatible registries such as Nexus Repository Manager, JFrog Artifactory, Azure Artifacts, and AWS CodeArtifact. |
| 15 | + |
| 16 | +Octopus communicates with the feed using the [PyPI Simple repository API](https://peps.python.org/pep-0503/). Both the JSON Simple API ([PEP 691](https://peps.python.org/pep-0691/)) and the legacy HTML Simple API ([PEP 503](https://peps.python.org/pep-0503/)) are supported, with the JSON API preferred when the registry offers it. |
| 17 | + |
| 18 | +## Adding an external Python feed |
| 19 | + |
| 20 | +The following steps can be followed to add an external Python feed. |
| 21 | + |
| 22 | +1. Navigate to **Deploy ➜ Manage ➜ External Feeds** and click the **ADD FEED** button. |
| 23 | +2. Select **PyPI Feed** from the **Feed Type** field. |
| 24 | +3. Enter a descriptive name for the feed in the **Feed name** field. |
| 25 | +4. In the **Feed URL** field, enter the URL of the PyPI Simple index ([PEP 503](https://peps.python.org/pep-0503/)). Common examples include: |
| 26 | + - Public PyPI registry: `https://pypi.org/simple/` |
| 27 | + - Nexus Repository Manager: `https://your-nexus-server/repository/pypi-hosted/simple/` |
| 28 | + - JFrog Artifactory: `https://your-artifactory-server/artifactory/api/pypi/pypi-repo/simple/` |
| 29 | +5. Under **Credentials**, choose the authentication type required by your registry (see [Authentication](#authentication) below). |
| 30 | +6. The **Download attempts** field defines the number of times that Octopus will attempt to download a package from the registry. Failed attempts will wait for the number of seconds defined in the **Download retry backoff** field before attempting to download the package again. |
| 31 | +7. Click **Save and test** to verify the feed configuration. |
| 32 | + |
| 33 | +## Authentication |
| 34 | + |
| 35 | +Under **Credentials**, Python feeds support three authentication types: |
| 36 | + |
| 37 | +### Anonymous access |
| 38 | + |
| 39 | +For public registries like pypi.org, authentication is optional. Select **Anonymous Access** to access public packages without credentials. |
| 40 | + |
| 41 | +### Username and password |
| 42 | + |
| 43 | +Select **Username and Password** to authenticate using basic credentials, entering them in the **Feed Username** and **Feed Password** fields. This is the common choice for registries such as Nexus Repository Manager and JFrog Artifactory. |
| 44 | + |
| 45 | +### Token |
| 46 | + |
| 47 | +Select **Token** when your registry uses an API token. This shows a single **Personal Access Token** field — paste the token (including the `pypi-` prefix, where present) into it; no username is required. |
| 48 | + |
| 49 | +Behind the scenes, Octopus authenticates using the standard Python convention of `__token__` as the username with your token as the password. |
| 50 | + |
| 51 | +## Referencing Python packages |
| 52 | + |
| 53 | +When referencing a Python package in Octopus Deploy, use the package name as it appears in the registry. PyPI package names are case-insensitive and treat `-`, `_`, and `.` as equivalent (see [PEP 503 name normalization](https://peps.python.org/pep-0503/#normalized-names)). |
| 54 | + |
| 55 | +Examples: |
| 56 | + |
| 57 | +- `requests` |
| 58 | +- `azure-storage-blob` |
| 59 | +- `Flask` |
| 60 | + |
| 61 | +Octopus prefers built distributions (wheels, `.whl`) when available, falling back to source distributions (`.tar.gz` or `.zip`). |
| 62 | + |
| 63 | +## Versioning with Python feeds |
| 64 | + |
| 65 | +Python packages use [PEP 440](https://peps.python.org/pep-0440/) version identifiers, which Octopus interprets as semantic versions. |
| 66 | + |
| 67 | +Pre-release versions are supported, following the PEP 440 specification: |
| 68 | + |
| 69 | +- `1.0.0a1` (alpha) |
| 70 | +- `1.0.0b2` (beta) |
| 71 | +- `1.0.0rc1` (release candidate) |
| 72 | +- `1.0.0.dev1` (development release) |
| 73 | + |
| 74 | +When selecting the latest version for a package, you can order by the most recently published version. For pypi.org, publish dates are retrieved from the [PyPI JSON API](https://docs.pypi.org/api/json/). For registries that don't expose this API, Octopus falls back to ordering by version number. |
| 75 | + |
| 76 | +## Testing a Python feed |
| 77 | + |
| 78 | +After adding a Python feed, you can verify it's working correctly: |
| 79 | + |
| 80 | +1. Click the **TEST** button on the feed configuration page. |
| 81 | +2. Search for a known package in your registry. |
| 82 | +3. Verify that the matching packages are listed. |
| 83 | + |
| 84 | +:::div{.hint} |
| 85 | +The feed test lists matching package names only. Version information isn't shown in the test results. |
| 86 | +::: |
| 87 | + |
| 88 | +## Troubleshooting Python feeds |
| 89 | + |
| 90 | +### Connection issues |
| 91 | + |
| 92 | +If you cannot connect to your registry: |
| 93 | + |
| 94 | +1. Verify the feed URL is correct and points at the Simple index (typically ending in `/simple/`), and that it is accessible from the Octopus Server. |
| 95 | +2. Check that authentication credentials are valid. |
| 96 | +3. Ensure any required network access (firewall rules, proxy settings) is configured. |
| 97 | +4. For Nexus or Artifactory, verify the repository is online and the repository path is correct. |
| 98 | + |
| 99 | +### Authentication failures |
| 100 | + |
| 101 | +If authentication is failing: |
| 102 | + |
| 103 | +1. Confirm your credentials or API token haven't expired. |
| 104 | +2. When using a token, ensure you selected the **Token** authentication type and pasted the full token into the **Personal Access Token** field. |
| 105 | +3. For Artifactory, ensure your API key or access token has the necessary permissions. |
| 106 | +4. Test authentication using `pip` with the same credentials and index URL: |
| 107 | + |
| 108 | +```bash |
| 109 | +pip install --index-url https://<username>:<password>@your-registry-url/simple/ package-name |
| 110 | +``` |
| 111 | + |
| 112 | +### Package not found |
| 113 | + |
| 114 | +If a package cannot be found: |
| 115 | + |
| 116 | +1. Verify the package name is spelled correctly. Remember that PyPI names are case-insensitive and treat `-`, `_`, and `.` as equivalent. |
| 117 | +2. Confirm the package exists in the registry and isn't private (if you're using anonymous access). |
| 118 | +3. Confirm the registry exposes the package on its Simple index. |
0 commit comments