DEV Community

Cover image for Article 5: HTTPS Setup and Future Improvements
Woulf
Woulf

Posted on • Edited on

Article 5: HTTPS Setup and Future Improvements

Setting up HTTPS certificates using Let’s Encrypt and cert-manager, with challenge configuration and security annotations in the Kubernetes Ingress.

In this fifth step, I’ll go over how I enabled an SSL/TLS certificate to secure woulf.fr, still within a DevOps mindset. We'll cover:

  1. Why Let’s Encrypt
  2. Why cert-manager
  3. Essential annotations (ssl-redirect, hsts-max-age)

Project context

Throughout the previous articles, I’ve:

  • Deployed a Kubernetes cluster using MicroK8s on a VPS
  • Containerized my application with Docker
  • Set up a GitHub Actions CI/CD pipeline to automatically build and publish the Docker image
  • Split app code and infrastructure into separate Git repositories
  • Deployed everything to Kubernetes using a GitOps approach

The final step was to secure the site with HTTPS.


Why Let’s Encrypt?

Let’s Encrypt is a free, automated, and open certificate authority. It’s the go-to solution for obtaining a valid SSL/TLS certificate easily.

Advantages:

  • Free: no cost for issuing or renewing certificates
  • Automated: works well with DevOps tools and Kubernetes
  • Trusted: certificates are valid in all modern browsers

Why cert-manager?

cert-manager is a Kubernetes operator built to automate certificate lifecycle management (issuing, renewal, rotation...).

It allows you to:

  • Create SSL/TLS certificates using Kubernetes Certificate resources
  • Handle validation challenges automatically with Let’s Encrypt
  • Manage renewals with no manual intervention

It fits naturally into a GitOps workflow: certificates and their configuration can be versioned in the infra repo.


How the HTTP-01 challenge works

To verify domain ownership, Let’s Encrypt uses HTTP-based validation:

  1. cert-manager creates a Challenge at a special URL:
http://woulf.fr/.well-known/acme-challenge/<token>
Enter fullscreen mode Exit fullscreen mode
  1. It spins up a temporary acmesolver pod that responds with a key
  2. Let’s Encrypt queries the URL:
    • If the correct key is returned, the certificate is issued
    • If not, validation fails

By adding this annotation to the Ingress:

acme.cert-manager.io/http01-edit-in-place: "true"
Enter fullscreen mode Exit fullscreen mode

the HTTP challenge is integrated directly into the main Ingress, avoiding conflicts (which I had with separate solver pods/Ingresses).


Adding annotations for extra security

nginx.ingress.kubernetes.io/ssl-redirect

nginx.ingress.kubernetes.io/ssl-redirect: "true"
Enter fullscreen mode Exit fullscreen mode

Automatically redirects HTTP traffic to HTTPS.

Once the certificate is active, this ensures users always connect over HTTPS.


nginx.ingress.kubernetes.io/hsts-max-age

nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
Enter fullscreen mode Exit fullscreen mode

Adds an HSTS (HTTP Strict Transport Security) header, telling browsers to refuse HTTP for 1 year (31,536,000 seconds).

⚠️ Enable this only after HTTPS is confirmed working, as it prevents fallback to HTTP.


Final configuration example

Here’s a snippet of the final Ingress configuration with all best practices included:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: woulf-ingress
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    acme.cert-manager.io/http01-edit-in-place: "true"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/hsts-max-age: "31536000"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - woulf.fr
      secretName: woulf-fr-tls
  rules:
    - host: woulf.fr
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: portfolio
                port:
                  number: 3000
Enter fullscreen mode Exit fullscreen mode

What’s next?

✅ The site is now accessible via HTTPS, with a Let’s Encrypt certificate fully managed by cert-manager.

Here’s what I’m planning next:

  • Monitoring: set up Prometheus / Grafana stack
  • Centralized logging: using Loki or EFK
  • Advanced GitOps: try out ArgoCD or Flux to continuously observe and reconcile cluster state

This project is my first step toward a fully automated and maintainable infrastructure. And it’s only the beginning 👨‍🚀

Top comments (0)