Skip to main content

Configuring Ingress and TLS Certificates with Traefik and Cert-Manager

Cloudflare API Token

You must give cert-manager permission to edit your DNS records.

  1. Go to the Cloudflare Dashboard.

  2. Create Token -> Use the Edit zone DNS template.

  3. Permissions: * Zone -> DNS -> Edit

    • Zone -> Zone -> Read

  4. Zone Resources: Include -> Specific zone -> penguincave.link.

  5. Copy the Token (e.g., zXy...).


Install Traefik


We will use Helm to install Traefik. We'll manually assign your Kube-Vip IP so it remains static.

# Add the Traefik repo
helm repo add traefik https://traefik.github.io/charts
helm repo update

# Create a namespace for networking
kubectl create namespace traefik

# Delete if there's an existing config
# Install Traefik
# Replace 192.168.1.50 with your actual Kube-Vip IP

kubectl delete ingressclass traefik --ignore-not-found=true
helm install traefik traefik/traefik \
  --namespace traefik \
  --create-namespace \
  --set deployment.replicas=2 \
  --set service.type=LoadBalancer \
  --set "service.annotations.kube-vip\\.io/loadbalancerIPs=192.168.100.101" \
  --set "ports.web.redirections.entryPoint.to=websecure" \
  --set "ports.web.redirections.entryPoint.scheme=https" \
  --set "ports.web.redirections.entryPoint.permanent=true"
  • What this does: It sets up two Traefik pods for HA and tells Kube-Vip to bind them to your specific IP. It also forces all HTTP traffic to jump to HTTPS automatically.

Deploy Support Tools (Cert-Manager & Reflector)

We need the "Secretary" to manage the certs and the "Mirror" to share them.

# 1. Install Cert-Manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

# 2. Install Reflector via OCI registry (standard for new versions)
helm upgrade --install reflector oci://ghcr.io/emberstack/helm-charts/reflector \
  --namespace kube-system

 

Phase 3: Cloudflare DNS-01 Setup

This part connects your Cloudflare API to the cluster and requests the certificate.

1. Create the API Token Secret

kubectl create secret generic cloudflare-api-token-secret \
  -n cert-manager \
  --from-literal=api-token=YOUR_ACTUAL_CLOUDFLARE_TOKEN

2. Create the ClusterIssuer (issuer.yaml): Note: Use a real email address to avoid ACME registration errors.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-cloudflare
spec:
  acme:
    email: your-real-email@gmail.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-cloudflare-account-key
    solvers:
    - dns01:
        cloudflare:
          apiTokenSecretRef:
            name: cloudflare-api-token-secret
            key: api-token

Phase 4: The Wildcard Certificate

This creates the master certificate in the traefik namespace. Reflector then mirrors it cluster-wide.

Create wildcard-cert.yaml:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: homelab-wildcard
  namespace: traefik
spec:
  secretName: homelab-wildcard-tls
  issuerRef:
    name: letsencrypt-cloudflare
    kind: ClusterIssuer
  dnsNames:
  - "*.homelab.penguincave.link"
  secretTemplate:
    annotations:
      reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
      reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"

Phase 5: High Availability Test (NGINX)

This ensures 3 replicas are spread across your 3 master nodes using Pod Anti-Affinity.

Create nginx-ha.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ha
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values: ["nginx"]
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: nginx
        image: nginx:latest
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
  - port: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
spec:
  ingressClassName: traefik
  tls:
  - hosts: ["nginx.homelab.penguincave.link"]
    secretName: homelab-wildcard-tls
  rules:
  - host: nginx.homelab.penguincave.link
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx-svc
            port:
              number: 80

Troubleshooting Commands

  • Check Cert Status: kubectl get cert -n traefik

  • Check DNS Challenge: kubectl describe challenge -n traefik

  • Check Secret Mirroring: kubectl get secret homelab-wildcard-tls -n longhorn-system

  • Check Pod Distribution: kubectl get pods -o wide

Would you like me to create a single bash script that automates these installations for future node resets?