Automating TLS on Kubernetes gets tricky once you go beyond a single Ingress certificate. This guide shows how to set up cert-manager on K3s with Let's Encrypt and DNS-01, starting from a fresh Ubuntu server to a working wildcard certificate attached to a Gateway API resource. It also covers checking that renewal works and storing your DNS credentials safely.
Set up Cert-Manager, DNS-01, and Gateway API on K3s
Table of Contents
- What You'll Need
- Step 1: Create a Working Directory for All Manifests
- Step 2: Install K3s
- Step 3: Prepare K3s for cert-manager
- Step 4: Install cert-manager 1.21 via Helm
- Step 5: Store DNS Credentials Securely
- Step 6: Create the ClusterIssuers
- Step 7: Request the Wildcard Certificate
- Step 8: Attach the Certificate to Gateway API
- Step 9: Verify Issuance and Renewal
- Conclusion

What You'll Need
Before starting with cert-manager on K3s with Let's Encrypt and DNS-01, make sure to have:
- A Linux server running Ubuntu 24.04 with sudo access. A reliable dedicated server gives you the stability K3s and ACME challenges need.
- A domain with API-manageable DNS. If you need one, register a domain with DNS you can control via API.
- Ports 80 and 443 are open on your firewall.
Step 1: Create a Working Directory for All Manifests
Everything you create in this guide, such as YAML files and Helm values, should live in one folder so nothing gets lost. On your server, run:
Step 2: Install K3s
Install K3s with a single command:
Export the kubeconfig so kubectl works without the k3s prefix:
Add this line to ~/.bashrc so KUBECONFIG persists across reboots:
Step 3: Prepare K3s for cert-manager
K3s bundles Traefik v3 as its default ingress controller, and Traefik v3 already supports Gateway API v1.4; it just needs to be switched on.
Enable Gateway API in Traefik
Create the HelmChartConfig file directly in the K3s manifests folder. This is a K3s-specific system path, not your ~/k3s-manifests working folder:
Paste this content into the file:
K3s picks this up automatically within a minute; restart K3s if you want it immediately:
Install the Gateway API CRDs
K3s's bundled Traefik already installs some Gateway API CRDs via Helm, so a plain kubectl apply will hit field-ownership conflicts. Use --force-conflicts to take ownership cleanly:
You must see these are listed in your output:
Step 4: Install cert-manager 1.21 via Helm
This is the core of any cert-manager on K3s with Let's Encrypt and DNS-01 setup. cert-manager provides the CRDs, including Certificate, Issuer, and ClusterIssuer, and controllers that talk to Let's Encrypt on your behalf.
If Helm isn't installed, use the commands below:
Now install cert-manager 1.21.1 with Gateway API support enabled:
Confirm every pod comes up:
You should see cert-manager, cert-manager-cainjector, and cert-manager-webhook all in Running state within about 30 seconds.
Step 5: Store DNS Credentials Securely
Never hardcode API tokens in a ClusterIssuer manifest or commit them to Git. You must create a scoped Cloudflare API Token first. From the Cloudflare dashboard > My Profile > API Tokens > Create Token, use the Edit zone DNS template, scoped to your specific zone only.
Copy the token, then create the secret directly on the command line:
kubectl get secret in the cert-manager namespace.Step 6: Create the ClusterIssuers
From the ~/k3s-manifests directory, you must create the DNS-01 issuer file:
Add:
Save and exit, then create the HTTP-01 issuer file:
Add:
Apply both with the commands below:
Step 7: Request the Wildcard Certificate
At this point, you must define a Certificate resource that requests both the root domain and the wildcard subdomain.
Create the file with:
Add:
Apply the Certificate resource and check the status and details of the certificate:
Step 8: Attach the Certificate to Gateway API
Gateway API doesn't use an Ingress annotation. Instead, it points straight to the TLS secret on a Gateway listener. This is the main upgrade that makes a modern cert-manager on K3s with Let's Encrypt and DNS-01 setup different from a basic Ingress-only setup.
Create the gateway file:
Add:
Save and exit, then create the HTTP route file:
Add:
Apply both files:
Step 9: Verify Issuance and Renewal
Check that the certificate is Ready:
Check the certificate details directly instead of just trusting the Kubernetes status:
Let's Encrypt certificates last 90 days. Cert-manager renews them automatically before they expire, usually once about two-thirds of that time has passed. You can also run a renewal manually to check that the automation actually works:
If you delete the secret, cert-manager will immediately request a new certificate. If a fresh one shows up within a minute or two, that confirms automatic renewal is working correctly in your cert-manager on K3s with Let's Encrypt and DNS-01 setup.
Conclusion
At this point, you have a cert-manager on K3s pipeline using Let's Encrypt and DNS-01. It issues both regular and wildcard certificates, handles TLS through a Gateway API listener instead of an old-style Ingress, and renews certificates automatically with no manual work needed.
With cert-manager 1.21.1, Traefik's Gateway API support in K3s, and a safely stored DNS token, this setup can scale from one app to a whole wildcard-covered domain.
We hope you enjoy this guide.
For deeper information on the Gateway API integration, you can check the official cert-manager Gateway API documentation.
HTTP-01 proves domain ownership by serving a file over HTTP; DNS-01 proves it by creating a TXT record. Only DNS-01 supports wildcard certificates.
Ingress still works fine for single-host certificates. Gateway API is the newer, more flexible standard, especially useful for wildcard listeners and multi-namespace routing.
Cert-manager 1.21 officially supports Kubernetes 1.33 through 1.36; older clusters should use cert-manager 1.20 or earlier instead.
Cloudflare, Route53, Google Cloud DNS, Azure DNS, DigitalOcean, RFC2136, and several others are natively supported.