Set index-url in pip's global configuration file for a baseline, repeat it in CI through a config file or environment variable, and accept that a developer can still override it with a command line flag. Pip applies options in a fixed order, so know which layer wins.
The layers
According to the pip documentation, there are three config file levels: global, user and site. They load in that order, then PIP_CONFIG_FILE if set, and later files override earlier values. Environment variables and command line options sit above all files.
Highest priority first:
- Command line options
- Environment variables, named
PIP_plus the option name in capitals with underscores - Config files, where a command specific section such as
[install]beats[global]
File locations
| Platform | Global | User |
|---|---|---|
| Linux | /etc/pip.conf (also under XDG_CONFIG_DIRS) | $HOME/.config/pip/pip.conf |
| macOS | /Library/Application Support/pip/pip.conf | $HOME/Library/Application Support/pip/pip.conf |
| Windows | C:\ProgramData\pip\pip.ini | %APPDATA%\pip\pip.ini |
Site config sits in the virtual environment, as pip.conf or pip.ini, or at the Python installation root when no environment is active.
A minimal global file looks like this.
[global]
index-url = https://pypi.internal.example/simple
The key name matches the long option name without the leading dashes.
What can defeat your setting
- A user running
pip install --index-url ...overrides every file. PIP_INDEX_URLin the environment overrides files.PIP_CONFIG_FILEloads last and wins over other files. The docs also say that setting it to the null device disables all config loading, and that if a file exists at the path it names, the user config file is skipped.- A virtual environment with its own site file changes behaviour for that environment.
So a global file is a default, not a lock. Real enforcement comes from the network: block direct access to the public index from build hosts, so a developer who skips the setting gets an error rather than a quiet bypass.
Do not combine indexes carelessly
--extra-index-url adds more indexes, and pip does not rank them. It picks the best version match across all of them, so a public package can beat your private one. The pip docs call using it for packages not in the main repository unsafe because of dependency confusion. Point index-url at one internal index that proxies the public one, instead of adding extras.
Rollout steps
- Stand up the internal index and test it with a few projects.
- Push the global file through device management and bake it into CI images.
- Add
PIP_INDEX_URLin CI as a second layer. - Block the public index at the build network edge.
- Check the index access log for clients that still bypass it.
Try it yourself
Click through it at your own pace, or open it full screen.
Open the inventory and look at where each package came from. Source matters as much as version.
Safeguard's SBOM and dependency scanning can show where your dependencies come from, with a free scan at gold.safeguard.sh/scan.
Quick check
Does a global pip.conf stop a developer using another index?
No. Command line options and environment variables outrank config files, so back it with network controls.
Which wins, PIP_INDEX_URL or pip.conf?
The environment variable. The docs rank command line, then environment, then config files.
Sources
Last reviewed: 19 October 2026.