Move to k8s: Using nginx rewrite rule to preserve permalinks
I have been moving all of my side projects to a kubernetes cluster to simplify my life. It's been going slow due to my commitments to my day jobs and (new side projects). While I had to say goodbye to my old personal website because it was difficult to migrate to a Linux environment, all other the services only required some docker magic as I have already upgraded them to .NET Core, or they were already written in cross-platform languages (like my secret crush Go).
One exception to that was go.mustak.im - I used it over the years to generate permalinks (for ex: go.mustak.im/linkedIn - takes to my LinkedIn page). It is a simple PHP script backed by MySQL database. Why PHP and MySQL for such a simple site? ... ahem, it was simple at that time when I wrote this ... a long time ago. I already had MySQL installed and IIS had PHP extension installed in my Windows Server VPS. It handled a decent amount of traffics over the years and never required any maintenance.
Being written using a programming language and a database meant I had an admin interface to add/remove permalinks and view hit counts etc. Here's how it looked, nice wasn't it?

Now, the whole reason I am writing this post - I didn't want to carry the weight of MySQL server for this in my new kubernetes environment. So I had to come up with a simple solution. Here's the idea and what it meant-
- Kubernetes ingress with hardcoded rewrite rule - simple, lightweight.
- I will lose access to hit counts - I couldn't care less!
- I will lose access to a back panel - It's fine, how often do I need to add a permalink? and how difficult it is to do
kubectl apply -f k8s-spec.yaml
?
Rewrite rules
Here is the Ingress resource with most of the rewrite rules removed for beivety
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: go-mustakim-ing
annotations:
nginx.ingress.kubernetes.io/server-snippet: |
rewrite ^/cant-run-linqpad(.*) "https://about.mustak.im/cant-run-linqpad/$1" last;
rewrite ^/linked[I|i]n(.*) "http://uk.linkedin.com/in/mustakimali/$1" last;
rewrite ^/(.*)$ "https://mustak.im/";
spec:
tls:
- hosts:
- go.mustak.im
rules:
- host: go.mustak.im
Few things to notice here,
- Each of the rules only matches the first part of the request and preserves the rest of the url across the redirect. so the rule
/foo
->/dest
will also match/foo/bar
and redirect to/dest/bar
. - All of the rewrite rules have
last
flag so that nginx skips checking any other rules - to improve the speed and to avoid any issues when multiple rules matches. - The last rule is a catch-all when none of the rule works - it redirects to the homepage.
rewrite ^/(.*)$ "https://mustak.im/";