# kubectl: x509 certificate signed by unknown authority fix

> kubectl reports x509: certificate signed by unknown authority when the CA in kubeconfig does not match the API server's. Refresh kubeconfig; don't skip TLS.

Source: https://ssl.sh/errors/kubectl-x509-certificate-signed-by-unknown-authority/
Last updated: 2026-11-10

**`Unable to connect to the server: x509: certificate signed by unknown authority` means kubectl could not verify the API server's certificate with the CA in your kubeconfig.** Usually the kubeconfig is out of date after a rebuild or CA rotation, points at the wrong cluster, or a proxy or load balancer presents a different certificate.

Newer kubectl versions print `tls: failed to verify certificate: x509: certificate signed by unknown authority`; it is the same error.

## Quick fix

A fresh kubeconfig from the cluster fixes most cases.

Compare the CA your kubeconfig trusts with the certificate the server presents, using the commands below or the [certificate decoder](https://ssl.sh/tools/certificate-decoder/):

```bash
# CA in the current context's kubeconfig
kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' \
  | base64 -d | openssl x509 -noout -subject -fingerprint -sha256

# Server URL and the certificate chain it presents
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}'; echo
openssl s_client -connect 203.0.113.10:6443 -showcerts </dev/null | grep -E 's:|i:'
```

If the server certificate's issuer is not the CA from your kubeconfig, get a fresh kubeconfig:

- **kubeadm:** copy `/etc/kubernetes/admin.conf` from a control-plane node to `~/.kube/config`.
- **Managed clusters:** download the kubeconfig again from the provider's console or CLI.
- **You only have the CA file:** embed it into the cluster entry:

```bash
kubectl config set-cluster my-cluster --certificate-authority=ca.crt --embed-certs=true
```

## Causes

A stale kubeconfig after a cluster rebuild or CA rotation is the most common cause.

### 1. Stale kubeconfig after rebuild or CA rotation

- **Confirm:** fingerprints differ between the kubeconfig CA and the server's issuing CA; the cluster was recently reinstalled.
- **Fix:** replace the kubeconfig as above. Kubeconfigs on CI runners and colleagues' laptops are stale too.

### 2. Wrong context or merged kubeconfig

With several clusters in one file, or `KUBECONFIG` listing multiple files, a cluster entry can end up with another cluster's CA.

- **Confirm:** `kubectl config current-context` and `kubectl config view --minify` show which cluster entry is used.
- **Fix:** switch context with `kubectl config use-context`, or fix the cluster entry.

### 3. Proxy in the path

kubectl honours `HTTPS_PROXY`. A TLS-inspecting corporate proxy replaces the API server certificate with its own.

- **Confirm:** `env | grep -i proxy`; the issuer in `openssl s_client` (run from the same shell) names the proxy.
- **Fix:** add the API server address to `NO_PROXY` so kubectl connects directly.

### 4. TLS-terminating load balancer

If a load balancer in front of the API server presents its own certificate, kubectl sees a certificate the cluster CA did not sign.

- **Fix:** use TCP (layer-4) pass-through for port 6443 so the API server's own certificate reaches the client, or point the kubeconfig at the balancer's CA (client-certificate authentication will then not work through a terminating balancer).

## Fixes by environment

Every fix gives kubectl the cluster's current CA, the [root certificate](https://ssl.sh/glossary/root-certificate/) that signed the API server certificate; only the place to get it differs.

**kubeadm:** the cluster CA is `/etc/kubernetes/pki/ca.crt`. `admin.conf` embeds it, together with an admin client certificate.

**Managed Kubernetes:** regenerate credentials with the provider's tool (for example the cloud CLI's "get credentials" command) rather than editing CA data by hand.

**Pods and webhooks inside the cluster:** a similar error from the API server when calling an admission webhook means the webhook's `caBundle` does not match its serving certificate. If cert-manager manages it, check the `Certificate` resource; see [cert-manager certificate not ready](https://ssl.sh/errors/cert-manager-certificate-not-ready/).

**Other Go tools:** Helm, k9s, Lens and Terraform's Kubernetes provider read the same kubeconfig, so one fix covers all of them. For the general Go error, see [x509: certificate signed by unknown authority](https://ssl.sh/errors/x509-certificate-signed-by-unknown-authority/).

## Don't do this

- **`kubectl --insecure-skip-tls-verify`** or `insecure-skip-tls-verify: true` in kubeconfig. Your client certificate or token goes to whoever answers, and these credentials are usually cluster-admin.
- **Deleting `certificate-authority-data`** to fall back to the system store. The cluster CA is private, so this fails, and it invites trusting a public CA for an internal endpoint.
- **Sharing one admin kubeconfig by chat or e-mail** to work around per-user setup. Generate per-user credentials instead.
