Skip to content
Latchkey

RubyGems "certificate verify failed" in CI - Fix the Trust Store

RubyGems could not verify the TLS certificate of the gem source. Either the runner is missing CA certificates, or a proxy is presenting its own certificate the runner does not trust. Unlike a transient SSL_connect blip, this fails the same way every time.

What this error means

gem install or bundle install fails during the TLS handshake with "certificate verify failed" and "unable to get local issuer certificate". It is deterministic and environment-specific - it passes on a developer machine but fails on a bare CI image.

gem output
Gem::RemoteFetcher::FetchError: SSL_connect returned=1 errno=0 state=error:
certificate verify failed (unable to get local issuer certificate)
(https://rubygems.org/specs.4.8.gz)

Common causes

Missing or stale CA certificates on the runner

A minimal image may not ship ca-certificates, so OpenSSL has no trust store to validate the source certificate against. Every verification then fails.

A proxy doing TLS interception

Corporate proxies re-sign HTTPS with their own root CA. Unless that root is in the runner trust store, RubyGems rejects the substituted certificate.

How to fix it

Install CA certificates

Terminal
# Debian/Ubuntu
apt-get update && apt-get install -y ca-certificates
update-ca-certificates
# Alpine
apk add --no-cache ca-certificates

Trust the proxy root CA

When a proxy intercepts TLS, add its root to the system trust store rather than disabling verification.

Terminal
cp corporate-root.pem /usr/local/share/ca-certificates/
update-ca-certificates
export SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt

How to prevent it

  • Use a runner image with ca-certificates preinstalled.
  • Add the corporate root CA to the trust store, not per-command overrides.
  • Keep the runner clock in sync so valid certificates are not rejected.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →