After trying out many different CMS and blogging solutions, I decided to stick with ghost. Ghost's WYSIWYG editor is the best on the market in my opinion. Deploying a ghost instance is pretty straightforward as well. Since I use containers for almost everything, I started with a simple docker-compose file:
version: '3.1'
services:
ghost:
image: ghost
restart: always
ports:
- 2368:2368
environment:
database__client: mysql
database__connection__host: db
database__connection__user: root
database__connection__password: example
database__connection__database: ghost
url: http://localhost:2368
db:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
That allows to deploy a ghost instance in seconds:

After this successful test I decided to deploy ghost directly to my k8s cluster. The deployment itself is straightforward, I basically just changed the "url" environment variable to match my URL:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: ghost
name: ghost
labels:
app: ghost
spec:
[...]
template:
[...]
spec:
containers:
- name: ghost
image: ghost
ports:
- containerPort: 2368
env:
[...]
- name: url
value: https://blog.mrupp.eu
[...]
I expected this to work just fine but the result was pretty unsatisfying:

It turned out that ghost tried to redirect me to https://blog.mrupp.eu
which is exactly the URL that I entered in my web browser. The problem is that the ingress controller (in this case traefik) access the ghost service via http - ghost expects https.
The fix is to write a traefik middleware that adds a X-Forwarded-Proto header that tells ghost that the site was originally accessed via https:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: proto-forward
namespace: ghost
spec:
headers:
customRequestHeaders:
X-Forwarded-Proto: "https"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ghost-ingress
namespace: ghost
annotations:
traefik.ingress.kubernetes.io/router.middlewares: ghost-proto-forward@kubernetescrd
spec:
rules:
- host: blog.mrupp.eu
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ghost-service
port:
number: 80
Personally I think that the absolute URL configuration is a bad design choice. It not only causes errors like the above one, it also makes it very hard to deploy one ghost instance for multiple domains.