EDIT 2019-10-31: I tried to update this guide to 0.11, as a lot of things have changed since the original publication. I haven’t tested the full guide in the new version yet, but it should work. EDIT 2019-12-09: Updated for 0.12 and helm3

This post will show you how to use cert-manager to automatically create and use certificates with Let’s Encrypt on Kubernetes. This is especially useful if you are looking for a successor to kube-lego, which is no longer maintained. Take a look at the offical docs, if you want more information about how each component works.

Prerequisites for this guide:

First we need to install cert-manager with helm

helm repo add jetstack https://charts.jetstack.io
helm repo update
kubectl create ns cert-manager
kubectl apply --validate=false -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.12/deploy/manifests/00-crds.yaml
helm install   --name cert-manager   --namespace cert-manager   --version v0.12.0   jetstack/cert-manager

Install clusterissuers, which instruct Cert Manager to use Let’s Encrypt. Replace the email with yours

apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: default
spec:
  acme:
    email: youremail@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class:  nginx

Enable usage of the issuer we just created:

helm upgrade cert-manager     stable/cert-manager     --namespace cert-manager     --set ingressShim.defaultIssuerName=letsencrypt-prod --set ingressShim.defaultIssuerKind=ClusterIssuer

Create ingress resources for your services with kubectl apply -f e.g.:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: www-ingress
  namespace: default
  annotations:
    # This needs to be set to enable automatic certificates
    kubernetes.io/tls-acme: "true"
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    - www.example.com
    # The secret will be created automatically
    secretName: www-tls
  rules:
  # The host must be identical to the above one
  - host: www.example.com
    http:
      paths:
      - path: /
        backend:
          # The name of your service
          serviceName: www-service
          servicePort: 80

This is the minimal configuration that gives you SSL. Your website should no be accessible via https at www.example.com.

Working with authentication

If you use nginx.ingress.kubernetes.io/auth-* annotations you will need to whitelist the ACME challenge location in order to succeed in proving that you operate the website to Let’s Encrypt. If you set up Nginx ingress correctly there should be a configmap for configuring nginx. Modify it (by e.g. running EDITOR=nano kubectl edit cm -n ingress-nginx nginx-configuration) to add the annotation no-auth-locations so that it looks similar to this:

apiVersion: v1
data:
  no-auth-locations: /.well-known/acme-challenge
  # ...
kind: ConfigMap
metadata:
  annotations:
    # ...
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: ingress-nginx
  # ...