jetstack
kube-lego
Go

DEPRECATED: Automatically request certificates for Kubernetes Ingress resources from Let's Encrypt

Last updated Jul 8, 2026
2.1k
Stars
257
Forks
104
Issues
0
Stars/day
Attention Score
74
Language breakdown
No language data available.
Files click to expand
README

kube-lego

:warning:
>
kube-lego is no longer maintained. The officially endorsed successor is cert-manager.
>
If you are a current user of kube-lego, you can find a migration guide here.
>
:warning:

kube-lego automatically requests certificates for Kubernetes Ingress resources from Let's Encrypt

Build Status

Screencast

Kube Lego screencast

Features

  • Recognizes the need of a new certificate for this cases:
- No certificate existing - Existing certificate is not containing all domain names - Existing certificate is expired or near to its expiry date (cf. option LEGOMINIMUMVALIDITY) - Existing certificate is unparseable, invalid or not matching the secret key
  • Creates a user account (incl. private key) for Let's Encrypt and stores it in Kubernetes secrets (secret name is configurable via LEGOSECRETNAME)
  • Obtains the missing certificates from Let's Encrypt and authorizes the request with the HTTP-01 challenge
  • Makes sure that the specific Kubernetes objects (Services, Ingress) contain the rights configuration for the HTTP-01 challenge to succeed
  • Official Kubernetes Helm chart for simplistic deployment.

Requirements

  • Kubernetes 1.2+
  • Compatible ingress controller (nginx or GCE see here)
  • Non-production use case :laughing:

Usage

run kube-lego

The default value of LEGO_URL is the Let's Encrypt staging environment. If you want to get "real" certificates you have to configure their production env.

how kube-lego works

As soon as the kube-lego daemon is running, it will create a user account with LetsEncrypt, make a service resource, and look for ingress resources that have this annotation:

metadata:
  annotations:
    kubernetes.io/tls-acme: "true"

Every ingress resource that has this annotation will be monitored by kube-lego (cluster-wide in all namespaces). The only part that is watched is the list spec.tls. Every element will get its own certificate through Let's Encrypt.

Let's take a look at this ingress resource:

spec:
  tls:
  - secretName: mysql-tls
    hosts:
    - phpmyadmin.example.com
    - mysql.example.com
  - secretName: postgres-tls
    hosts:
    - postgres.example.com

On finding the above resource, the following happens:

  • An ingress resource is created coordinating where to send acme challenges for the said domains.
  • kube-lego will then perform its own check for i.e. http://mysql.example.com/.well-known/acme-challenge/_selftest to ensure all is well before reaching out to letsencrypt.
  • kube-lego will obtain two certificates (one with phpmyadmin.example.com and mysql.example.com, the other with postgres.example.com).

Please note:

  • The secretName statements have to be unique per namespace
  • secretName is required (even if no secret exists with that name, as it will be created by kube-lego)
  • Setups which utilize 1:1 NAT need to ensure internal resources can reach gateway controlled public addresses.
  • Additionally, your domain must point to your externally available Load Balancer (either directly or via 1:1 NAT)

Switching from staging to production

At some point you'll be ready to use LetsEncrypt production API URL. To make the switch in kube-lego, please do the following:
  • Update LEGO_URL to https://acme-v01.api.letsencrypt.org/directory.
  • Delete the existing k8s secret kube-lego-account.
  • Delete other secrets that hold data for certificates you want to replace.
  • Restart kube-lego.

Ingress controllers

Nginx Ingress Controller

  • available through image gcr.io/google_containers/nginx-ingress-controller
  • fully supports kube-lego from version 0.8 onwards

GCE Loadbalancers

  • you don't have to maintain the ingress controller yourself, you pay GCE to do that for you
  • every ingress resource creates one GCE load balancer
  • all service that you want to expose, have to be Type=NodePort

Environment variables

| Name | Required | Default | Description | |------|----------|---------|-------------| | LEGO_EMAIL | y | - | E-Mail address for the ACME account, used to recover from lost secrets | | LEGOPODIP | y | - | Pod IP address (use the downward API)| | LEGO_NAMESPACE | n | default | Namespace where kube-lego is running in | | LEGO_URL | n | https://acme-staging.api.letsencrypt.org/directory | URL for the ACME server. To get "real" certificates set to the production API of Let's Encrypt: https://acme-v01.api.letsencrypt.org/directory | | LEGOSECRETNAME | n | kube-lego-account | Name of the secret in the same namespace that contains ACME account secret | | LEGOSERVICESELECTOR | n | kube-lego | Set the service selector to the the kube-lego pod | | LEGOSERVICENAME_NGINX | n | kube-lego-nginx | Service name for NGINX ingress | | LEGOSERVICENAME_GCE | n | kube-lego-gce | Service name for GCE ingress | | LEGOSUPPORTEDINGRESS_CLASS | n | nginx,gce | Specify the supported ingress class | | LEGOSUPPORTEDINGRESS_PROVIDER | n | nginx,gce | Specify the supported ingress provider | | LEGOINGRESSNAME_NGINX | n | kube-lego-nginx | Ingress name which contains the routing for HTTP verification for nginx ingress | | LEGO_PORT | n | 8080 | Port where this daemon is listening for verifcation calls (HTTP method) | | LEGOCHECKINTERVAL | n | 8h | Interval for periodically certificate checks (to find expired certs) | | LEGOMINIMUMVALIDITY | n | 720h (30 days) | Request a renewal when the remaining certificate validity falls below that value | | LEGODEFAULTINGRESS_CLASS | n | nginx | Default ingress class for resources without specification| | LEGODEFAULTINGRESSPROVIDER | n | $LEGODEFAULTINGRESSCLASS | Default ingress provider for resources without specification | | LEGOKUBEAPI_URL | n | http://127.0.0.1:8080 | API server URL | | LEGOLOGLEVEL | n | info | Set log level (debug, info, warn or error) | | LEGOLOGTYPE | n | text | Set log type. Only json as custom value supported, everything else defaults to default logrus textFormat | | LEGOKUBEANNOTATION | n | kubernetes.io/tls-acme | Set the ingress annotation used by this instance of kube-lego to get certificate for from Let's Encrypt. Allows you to run kube-lego against staging and production LE | | LEGOWATCHNAMESPACE | n | ` | Namespace that kube-lego should watch for ingresses and services | | LEGORSAKEYSIZE | n | 2048 | Size of the private RSA key | | LEGOEXPONENTIALBACKOFFMAXELAPSED_TIME | n | 5m | Max time to wait for each domain authorization attempt | | LEGOEXPONENTIALBACKOFFMAXINITIAL_INTERVAL | n | 30s | Initial interval to wait for each domain authorization attempt | | LEGOEXPONENTIALBACKOFFMAXMULTIPLIER | n | 2.0 | Multiplier for every step |

Full deployment examples

Troubleshooting

When interacting with kube-lego, its a good idea to run with LEGOLOGLEVEL=debug for more verbose details. Additionally, be aware of the automatically created resources (see environment variables) when cleaning up or testing.

Possible resources for help:

  • The official channel #kube-lego #cert-manager on kubernetes.slack.com (The old channel was renamed)
> There is also a good chance to get some support on non-official support > channels for kube-lego, but be aware that these are rather general > kubernetes discussion channels.
  • #coreos on freenode
  • Slack channels like #kubernetes-users or #kubernetes-novice on kubernetes.slack.com
  • If you absolutely just can't figure out your problem, file an issue.

Enable the pprof tool

To enable the pprof tool run kube-lego with environment LEGOLOG_LEVEL=debug.

Capture 20 seconds of the execution trace:

$ wget http://localhost:8080/debug/pprof/trace?seconds=20 -O kube-lego.trace

You can inspect the trace sample running

$ go tool trace kube-lego.trace`

Authors

🔗 More in this category

© 2026 GitRepoTrend · jetstack/kube-lego · Updated daily from GitHub