Time to fight your company's authentication system. This shit breaks constantly, usually at 3am during deployments when nobody from IT is awake to help.
Private PyPI Repository Setup
Your company probably runs Nexus, Artifactory, or GitLab Package Registry. Here's how to point uv at whatever overly complicated setup IT created:
## pyproject.toml
[tool.uv.pip]
extra-index-url = ["https://pypi.company.com/simple/"]
trusted-host = ["pypi.company.com"]
[tool.uv.sources]
company-lib = { index = "company-pypi" }
[[tool.uv.index]]
name = "company-pypi"
url = "https://pypi.company.com/simple/"
explicit = true # Only use for specifically marked packages
That explicit = true
line is crucial - without it, uv will spam your private repo asking for requests
and numpy
like an idiot. Our Jenkins builds started randomly shitting themselves because uv was making 500+ requests to Nexus for packages that obviously aren't there. IT was not pleased.
AWS CodeArtifact Integration
AWS CodeArtifact tokens expire every 12 hours, which guarantees your weekend deploy will fail. Here's how to make this work (until AWS decides to change the auth flow again):
## Generate auth token (expires in 12 hours)
export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
--domain my-domain --domain-owner 123456789012 \
--query authorizationToken --output text)
## Configure uv to use the token
export UV_EXTRA_INDEX_URL="https://aws:${CODEARTIFACT_AUTH_TOKEN}@my-domain-123456789012.d.codeartifact.us-east-1.amazonaws.com/pypi/my-repo/simple/"
For CI/CD environments, this integrates with IAM roles and doesn't require hardcoded credentials.
Azure DevOps Artifacts Authentication
Azure Artifacts requires personal access tokens (PATs) or Azure AD authentication:
## Using PAT authentication
export UV_EXTRA_INDEX_URL="https://username:${AZURE_DEVOPS_PAT}@pkgs.dev.azure.com/organization/_packaging/feed/pypi/simple/"
## Or using Azure CLI token
az artifacts universal download \
--organization https://dev.azure.com/myorg \
--feed myfeed \
--name mypackage \
--version 1.0.0 \
--path .
GitLab Package Registry Integration
GitLab's built-in PyPI registry works well with uv through deploy tokens or CI/CD job tokens:
## For GitLab private packages
[[tool.uv.index]]
name = "gitlab"
url = "https://__token__:${CI_JOB_TOKEN}@gitlab.company.com/api/v4/projects/PROJECT_ID/packages/pypi/simple"
explicit = true
Security Best Practices for Enterprise
Never hardcode credentials in pyproject.toml. Use environment variables or external credential management:
- Keyring integration: uv supports system keyrings through
UV_KEYRING_PROVIDER=subprocess
- Docker secrets: Mount credentials as files rather than environment variables
- CI/CD secrets: Use GitHub Actions secrets, GitLab CI variables, or Jenkins credentials
Network security considerations:
## Corporate proxy support
export UV_HTTP_PROXY="http://proxy.company.com:8080"
export UV_HTTPS_PROXY="http://proxy.company.com:8080"
export UV_NO_PROXY="localhost,127.0.0.1,.company.com"
## Custom CA certificates
export UV_CERT_BUNDLE="/etc/ssl/certs/company-ca.pem"
export REQUESTS_CA_BUNDLE="/etc/ssl/certs/company-ca.pem"
Multi-Repository Configuration
Large organizations often have multiple private repositories. uv handles this through index priority and explicit sourcing:
[tool.uv.pip]
index-url = "https://pypi.org/simple/" # Default for public packages
extra-index-url = [
"https://ml-packages.company.com/simple/", # ML team packages
"https://backend-packages.company.com/simple/", # Backend team packages
]
## Explicit package routing prevents conflicts
[tool.uv.sources]
ml-models = { index = "ml-packages" }
api-client = { index = "backend-packages" }
[[tool.uv.index]]
name = "ml-packages"
url = "https://ml-packages.company.com/simple/"
explicit = true
[[tool.uv.index]]
name = "backend-packages"
url = "https://backend-packages.company.com/simple/"
explicit = true
Authentication Troubleshooting (aka 90% of Your Time)
Real authentication failures that will ruin your day:
- 401 Unauthorized: Token expired 5 minutes ago, or IT rotated keys without telling anyone
- SSL Certificate errors: Corporate proxy injects its own cert, breaking everything
- 403 Forbidden: Your service account lost permissions overnight for no reason
- Network timeouts: Corporate network is slower than dial-up on Mondays
CERTIFICATE_VERIFY_FAILED
: The classic - your proxy hates Python
## Debug authentication issues (prepare for spam)
UV_VERBOSE=1 uv pip install your-private-package
## Test if your private index is reachable
## Use curl to test connectivity to your private index
curl -I https://pypi.org/simple/
## Nuclear option: disable SSL verification (don't do this in prod)
export PYTHONHTTPSVERIFY=0
Keep pip installed as backup - when uv craps out on auth, pip usually still works for some reason.
uv 0.8.17 finally shows actual HTTP status codes instead of the useless "connection failed" bullshit from 0.7.x. But SSL: CERTIFICATE_VERIFY_FAILED
errors are still garbage - it won't tell you which cert is fucked, so good luck debugging that.