Ansible Error Guide: 'certificate verify failed' ansible-galaxy x509 TLS Error
Fix ansible-galaxy's 'SSL: CERTIFICATE_VERIFY_FAILED' x509 error: diagnose missing CA bundles, proxies, expired certs, and self-signed Galaxy/Automation Hub endpoints.
- #ansible
- #troubleshooting
- #errors
- #galaxy
Exact Error Message
ERROR! Unknown error when attempting to call Galaxy server 'default'.
HTTPSConnectionPool(host='galaxy.ansible.com', port=443): Max retries exceeded with url: /api/
(Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed:
unable to get local issuer certificate (_ssl.c:1006)')))
You may also see the variants certificate has expired, self-signed certificate in certificate chain, or hostname mismatch, all under the same CERTIFICATE_VERIFY_FAILED header.
What the Error Means
When ansible-galaxy installs a role or collection, it makes an HTTPS request to a Galaxy server (the public galaxy.ansible.com, a private Automation Hub, or a pull-through proxy). Python’s TLS stack validates the server’s x509 certificate against a trusted CA bundle. If it cannot build a trust chain to a known root, the certificate is expired, or the hostname does not match, validation fails and the request is aborted before any collection is downloaded.
This is a TLS trust problem on the control node, not a problem with the collection itself.
Common Causes
- The control node’s CA bundle is missing or outdated, so the issuing CA is unknown (
unable to get local issuer certificate). - A corporate TLS-inspecting proxy re-signs traffic with an internal CA that is not in the system trust store (
self-signed certificate in certificate chain). - A private Automation Hub or internal Galaxy mirror uses a self-signed or internally issued certificate.
- The server certificate genuinely expired (
certificate has expired). requests/certifiis using its own bundled CA store that differs from the OS store.- The endpoint URL uses an IP or alternate name not present in the certificate’s SAN (
hostname mismatch).
How to Reproduce the Error
Install a collection from behind a TLS-inspecting proxy without trusting its CA:
ansible-galaxy collection install community.general -vvv
ERROR! Unknown error when attempting to call Galaxy server 'default'.
... SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed:
self-signed certificate in certificate chain (_ssl.c:1006)'))
Or target a private hub with an internal cert:
ansible-galaxy collection install mycorp.platform -s https://hub.internal/api/galaxy/ -vvv
Diagnostic Commands
Inspect the exact certificate the server is presenting and whether it verifies:
openssl s_client -connect galaxy.ansible.com:443 -servername galaxy.ansible.com </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject -dates
Find which CA bundle Python is using:
python3 -c "import ssl; print(ssl.get_default_verify_paths())"
python3 -c "import certifi; print(certifi.where())"
Confirm whether a proxy is in play (it usually is, when you see a self-signed chain):
env | grep -i proxy
Test the raw HTTPS handshake the way Galaxy would:
curl -v https://galaxy.ansible.com/api/ 2>&1 | grep -iE "issuer|verify|SSL"
Step-by-Step Resolution
-
Read the specific reason.
unable to get local issuer certificateandself-signed certificate in certificate chainare trust-store problems.certificate has expiredis the server’s fault.hostname mismatchis a SAN problem. -
Update the system CA bundle if the issuer is simply unknown:
sudo update-ca-certificates # Debian/Ubuntu
sudo update-ca-trust # RHEL/Fedora
- Trust a corporate or internal CA. Get the proxy/hub root CA PEM and install it:
sudo cp corp-root-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
- Point ansible-galaxy at a specific CA bundle if you cannot modify the system store. Set
GALAXY_IGNORE_CERTS=Falseand reference the bundle via the environment Python uses:
REQUESTS_CA_BUNDLE=/etc/ssl/certs/corp-bundle.pem ansible-galaxy collection install community.general
- Fix
certifidrift. If Python uses a stalecertifistore, update it:
pip install --upgrade certifi
-
For an expired or mismatched server cert, fix the server. Renew the certificate or correct its SAN; do not work around it on every client.
-
As a last resort for trusted internal mirrors only, you can ignore verification for one command. Treat this as a temporary, deliberate exception:
ansible-galaxy collection install mycorp.platform -s https://hub.internal/api/galaxy/ --ignore-certs
Prevention and Best Practices
- Distribute your corporate/proxy root CA to every control node and CI runner through configuration management so the trust store is always complete.
- Keep
ca-certificatesandcertifipatched; expired or removed roots cause sudden, confusing failures. - Pin the CA bundle explicitly in CI with
REQUESTS_CA_BUNDLEso builds do not depend on whatever store the base image ships. - Monitor certificate expiry on private Automation Hub endpoints and renew ahead of time.
- Avoid
--ignore-certsin pipelines; it disables a real protection and tends to become permanent. - Configure Galaxy servers explicitly in
ansible.cfgso you know exactly which endpoint and trust settings apply.
Related Errors
Failed to import the required Python library— a different dependency problem, not TLS.Max retries exceeded ... Connection refused— the endpoint is unreachable, not untrusted.HTTP Error 401/403from Galaxy — authentication/token issue, not certificate validation.tlsv1 alert protocol version— a TLS version mismatch rather than a trust-chain failure.
Frequently Asked Questions
Why does curl work but ansible-galaxy fails? curl may use the OS trust store while Python’s requests/certifi uses its own bundle. Update certifi or set REQUESTS_CA_BUNDLE to align them.
We are behind a TLS-inspecting proxy. What is the right fix? Install the proxy’s root CA into the system trust store with update-ca-certificates / update-ca-trust, or point REQUESTS_CA_BUNDLE at a bundle that includes it. The proxy re-signs traffic, so its CA must be trusted.
Is --ignore-certs safe? Only for a trusted internal mirror on a controlled network, and ideally only temporarily. It disables certificate verification entirely, which removes MITM protection.
The server cert expired — can I fix it client-side? No. Renew the server certificate. Working around expiry on every client is fragile and insecure. For more dependency and supply-chain patterns, see the Ansible guides.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.