Issue Summary
I have a Kubernetes cluster 1.30 running on 3 AWS EC2 servers, 1 master node, and 2 worker nodes. I am trying to deploy a private container registry using the registry:2.8.2
image of the CNCF distribution project. I have followed the steps listed below, but I am getting the error "x509 certificate signed by unknown authority" while I am trying to perform a docker login to the registry.
Note: I am using self-signed certificates.
Steps to Reproduce
-
Create self-signed certificates and user authentication. The TLS certificates use OpenSSL:
mkdir registry cd registry mkdir certs mkdir auth openssl req -x509 -newkey rsa:4096 -days 365 -nodes -sha256 -keyout certs/tls.key -out certs/tls.crt -subj "/CN=my-registry" -addext "subjectAltName = DNS:my-registry"
-
Use
htpasswd
to add user authentication for registry access. The credentials for the private registry aremyuser/mypasswd
:docker run --entrypoint htpasswd httpd:2 -Bbn myuser mypasswd > auth/htpasswd
-
Create a secret to mount the certificates (secret type
tls
):kubectl create secret tls certs-secret --cert=/home/ubuntu/day42/registry/certs/tls.crt --key=/home/ubuntu/day42/registry/certs/tls.key
-
Create a secret for authentication:
kubectl create secret generic auth-secret --from-file=/home/ubuntu/day42/registry/auth/htpasswd
-
Create the local directory and apply PV PVC.
-
Create the registry pod.
apiVersion: v1
kind: Pod
metadata:
name: docker-registry-pod
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2.8.2
volumeMounts:
- name: repo-vol
mountPath: "/var/lib/registry"
- name: certs-vol
mountPath: "/certs"
readOnly: true
- name: auth-vol
mountPath: "/auth"
readOnly: true
env:
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: "/certs/tls.crt"
- name: REGISTRY_HTTP_TLS_KEY
value: "/certs/tls.key"
volumes:
- name: repo-vol
persistentVolumeClaim:
claimName: registry-pvc
- name: certs-vol
secret:
secretName: certs-secret
- name: auth-vol
secret:
secretName: auth-secret
-
Create the service pod.
-
Export the environment variables:
export REGISTRY_NAME="my-registry" Master-->export REGISTRY_IP="10.100.175.12" # (Above IP is the NodePort service IP)
-
Add the below entry to
/etc/hosts
of all nodes:10.100.175.12 my-registry
-
Copy
tls.crt
to/usr/local/share/ca-certificates
on all the nodes and run the following command:sudo update-ca-certificates
-
Try to login to the registry:
docker login my-registry:5000 -u myuser -p mypasswd
Error Details
Error response from daemon: Get "https://my-registry:5000/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority
Output of crictl info
crictl info |grep -i tls
"enableTLSStreaming": false,
"tlsCertFile": "",
"tlsKeyFile": ""
2
Answers
Phew! After spending 3 days with this issue, I finally figured it out.
Below are the steps I have taken to fix the issue:
Ensure All Nodes Trust the Self-Signed Certificate:
tls.crt
is copied to/usr/local/share/ca-certificates
on all nodessudo update-ca-certificates
on each node.Configure Docker to Trust the Self-Signed Certificate:
Docker needs to be explicitly configured to trust your self-signed certificate. You must copy the
tls.crt
to Docker's trusted certificates directory.Run docker login again
For the certificates like the SSL ones, you need to add the entire certificate chain into the certificate file you are using with nginx to run the registry. Many operating systems don’t trust the intermediate CAs, just the root CA, so you need to fill in the missing steps between the certificate for your host and the root CA that is trusted by the OS.
In the email you received your certificate with, you should also find links to the intermediate CAs and the root CA. Open the docker-registry.crt file, scroll to the bottom, and append the intermediate CAs and, finally, the root CA certificate for the PositiveSSL chain. Once you’ve done that, restart nginx. You should now be good to go.
Note: If you own a domain name you can use Let’s Encrypt to obtain a trusted certificate at zero cost.