# 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.

```yaml
...
- 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.

```yaml
  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.

```yaml
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.
