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!