This repository contains kube-acme, a service that performs Let's Encrypt certificate updates in Kubernetes. It accepts ACME challenges routed from nginx and stores the certificate as a Secret. On top of that, if you're running on Oracle Cloud Kubernetes Engine (OKE), kube-acme can update your Service if your setup terminates SSL/TLS at the load balancer.
Note: This is only useful for the above-mentioned setup where cert-manager doesn't fit. In all other cases, you should probably use that.
This service can be used in a couple different configurations but they all require the following:
- Whatever is serving your HTTP requests, it needs to be able to relay the
/.well-known/acme-challenge/path to thekube-acmepod. - Whatever is providing your SSL/TLS service, it needs to be able to load it from a Kubernetes
Secret.
To install kube-acme in your cluster, download the deployment.yaml and edit the environment variables. The commented out ones are optional and will have their default values.
curl -O https://github.com/prep/kube-acme/blob/k8s/deployment.yamlLoad your deployment.yaml once it's been edited:
kubectl apply -f deployment.yamlCheck that a single pod is running:
kubectl -n kube-acme get podsThe kube-acme pod needs the ability to receive ACME challenges from all the configured domains. Here are 2 ways to relay them based on what setup you are running.
If your setup uses nginx then you need add a location rule in your nginx configuration for every domain who will be part of the certificate.
server {
server_name example.com;
location /.well-known/acme-challenge/ {
proxy_pass http://kube-acme.kube-acme.svc.cluster.local:80;
}
}Apply this change to your configuration and restart your nginx pods:
kubectl -n nginx rollout restart deploy nginxTo request kube-acme to create or update the certificate, send the following request to the running pod:
kubectl exec -n kube-acme $(kubectl get pod -n kube-acme -l app=kube-acme -o jsonpath='{.items[0].metadata.name}') -- /kubeacme requestKeep an eye out on the logs to see if it succeeded:
kubectl logs -f -n kube-acme -l app=kube-acmeIdeally, this should be done automatically, but that's not implemented yet. A typical log should look like this:
time=2025-07-06T16:22:55.432Z level=INFO msg="Requesting certificate update" app.name=kube-acme app.revision=19 app.commit=df08ca2
time=2025-07-06T16:23:00.390Z level=INFO msg="Secret stored" k8s.namespace=nginx k8s.name=ssl-cert-20250706 app.name=kube-acme app.revision=19 app.commit=df08ca2
time=2025-07-06T16:23:00.391Z level=INFO msg="Updating service annotation" key=service.beta.kubernetes.io/oci-load-balancer-tls-secret value=ssl-cert-20250706 k8s.name=ingress k8s.namespace=nginx app.name=kube-acme app.revision=19 app.commit=df08ca2
time=2025-07-06T16:23:00.398Z level=INFO msg="Certificate update finished" k8s.name=ssl-cert-20250706 k8s.namespace=nginx app.name=kube-acme app.revision=19 app.commit=df08ca2
To pull the latest image in and update the service, simply restart the deployment.
kubectl -n kube-acme rollout restart deploy