OpenShift and OKD 4.x enforce TLS verification on all container image pulls by default. In production, this is exactly what you want – every registry should serve images over HTTPS with valid certificates. But in development, lab, and air-gapped environments, you often run internal registries with self-signed certificates or no TLS at all. Configuring insecure registries lets your cluster pull images from these sources without certificate errors.
This guide covers multiple methods to allow insecure registries in OpenShift 4.x and OKD 4.x clusters – from quick oc patch commands to the production-recommended approach of adding CA certificates. We also cover mirror registry configuration and troubleshooting common image pull failures. All commands are tested on OpenShift 4.14+ and apply to any OpenShift Container Platform 4.x release.
Prerequisites
- A running OpenShift 4.x or OKD 4.x cluster
- The
ocCLI installed and authenticated as acluster-adminuser - Access to the internal registry you want to configure (know the hostname/IP and port)
- If adding CA certificates – the registry’s CA certificate file in PEM format
Step 1: Check Current Image Configuration
Before making changes, review the current cluster-wide image configuration. OpenShift stores registry settings in the image.config.openshift.io/cluster resource.
oc get image.config.openshift.io/cluster -o yaml
On a default cluster with no custom registry configuration, the output shows an empty spec:
apiVersion: config.openshift.io/v1
kind: Image
metadata:
name: cluster
spec: {}
status:
internalRegistryHostname: image-registry.openshift-image-registry.svc:5000
The spec section is where you define insecure registries, allowed/blocked registries, and additional CA certificates. The status.internalRegistryHostname shows the cluster’s built-in registry address.
Step 2: Add Insecure Registry with oc patch
The fastest way to allow an insecure registry is using oc patch. This method works well when you need to add one or two registries quickly. Replace registry.lab.example.com:5000 with your actual registry address.
oc patch image.config.openshift.io/cluster --type=merge -p '{"spec":{"registrySources":{"insecureRegistries":["registry.lab.example.com:5000"]}}}'
The command returns a confirmation that the resource was patched:
image.config.openshift.io/cluster patched
To add multiple insecure registries in a single patch, list them all in the array:
oc patch image.config.openshift.io/cluster --type=merge -p '{"spec":{"registrySources":{"insecureRegistries":["registry.lab.example.com:5000","192.168.1.50:8443","harbor.dev.local"]}}}'
After patching, the Machine Config Operator (MCO) rolls out the change to all nodes. This triggers a rolling reboot of worker and master nodes, so plan accordingly in shared environments.
Step 3: Add Insecure Registry via YAML Edit
For more control over the configuration, edit the image config resource directly. This approach is better when you need to set multiple options at once – insecure registries, allowed registries, and blocked registries all in one edit.
oc edit image.config.openshift.io/cluster
Add or update the spec section with your insecure registries. Here is an example configuration with multiple registry settings:
apiVersion: config.openshift.io/v1
kind: Image
metadata:
name: cluster
spec:
registrySources:
insecureRegistries:
- registry.lab.example.com:5000
- 192.168.1.50:8443
allowedRegistries:
- registry.lab.example.com:5000
- 192.168.1.50:8443
- docker.io
- registry.redhat.io
- quay.io
- registry.access.redhat.com
- ghcr.io
A few important points about this configuration:
- insecureRegistries – registries where TLS verification is skipped. OpenShift will connect over HTTP or accept invalid/self-signed certificates
- allowedRegistries – when set, only these registries can be used for image pulls. All others are blocked. Always include the Red Hat registries (
registry.redhat.io,quay.io,registry.access.redhat.com) or cluster updates and operator installs will break - blockedRegistries – the inverse of allowedRegistries. Cannot be used together with allowedRegistries. Blocks only the listed registries
Save and exit the editor. The MCO picks up the change and starts rolling it out to all nodes.
Step 4: Verify Machine Config Operator Rollout
After modifying the image configuration, the Machine Config Operator updates the /etc/containers/registries.conf file on every node. This requires a node reboot, which the MCO handles automatically. Monitor the rollout progress with these commands.
Check the MachineConfigPool status for worker nodes:
oc get machineconfigpool
During the rollout, you see nodes updating one at a time. The UPDATED column shows False until all nodes finish:
NAME CONFIG UPDATED UPDATING DEGRADED MACHINECOUNT READYMACHINECOUNT UPDATEDMACHINECOUNT UNAVAILABLEMACHINECOUNT AGE
master rendered-master-a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 True False False 3 3 3 0 45d
worker rendered-worker-f6e5d4c3b2a1f6e5d4c3b2a1f6e5d4c3 False True False 3 2 2 1 45d
Wait for all pools to show UPDATED=True and UPDATING=False. You can watch the progress in real time:
oc wait machineconfigpool/worker --for=condition=Updated --timeout=600s
Once complete, the command returns:
machineconfigpool.machineconfiguration.openshift.io/worker condition met
To confirm the registry configuration reached the nodes, open a debug shell on any worker node and check the container registry config:
oc debug node/worker-0.example.com -- chroot /host cat /etc/containers/registries.conf
You should see your insecure registry listed with insecure = true in the output:
[[registry]]
prefix = ""
location = "registry.lab.example.com:5000"
insecure = true
Step 5: Test Pulling from Insecure Registry
With the configuration applied and all nodes updated, verify that your cluster can pull images from the insecure registry. Create a test pod that pulls an image from your registry.
oc run test-pull --image=registry.lab.example.com:5000/myapp:latest --restart=Never
Check the pod status to confirm the image was pulled successfully:
oc get pod test-pull
A successful pull shows the pod in Running or Completed state:
NAME READY STATUS RESTARTS AGE
test-pull 1/1 Running 0 15s
If the pod is stuck in ImagePullBackOff, check the events for details:
oc describe pod test-pull | grep -A 5 Events
Clean up the test pod when done:
oc delete pod test-pull
You can also test image pulls in a Harbor registry deployment or any private registry running in your lab. If you need to add pull secrets for authenticated registries, see Step 8 for troubleshooting authentication issues.
Step 6: Add Registry CA Certificate (Production Approach)
For production environments, the correct approach is to add your registry’s CA certificate to the cluster trust store instead of marking the registry as insecure. This keeps TLS verification active while trusting your internal certificate authority.
First, create a ConfigMap in the openshift-config namespace containing your registry’s CA certificate. The key in the ConfigMap must be the registry hostname and port:
oc create configmap registry-ca \
--from-file=registry.lab.example.com:5000=/path/to/ca-certificate.crt \
-n openshift-config
If your CA certificate covers multiple registries, add them all to the same ConfigMap:
oc create configmap registry-ca \
--from-file=registry.lab.example.com:5000=/path/to/ca-certificate.crt \
--from-file=harbor.internal.local=/path/to/harbor-ca.crt \
-n openshift-config
Next, patch the cluster image config to reference this ConfigMap:
oc patch image.config.openshift.io/cluster --type=merge -p '{"spec":{"additionalTrustedCA":{"name":"registry-ca"}}}'
The MCO distributes the CA certificate to all nodes and updates the trust store. Monitor the rollout the same way as Step 4:
oc get machineconfigpool -w
This approach is strongly recommended over insecure registries because it maintains certificate validation while trusting your internal CA. If you ever need to update the certificate, edit the ConfigMap and the MCO re-rolls the nodes automatically. For troubleshooting x509 certificate errors with container registries, the CA trust method resolves these permanently.
Step 7: Configure Mirror Registries
Mirror registries are common in air-gapped or disconnected OpenShift clusters where nodes cannot reach the internet. Instead of pulling from docker.io or quay.io, the cluster pulls from a local mirror. OpenShift 4.x uses ImageDigestMirrorSet (IDMS) and ImageTagMirrorSet (ITMS) resources for this purpose.
Create an ImageDigestMirrorSet to mirror images from a public registry to your local one:
apiVersion: config.openshift.io/v1
kind: ImageDigestMirrorSet
metadata:
name: local-mirror
spec:
imageDigestMirrors:
- mirrors:
- registry.lab.example.com:5000/docker-io
source: docker.io
- mirrors:
- registry.lab.example.com:5000/quay-io
source: quay.io
Apply the mirror configuration:
oc apply -f image-digest-mirror-set.yaml
If your mirror registry uses self-signed certificates, combine the mirror configuration with Step 6 (add the CA certificate) or Step 2 (mark it as insecure for lab environments).
For environments using Project Quay as the mirror registry, the Quay operator can handle mirror synchronization automatically.
To verify the mirror configuration is active on nodes, check the registries config:
oc debug node/worker-0.example.com -- chroot /host cat /etc/containers/registries.conf.d/99-master-generated-registries.conf
Step 8: Troubleshoot Insecure Registry Issues
When pods fail to pull images from insecure registries, the symptoms are usually ImagePullBackOff or ErrImagePull. Here are the most common causes and fixes.
ImagePullBackOff with x509 Certificate Error
This happens when the registry uses a self-signed certificate but is not listed in insecureRegistries and its CA is not trusted. Check pod events for the exact error:
oc describe pod failing-pod -n your-namespace
Look for messages like this in the Events section:
Failed to pull image "registry.lab.example.com:5000/myapp:latest": rpc error: code = Unknown desc = pinging container registry registry.lab.example.com:5000: Get "https://registry.lab.example.com:5000/v2/": x509: certificate signed by unknown authority
Fix: either add the registry to insecureRegistries (Step 2) or add its CA certificate (Step 6).
MCO Rollout Stuck or Degraded
If the MachineConfigPool shows DEGRADED=True after changing image config, a node failed to apply the new configuration. Check which node is degraded:
oc get nodes -o wide
Then inspect the machine config daemon logs on the affected OpenShift node:
oc logs -n openshift-machine-config-operator -l k8s-app=machine-config-daemon --tail=50
Registry Not Reachable from Nodes
Even with insecure registry configured, pods fail if nodes cannot reach the registry on the network. Open a debug shell and test connectivity:
oc debug node/worker-0.example.com -- chroot /host curl -k https://registry.lab.example.com:5000/v2/
If this times out, check firewall rules between your cluster nodes and the registry server. Port 5000 (or your registry’s configured port) must be open TCP.
Authentication Failures (401 Unauthorized)
Insecure registry configuration handles TLS, not authentication. If your registry requires login credentials, you need a pull secret. Create one and link it to the service account:
oc create secret docker-registry my-registry-secret \
--docker-server=registry.lab.example.com:5000 \
--docker-username=admin \
--docker-password=secretpassword \
-n your-namespace
Link the secret to the default service account in your namespace:
oc secrets link default my-registry-secret --for=pull -n your-namespace
For cluster-wide pull secrets that apply to all namespaces, update the global pull secret. See the Harbor pull secret guide for a detailed walkthrough on managing registry authentication in OpenShift and Kubernetes.
Conclusion
You now have multiple methods to allow insecure registries in your OpenShift or OKD 4.x cluster – from quick oc patch commands for dev/lab environments to the production-grade approach of adding CA certificates. The insecure registry option works for testing but should not be used in production. For production clusters, always add your registry’s CA certificate to the cluster trust store and use allowedRegistries to restrict which registries your cluster can pull from.
For air-gapped deployments, combine mirror registries with CA certificates to keep your cluster secure while running fully disconnected. Monitor MCO rollouts after every image config change and verify the configuration reached all nodes before deploying workloads.