OpenShift Custom CA for Private Registries
Configure OpenShift to trust a custom Certificate Authority for private container registries using additionalTrustedCA and image.config.openshift.io settings.
π‘ Quick Answer: Create a ConfigMap with your CA cert keyed by the registry hostname, then patch
image.config.openshift.io/clusterto reference it viaadditionalTrustedCA.
The Problem
Your private Quay registry uses a self-signed certificate or an internal CA that OpenShift nodes donβt trust. Image pulls fail with:
x509: certificate signed by unknown authorityEven with correct pull secret credentials, nodes canβt establish TLS connections to the registry. You need to distribute your CA certificate to all nodes cluster-wide.
The Solution
Step 1: Create the CA ConfigMap
The ConfigMap key must be the registry hostname (with port if non-standard):
# For a registry on the default HTTPS port (443)
oc create configmap registry-ca \
--from-file=quay.internal.example.com=/path/to/ca-bundle.crt \
-n openshift-configFor a registry on a custom port:
# Key must include the port
oc create configmap registry-ca \
--from-file=quay.internal.example.com..8443=/path/to/ca-bundle.crt \
-n openshift-configβ οΈ Note: Dots in the port separator must be
..(double dot) because ConfigMap keys canβt contain colons. OpenShift interpretshostname..portashostname:port.
Step 2: Patch the Cluster Image Configuration
oc patch image.config.openshift.io/cluster --type=merge \
-p '{"spec":{"additionalTrustedCA":{"name":"registry-ca"}}}'Step 3: Wait for the Machine Config Operator Rollout
The MCO distributes the CA to all nodes. Monitor the rollout:
# Watch MachineConfigPools
oc get machineconfigpool -w
# Wait for all pools to finish updating
oc wait machineconfigpool --all \
--for=condition=Updated=True \
--timeout=600sStep 4: Verify the CA is Trusted
# Test from a debug pod on a node
oc debug node/<node-name> -- chroot /host \
curl -s --cacert /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem \
https://quay.internal.example.com/v2/ -o /dev/null -w "%{http_code}"
# Expected: 200 or 401 (auth required, but TLS works)Step 5: Test Image Pull
# Test with a pod
oc run test-pull \
--image=quay.internal.example.com/myorg/test-image:latest \
--restart=Never
# Verify it pulled successfully
oc get pod test-pull -o jsonpath='{.status.phase}'
# Expected: Running or Succeeded
# Clean up
oc delete pod test-pullMultiple Registries
Add multiple CAs to the same ConfigMap:
oc create configmap registry-ca \
--from-file=quay.internal.example.com=/path/to/quay-ca.crt \
--from-file=harbor.internal.example.com=/path/to/harbor-ca.crt \
--from-file=registry.internal.example.com..5000=/path/to/registry-ca.crt \
-n openshift-config \
--dry-run=client -o yaml | oc apply -f -flowchart TD
A[CA Certificate File] -->|oc create configmap| B[ConfigMap: registry-ca<br/>openshift-config namespace]
B -->|image.config.openshift.io| C[Cluster Image Config]
C -->|MCO distributes| D[All Nodes<br/>CA added to trust store]
D -->|TLS verified| E[Private Registry<br/>quay.internal.example.com]
E -->|Image pulled| F[Running Pods]Common Issues
x509 Still Failing After ConfigMap Update
- Wait for MCO rollout β check
oc get mcpshowsUPDATED=True - Verify the key name matches the registry hostname exactly
- Check the CA file β must be PEM format, not DER
ConfigMap Key Format for Non-Standard Ports
# β Wrong β colons not allowed in ConfigMap keys
--from-file=quay.example.com:8443=ca.crt
# β
Correct β use double dots
--from-file=quay.example.com..8443=ca.crtCA Chain Issues
If your registry cert is signed by an intermediate CA, include the full chain:
# Concatenate intermediate + root CA
cat intermediate-ca.crt root-ca.crt > ca-bundle.crt
oc create configmap registry-ca \
--from-file=quay.internal.example.com=ca-bundle.crt \
-n openshift-configBest Practices
- Use a CA bundle β include the full chain from leaf to root
- One ConfigMap for all registries β keep all CAs in the same ConfigMap referenced by
additionalTrustedCA - Test with
oc debug nodeβ verify TLS from the node perspective, not just from your workstation - Combine with pull secret β CA trust enables TLS; pull secrets handle authentication
- Document your CAs β track which certificates are in the ConfigMap and when they expire
Key Takeaways
- Use
additionalTrustedCAonimage.config.openshift.io/clusterfor cluster-wide registry CA distribution - ConfigMap keys must match registry hostnames exactly (use
..for port separators) - MCO rollout takes several minutes β monitor
machineconfigpoolstatus - Always combine CA trust with pull secret credentials for private registries

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
