When you pip install from an internal package repository that uses self-signed SSL certificates, you often run into SSLError complaints. This happens because Python’s ssl module, which pip relies on, doesn’t trust your internal server’s certificate by default.

Here’s how to tell pip to trust your internal server, even with a dodgy certificate:

1. The "Just Trust It" Approach: trusted-host

The simplest way is to tell pip to ignore SSL certificate validation for a specific host.

Diagnosis: You’ll see an error like this when trying to install from your internal repo:

SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)

Cause: Your internal server is presenting a certificate that isn’t signed by a publicly recognized Certificate Authority (CA), and pip doesn’t have it in its trust store.

Fix: Use the --trusted-host flag with pip install.

pip install --trusted-host your-internal-repo.example.com your-package

Why it works: This flag tells the underlying urllib3 library (which pip uses for HTTP requests) to skip the certificate verification step only for the specified host. It doesn’t disable SSL entirely, just the trust check.

Example: If your internal repository is at pypi.internal.company.com:8080, you’d run:

pip install --trusted-host pypi.internal.company.com:8080 my-internal-package

Important Note: This is generally less secure because it bypasses a crucial security check. Use it only for internal networks where you have a high degree of trust in the network and the server itself.

2. The "Here’s the Real CA" Approach: --cert

If you have the Certificate Authority (CA) certificate that signed your internal server’s certificate, you can tell pip to trust that CA.

Diagnosis: Same SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] as above.

Cause: Your internal server’s certificate is signed by a CA that pip (and Python’s ssl module) doesn’t recognize.

Fix: Download the CA certificate file (usually a .pem file) and point pip to it using the --cert flag.

pip install --cert /path/to/your/internal_ca.pem your-package

Why it works: This flag tells pip to use the specified file as the root of trust for SSL connections. It will now trust any certificate signed by the CA contained in internal_ca.pem.

Example: If your CA certificate is company_root_ca.crt located in /etc/ssl/certs/, and your internal repo is pypi.internal.company.com:

pip install --cert /etc/ssl/certs/company_root_ca.crt my-internal-package

3. The "Trust This CA Globally" Approach: PIP_CERT Environment Variable

Instead of passing --cert every time, you can set an environment variable.

Diagnosis: Again, the familiar SSL error: [SSL: CERTIFICATE_VERIFY_FAILED].

Cause: The system’s default CA store doesn’t include the CA that signed your internal server’s certificate.

Fix: Set the PIP_CERT environment variable to the path of your CA certificate file.

export PIP_CERT=/path/to/your/internal_ca.pem
pip install your-package

Why it works: pip checks for the PIP_CERT environment variable. If found, it uses that certificate file for SSL verification, similar to the --cert flag. This makes the setting persistent for your current shell session.

Example:

export PIP_CERT=/etc/ssl/certs/company_root_ca.crt
pip install --index-url https://pypi.internal.company.com/simple/ my-internal-package

4. The "Trust This CA System-Wide" Approach: System Certificate Store

The most robust solution is to add your internal CA certificate to your operating system’s trusted CA store. How you do this depends on your OS.

Diagnosis: The SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] persists.

Cause: The operating system’s default trust store lacks the root CA certificate for your internal repository.

Fix:

  • Debian/Ubuntu:
    1. Copy your CA cert to /usr/local/share/ca-certificates/.
    2. Run sudo update-ca-certificates.
  • RHEL/CentOS/Fedora:
    1. Copy your CA cert to /etc/pki/ca-trust/source/anchors/.
    2. Run sudo update-ca-trust extract.
  • macOS:
    1. Open "Keychain Access".
    2. Drag your .pem file into the "System" keychain.
    3. Find the imported certificate, double-click it, and expand the "Trust" section.
    4. Set "When using this certificate" to "Always Trust".
  • Windows:
    1. Open "Manage computer certificates" (certlm.msc).
    2. Navigate to "Trusted Root Certification Authorities" -> "Certificates".
    3. Right-click "Certificates" and select "All Tasks" -> "Import…".
    4. Follow the wizard, choosing the "Local Machine" store and placing it in the "Trusted Root Certification Authorities" store.

Why it works: Once added to the system’s trust store, all applications (including Python and pip) that consult the system’s trust store will automatically trust certificates signed by that CA.

5. The "Combine Trusted Host and Cert" Approach

Sometimes, you need to specify both the host and a custom certificate.

Diagnosis: You still get SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] even after trying --trusted-host.

Cause: --trusted-host alone bypasses verification. If you also want to specify which certificate to trust (e.g., a specific server cert, not just a CA), you might need to combine it with --cert. However, usually, --trusted-host is sufficient for bypassing validation errors. This scenario is less common for simple internal repos.

Fix:

pip install --trusted-host your-internal-repo.example.com --cert /path/to/your/internal_ca.pem your-package

Why it works: This explicitly tells pip to trust your-internal-repo.example.com and to use /path/to/your/internal_ca.pem as the certificate authority for validation. The --trusted-host here ensures that even if the CA isn’t fully trusted by the system, the connection to that specific host proceeds.

You can technically disable SSL entirely for a host, but this is highly insecure and rarely the right solution.

Diagnosis: Any SSL-related errors, including handshake failures.

Cause: The server might be misconfigured for SSL, or you want to connect over plain HTTP (again, not recommended for any sensitive data).

Fix: Use the --trusted-host flag and ensure your index URL uses http:// instead of https://.

pip install --trusted-host your-internal-repo.example.com --index-url http://your-internal-repo.example.com/simple/ your-package

Why it works: By switching to http://, you’re telling pip to make a plain HTTP request, bypassing the SSL layer entirely. The --trusted-host is still useful here as a general directive, though it’s less critical when SSL is off.

Example:

pip install --trusted-host pypi.internal.company.com --index-url http://pypi.internal.company.com:8080/simple/ my-internal-package

Security Warning: Never do this over an untrusted network or for sensitive packages.


After successfully configuring your pip to trust your internal repository, the next hurdle you’ll likely encounter is dealing with dependency resolution issues or version conflicts within your internal package ecosystem.

Want structured learning?

Take the full Pip course →