Aims
The goal for today was to get my first piece of software running on the cluster, ensuring that:
- It leveraged the NAS for storage.
- It was accessible externally via Traefik.
- The process was repeatable for future deployments.
I chose the Unifi Management Console as my first self-hosted application. Once migrated, I could wipe my Raspberry Pi 4, which was previously running the console, and add it as a worker node to the cluster.
What I Did
NFS Storage Setup
- I needed NFS storage to persist Unifi’s data.
- After trying multiple providers, I settled on the nfs-subdir-external-provisioner Helm chart.
- I pointed it at my NAS server to handle persistent storage.
Persistent Volume & Claims
- Configuring Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) took some effort.
- Eventually, I got them working with my NAS-hosted NFS.
Ingress & Networking Challenges
- Since K3s includes Traefik by default, I wanted to leverage its built-in ingress controller.
- Initially, I attempted to use IngressRoutes, but Unifi’s self-signed TLS certificate caused issues.
- After much debugging, I realised I needed IngressRouteTCP with TLS passthrough.
- The final working configuration looked like this:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: unifi-ingress-tcp
namespace: unifi
spec:
entryPoints:
- websecure
routes:
- match: HostSNI(`example.com`) # SNI-based routing required
services:
- name: unifi-gui
port: 8443
tls:
passthrough: true # Required to let Unifi handle TLS
Lessons Learned
- NFS Setup Took Iterations – The nfs-subdir-external-provisioner was the best option for easy NAS integration.
- Ingress Troubles – K3s’ built-in Traefik works well, but TLS handling is tricky with self-signed certs.
- IngressRoute vs IngressRouteTCP – If an app manages its own TLS, use IngressRouteTCP with passthrough instead of a standard IngressRoute.
Final Thoughts
Now that I’ve got my first app running, I expect future deployments to be faster and more repeatable. Next, I need to figure out subdomains and path-based routing for managing multiple applications—but that’s a problem for another day!