SSL
Kubernetes
Ingress Controller
Fake Certificate
Troubleshooting

SSL Certificate added but shows Kubernetes Ingress controller fake certificate

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When an Ingress controller serves a “fake” or default certificate instead of your real TLS certificate, the controller is telling you it could not find or use a matching certificate for that request. The problem is usually not TLS itself. It is a mismatch between hostnames, secret location, ingress class, or the controller's ability to load the secret.

Why the Fake Certificate Appears

Controllers such as ingress-nginx keep a fallback certificate so they can still terminate TLS when no valid host-specific certificate is available. You usually see that fallback in one of these cases:

  • the request hostname does not match any Ingress rule
  • the tls.secretName is wrong or the secret is in a different namespace
  • the secret data is malformed or missing tls.crt or tls.key
  • the Ingress is not handled by the controller you think it is
  • the certificate does not match the requested host through SNI

That means the debugging question is not “why is Kubernetes inventing a cert?” It is “why did the controller ignore my intended certificate?”

Verify the Ingress and Secret First

Start by checking the Ingress object and the TLS secret in the same namespace:

bash
kubectl get ingress my-app -n web -o yaml
kubectl get secret my-app-tls -n web -o yaml
kubectl describe ingress my-app -n web

The secret referenced under spec.tls.secretName must exist in the same namespace as the Ingress. A secret in default cannot be used by an Ingress in web.

A correct-looking Ingress typically resembles this:

yaml
1apiVersion: networking.k8s.io/v1
2kind: Ingress
3metadata:
4  name: my-app
5  namespace: web
6spec:
7  ingressClassName: nginx
8  tls:
9    - hosts:
10        - app.example.com
11      secretName: my-app-tls
12  rules:
13    - host: app.example.com
14      http:
15        paths:
16          - path: /
17            pathType: Prefix
18            backend:
19              service:
20                name: my-app
21                port:
22                  number: 80

Notice that the host under tls.hosts and the host under rules.host must line up with the hostname clients actually request.

Test the Request with the Correct Hostname

One of the easiest mistakes is testing the load balancer IP directly in a browser or with curl and expecting your custom certificate to appear. TLS selection is usually based on SNI, which depends on the hostname the client sends.

Use openssl or curl with the intended host explicitly:

bash
openssl s_client -connect app.example.com:443 -servername app.example.com
curl -vk --resolve app.example.com:443:203.0.113.10 https://app.example.com/

If you browse to https://203.0.113.10/ instead, the controller may correctly serve the default certificate because no host rule matches that request.

Check Controller Ownership and Logs

If the Ingress object looks right but the certificate is still fake, confirm the correct controller is watching it. In clusters with multiple controllers, the wrong ingress class can leave your resource ignored.

Then inspect controller logs for secret loading errors:

bash
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller

You may find messages about a missing secret, invalid PEM data, or a reload problem. Those log lines usually identify the failure much faster than trial-and-error YAML edits.

Also verify the certificate itself:

bash
kubectl get secret my-app-tls -n web -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -text

Check the subject alternative names and confirm app.example.com appears there.

Common Pitfalls

The most common mistake is a namespace mismatch between the Ingress and the TLS secret. The second is testing the wrong hostname and concluding the certificate is broken when the controller is simply serving the default server block.

Another frequent issue is forgetting ingressClassName in clusters with more than one ingress controller. Your resource may exist, but the controller serving traffic may not be the one processing it.

It is also possible to create the secret with the wrong data or an incomplete chain. If the controller cannot parse the secret correctly, it will fall back to the default certificate.

Summary

  • The fake certificate is a fallback, not the real root cause.
  • Check that the TLS secret exists in the same namespace as the Ingress.
  • Make sure the requested hostname matches the Ingress rule and the certificate SANs.
  • Confirm the correct ingress controller owns the resource.
  • Use controller logs and openssl to verify what certificate is actually being served.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.