Generate SSL Certificates with Traefik and Let's Encrypt
Traefik is awesome. It can use both file-based certificates and Kubernetes TLS Secret objects as SSL store.
Even it is possible to use SSL certificates generated by Let's Encrypt (privkey.pem
and fullchain.pem
from /etc/letsencrypt/live
direcotory) by creating a TLS secret from these files.
But what if you want to generate certificates using Traefik itself? Luckily Traefik has full support for all Let's Encrypt challenges (http, https and dns based verification). Let's jump in.
First, ensure that Traefik has connectivity to the internet. Without internet connectivity, Traefik will not be able to send certificate renewal requests to ACME servers.
Second, if you have multiple replicas of Traefik running in the cluster (DaemonSet or Deployment) then you can reduce the replicas to 1. This will lower the chance of failed verification attempts and being restricted to issue certificates for a week.
Third, Traefik stores the keys and certificates in a JSON file named acme.json
. This must persist when Traefik restarts. Otherwise, Traefik will try to re-issue the certificate and your domain could be blacklisted for a while.
To enable ACME based resolver, add the following parameters email
, storage
and challenge
as Traefik command line parameters. You are free to choose any name. I used letsencrypt
in this case.
...
- args:
- --log.level=DEBUG
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.email=me@example.com
- --certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/acme.json
- --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
- --serversTransport.insecureSkipVerify=true
image: traefik:v2.9
name: traefik
...
Then let's mount the path /etc/traefik/acme
as a persistence volume. You can use hostPath
, nfs
, glusterfs
or anything compatible with Kubernetes. But make sure that the mount path is shared across all Traefik pods running in the cluster.
volumeMounts:
- name: acme
mountPath: /etc/traefik/acme
volumes:
- name: acme
nfs:
path: /data/traefik-system/acme
server: 192.168.100.200
Once Traefik pods are in Running
state, let's create an IngressRoute
object that uses letsencrypt
resolver as SSL store. Here is one example.
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: my-app
spec:
entryPoints:
- websecure
routes:
- kind: Rule
match: Host(`my-app.com`)
services:
- name: my-app
port: 80
tls:
certResolver: letsencrypt
Once this resource is applied, Traefik will try to issue a certificate using ACME API and disable all other ingress hosts for a few seconds. Upon a successful issue, the acme.json
file will be generated.
Please note that wildcard certificates can only be generated using DNS-based verifications. So you have to use the sans
sections in the tls
block of IngressRoute
carefully.
I hope the post helps you all.
Subscribe to my newsletter
Read articles from Md. Minhazul Haque directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Md. Minhazul Haque
Md. Minhazul Haque
DevOps Engineer | Kubernetes | Python | Terraform | AWS | GCP