+
Alles, was unter *.plate-software.de erreichbar ist, läuft auf einem TrueNAS bei mir zu Hause. Öffentlich wird das Ganze über einen winzigen VPS, der nichts anderes tut, als einen frps-Tunnel zu halten — davor steht ein IONOS-Reverse-Proxy, der TLS terminiert. Ein git push nach Gitea, der Runner baut das Docker-Image, und in unter einer Minute steht die neue Version öffentlich unter HTTPS.
+
Everything you can reach under *.plate-software.de runs on a TrueNAS at home. The whole thing is exposed publicly through a tiny VPS whose only job is to hold an frps tunnel — fronted by an IONOS reverse-proxy that terminates TLS. A git push to Gitea, the runner builds the Docker image, and in under a minute the new version is live on public HTTPS.
+
+
Der Stack
+
The stack
+
TrueNAS SCALE hostet Gitea, den act_runner und pro App einen Docker-Stack. Der VPS fährt ausschließlich frps (frp-Server) — kein Anwendungs-Code, keine Datenbank, einfach nur Tunnel-Endpunkt. Eingehender Traffic landet zuerst auf IONOS-Apache-vHosts, die per Reverse-Proxy in den frps-Tunnel zeigen. Let's-Encrypt-Zertifikate kommen via acme.sh.
+
TrueNAS SCALE hosts Gitea, the act_runner, and a per-app Docker stack. The VPS runs only frps (the frp server) — no application code, no database, just a tunnel endpoint. Public traffic enters IONOS Apache vhosts that reverse-proxy into the frps tunnel. Let's Encrypt certificates via acme.sh.
+
+
Warum so?
+
Why this setup?
+
Vor allem die Kosten: rund 10 €/Monat für VPS und Domain — bei einer vergleichbar gemanageten Hosting-Lösung wären es eher 80 €. Dazu volle Kontrolle, kein Vendor-Lock-in und ehrlich gesagt: Infrastruktur zu bauen ist die halbe Miete vom Spaß.
+
Mostly cost: about €10/month for VPS plus domain, versus around €80/month for an equivalent managed hosting setup. Add full control, no vendor lock-in, and frankly — building the infrastructure is half of why this is fun.
+
+
Was ich gelernt habe
+
Lessons learned
+
Zwei systemische Stolpersteine sind hängen geblieben: in einer Proxy-Kette muss auth() von NextAuth verwendet werden, getToken() bricht durch die mehrfachen Hops. Und die DNS-A-Records zeigen auf IONOS, nicht auf den VPS — wer das vergisst, wundert sich lange über kaputtes Routing.
+
Two systemic gotchas have stuck with me: in a proxy chain you need NextAuth's auth(), not getToken() — the latter breaks across the multiple hops. And the DNS A-records point to IONOS, not the VPS — forget that and you'll spend a long time wondering why routing is broken.
+