My musings on technology, science, math, and more

Redirecting Domains on a Traefik Ingress

I recently posted about my experience with k3s and how I’m now using it to run my blog. I also mentioned my blog’s new domain and how I’m keeping the old name working. That involved changing the Ingress resource for my blog, so I’ll show how I updated it to accept the old domains and automatically redirect to my preferred domain without needing to make WordPress itself do any redirecting.

The Ingress Controller installed by default by k3s (at least for now) is Traefik. It supports a couple of interesting features, including the ability to automatically redirect based on URL regular expressions via just two annotations. These annotations aren’t documented particularly well but I was able to figure them out through some trial and error. First, let me lay out my goals:

  • Redirect requests for these domains to my preferred domain (therubyist.org):
    • www.therubyist.org
    • blog.gnagy.info
    • gnagy.info
  • Make the above redirection happen before WordPress is involved
  • Ensure that HTTPS still works and is forced
    • Also before WordPress itself is involved
  • This redirect should be permanent (meaning an HTTP 301)

Given the above goals, the end result really was modifying the Ingress resource in my previous post from this:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: blog
  namespace: blog
  labels:
    app.kubernetes.io/name: blog
    app.kubernetes.io/part-of: blog
    app.kubernetes.io/component: blog-ingress
  annotations:
    # Forces HTTPS
    ingress.kubernetes.io/ssl-redirect: "true"
    # Uses the right ingress class
    kubernetes.io/ingress.class: "traefik"
    # Tells this Ingress to issue a cert via our ClusterIssuer
    cert-manager.io/cluster-issuer: letsencrypt
    # Uses "http01" for ACME provisioning via Let's Encrypt
    cert-manager.io/acme-challenge-type: http01
spec:
  rules:
  - host: blog.gnagy.info
    http:
      paths:
      - backend:
          serviceName: blog
          servicePort: www
  tls:
  - hosts:
    - blog.gnagy.info
    secretName: blog-tls

To this, which includes the required changes:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: blog
  namespace: blog
  labels:
    app.kubernetes.io/name: blog
    app.kubernetes.io/part-of: blog
    app.kubernetes.io/component: blog-ingress
  annotations:
    # Forces HTTPS
    ingress.kubernetes.io/ssl-redirect: "true"
    # Forces a Permanent (301) redirect
    ingress.kubernetes.io/redirect-permanent: "true"
    # Specifies a regex for which URLs to redirect
    ingress.kubernetes.io/redirect-regex: "^https://(www.therubyist.org|(blog.)?gnagy.info)/?(.*)"
    # Here is where redirected URLs will end up
    #   Notice the $3, which is the third capture
    #   group from the above regex
    ingress.kubernetes.io/redirect-replacement: "https://therubyist.org/$3"
    # Uses the right ingress class
    kubernetes.io/ingress.class: "traefik"
    # Tells this Ingress to issue a cert via our ClusterIssuer
    cert-manager.io/cluster-issuer: letsencrypt
    # Uses "http01" for ACME provisioning via Let's Encrypt
    cert-manager.io/acme-challenge-type: http01
spec:
  # All four rules point to the same service
  rules:
  - host: blog.gnagy.info
    http:
      paths:
      - backend:
          serviceName: blog
          servicePort: www
  - host: gnagy.info
    http:
      paths:
      - backend:
          serviceName: blog
          servicePort: www
  - host: www.therubyist.org
    http:
      paths:
      - backend:
          serviceName: blog
          servicePort: www
  - host: therubyist.org
    http:
      paths:
      - backend:
          serviceName: blog
          servicePort: www
  # Notice how TLS now includes the additional domains
  tls:
  - hosts:
    - blog.gnagy.info
    - gnagy.info
    - therubyist.org
    - www.therubyist.org
    secretName: blog-tls

The above changes amount to three additional annotations, one to specify a permanent redirect and the other two decide what to redirect and where it is redirected. Beyond that, I needed to inform the ingress itself that it is responsible for the additional domains (the rules portion of the spec) as well as updating tls.hosts to include the additional names (so Let’s Encrypt via cert-manager can do its thing).

Of course, this required that I did the prework of pointing those domains at my server ahead of time, but this wasn’t a problem.

If the above is still called blog-ingress.yaml, save it and run:

kubectl apply -f blog-ingress.yaml

Once things are done applying, the redirects should be all set.

Spread the love