Skip to main content

Fixing my wildcard certificates

· 3 min read
Kas J

In an earlier post, I installed cert-manager to automatically manage my SSL certificates for TLS for my home-lab services. Given it was a set of services within my internal network, I was comfortable with issuing a single wildcard certificate *.local.kasj.live.

The problem

I've since realised a bit of an issue. The wildcard certificates that are issued are issued as a kubernetes secret resource which is specific to a namespace. This meant that in order for me to use the wildcard cert for all my services, I needed to deploy all my services into the same namespace (not ideal).

The research

Turns out there were many solutions to this, many of which I don't really understand but I tried anyway. This included:

The solution

I landed with a solution outline here and it still doesn't work how I want it to but its definitely a step forward.

The first few steps are exactly as I'd performed in my earlier post:

  1. Install Traefik
  2. Install Cert-Manager
  3. Set up Let's Encrypt as an Issuer

This is where I learnt something new:

  1. Issue a wilcard certificate in the same namespace as Traefik in my case this was the kube-system namespace - I also issued myself a new one here to keep things fresh *.home.kasj.live
/home-lab/cluster-setup/cert-manager/wildcard-cert.yaml
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: wildcard-home-kasj-live
namespace: kube-system
spec:
secretName: wildcard-home-kasj-live-tls
issuerRef:
name: letsencrypt-production
kind: ClusterIssuer
# commonName: "*.home.kasj.live"
dnsNames:
- "home.kasj.live"
- "*.home.kasj.live"

Traefik by default normally uses its own self-signed certificate for each ingress service that you define. What I needed to configure was something to tell Traefik to serve the new wildcard certifate I'd created instead. This can be done through a kubernetes resource called TLSStore.

  1. Create a TLSStore resource with the name default. According to the article above, it needed to be called default to be picked up by Traefik by default:
/home-lab/cluster-setup/cert-manager/tls-store.yaml
---
apiVersion: traefik.containo.us/v1alpha1
kind: TLSStore
metadata:
name: default
namespace: kube-system
spec:
defaultCertificate:
secretName: wildcard-home-kasj-live-tls"
  1. Restart Traefik deployment so that it knows to pick up the new cert by default

Testing the new solution

To test if Traefik was issuing my new wildcard certificate by default, I created a simple nginx server and exposed it using the following manifest on test.home.kasj.live:

//home-lab/prod-apps/nginx/ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx
namespace: nginx
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/redirect-entry-point: https
spec:
rules:
- host: test.home.kasj.live
http:
paths:
- backend:
service:
name: nginx
port:
number: 80
path: /
pathType: Prefix

Note: I've moved away from the IngressRoute resource to Ingress

Success! nginx nginx2

Now earlier, I mentioned it still wasn't working as I wanted it to and that's because there is still an issue with some services that already expose their services on SSL/HTTPS (Port 443) by default like nextcloud. Stay tuned for a future post on how I tackle that one but for now I'm going to enjoy this win.

winning