DEV Community

giveitatry
giveitatry

Posted on • Edited on

๐Ÿ” How to Enable Letโ€™s Encrypt TLS in K3s with Traefik

By default, K3s ships with Traefik as the Ingress controller. You can configure it to automatically generate TLS certificates using Letโ€™s Encrypt via the ACME protocol.

This guide assumes:

  • You're running K3s with Traefik enabled
  • You have a public domain name (e.g., me.example.com)
  • Ports 80 and 443 are open and forwarded to your K3s nodes
  • DNS for your domain points to your K3s cluster external IP

โœ… Step 1: Check That Traefik Is Installed

Run the following to verify Traefik is deployed:

kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
Enter fullscreen mode Exit fullscreen mode

If you see a Traefik pod running, you're good.

If not, reinstall K3s with the --disable traefik flag removed.


โœ๏ธ Step 2: Create a Traefik Configuration Override

๐Ÿ“ Youโ€™ll only do this on one of the control-plane nodes (any server running k3s server).

Create a file at:

/var/lib/rancher/k3s/server/manifests/traefik-config.yaml
Enter fullscreen mode Exit fullscreen mode

Paste the following config (customize your email address):

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "[email protected]"
      - "--certificatesresolvers.default.acme.storage=/data/acme.json"
      - "--certificatesresolvers.default.acme.httpchallenge.entrypoint=web"
    ports:
      web:
        exposedPort: 80
      websecure:
        exposedPort: 443
Enter fullscreen mode Exit fullscreen mode

Replace [email protected] with your real email. Letโ€™s Encrypt will use this to notify you about certificate expiry issues.

Save and close the file.

K3s will detect the new manifest and automatically apply it (no restart needed).


๐Ÿงช Step 3: Verify Traefik Restarted With New Settings

Check that the Traefik pods restarted and picked up the changes:

kubectl get pods -n kube-system -l app.kubernetes.io/name=traefik
Enter fullscreen mode Exit fullscreen mode

Watch logs to see ACME activity:

kubectl logs -n kube-system -l app.kubernetes.io/name=traefik --tail=100 -f
Enter fullscreen mode Exit fullscreen mode

Look for lines like:

Starting provider aggregator.ProviderAggregator
... Using HTTP challenge
... Registering with ACME server https://acme-v02.api.letsencrypt.org
Enter fullscreen mode Exit fullscreen mode

๐ŸŒ Step 4: Create an Ingress Resource with TLS

Hereโ€™s a sample Ingress you can use for something like me.example.com:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: me-ingress
  annotations:
    kubernetes.io/ingress.class: "traefik"
    traefik.ingress.kubernetes.io/router.entrypoints: websecure
    traefik.ingress.kubernetes.io/router.tls.certresolver: default
spec:
  rules:
    - host: me.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: me-loadbalancer
                port:
                  number: 9000
  tls:
    - hosts:
        - me.example.com
Enter fullscreen mode Exit fullscreen mode

Replace me.example.com with your real domain, and me-loadbalancer with the name of your Service.


๐ŸŒ Step 5: Point DNS to Your Cluster

Make sure me.example.com points to your external IP (e.g., from a cloud provider or your router). You can use services like:

  • Cloudflare DNS
  • DuckDNS (free dynamic DNS)
  • Any custom domain registrar

๐Ÿš€ Step 6: Apply the Ingress

kubectl apply -f me-ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Wait 30โ€“60 seconds. Then check if the certificate was issued:

kubectl describe ingress me-ingress -n my-namesapce
Enter fullscreen mode Exit fullscreen mode

You should see a section under TLS with a certificate from Letโ€™s Encrypt.


๐Ÿ” Step 7: Access Your App via HTTPS

Open your browser and go to:

https://me.example.com
Enter fullscreen mode Exit fullscreen mode

You should see a valid SSL certificate (green lock icon) and no warnings.


๐Ÿงฐ Troubleshooting Tips

Issue Solution
ERR Unable to obtain ACME certificate for domains error="unable to generate a certificate for the domains [me.example.com]: error: one or more domains had a problem:\n[me.example.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: xxx.xxx.xxx.xxx: Invalid response from http://me.example.com/.well-known/acme-challenge/yyyy: 503\n" ACME CA=https://acme-v02.api.letsencrypt.org/directory acmeCA=https://acme-v02.api.letsencrypt.org/directory domains=["me.example.com"] providerName=default.acme routerName=minio-me-ingress-me-example-com@kubernetes rule="Host(me.example.com) && PathPrefix(/) This url http://me.example.com/.well-known/acme-challenge/yyyy shour return 404. If you are running a loadbalancer make shure that it allows 404 statuses to pass health check
When using Load Balancer Make sure that it is not proxied and have ports 80 and 443 open.
Certificate not generated Check if port 80 is open and reachable
DNS not working Use nslookup me.example.com from your local machine
Traefik logs show ACME errors Check email and domain configuration
Still using HTTP Ensure you're hitting https:// and not http://

โœ… Summary

Task Done
Verified Traefik is installed โœ…
Configured Let's Encrypt via manifest โœ…
Created Ingress with TLS annotations โœ…
DNS points to your K3s cluster โœ…
Accessed service over HTTPS โœ…

Top comments (0)