infrastructure
This site is the case study.
No Vercel, no Netlify. The page you are reading was built by CI, pushed to a registry, and reconciled by ArgoCD onto a self-hosted Talos Kubernetes cluster in Oslo. The status below is read from that cluster.
Serving build
dbcaf27
pinned to commit SHA
ArgoCD app
Synced
healthy · auto-sync
Cluster nodes
6 / 6 ready
Talos Linux · Kubernetes
TLS certificate
auto
auto-renews · Let's Encrypt
the request path
How this page reached you.
Every request crosses this chain. Each hop maps to a manifest in the repo.
You
HTTPS request to nordbye.it
TLS 1.3
DNS
Cloudflare DNS points straight at the cluster's public IP
no CDN in front
Cilium LB
L2-announced VIP, eBPF load-balancing into the cluster
LoadBalancer IPAM
Traefik
Gateway API HTTPRoute, certificate from cert-manager
gateway.networking.k8s.io
portfolio pod
Hardened Node runtime serving the Next.js app
read-only rootfs
the deploy path
How a commit becomes this page.
Nothing is applied by hand. A push to main is the only deploy action that exists. ArgoCD reconciles the rest.
01
git push
Commit to main in the homelab monorepo
02
GitHub Actions
Builds the image and updates the manifest tag in the same run
03
GHCR
Image pushed and pinned to the commit SHA, never :latest
04
ArgoCD
Detects the manifest change in Git and syncs the Application
app-of-apps
05
Talos cluster
Rolling update, zero downtime. You're looking at the result.
genesis
how the numbers get here
A live pulse, no cluster keys in the open.
This site runs as a Next.js server, but the pod serving it still has no access to the Kubernetes API. A small CronJob inside the cluster gathers the facts every few minutes, from the Kubernetes API, ArgoCD, and cert-manager, and writes them to a ConfigMap. The API reads that ConfigMap and serves it at /api/v1/infra.
The page fetches that endpoint client-side. If the fetch fails, the tiles fall back to a build-time snapshot and say so. The page never breaks because the homelab is having a bad day.
design decisions
Serving a status endpoint doesn't mean handing it cluster credentials. The web pod only reads a ConfigMap the publisher writes; it holds no Kubernetes API access of its own. The publisher's RBAC reads the objects it reports on, pinned to resource names where the API allows it, and writes one ConfigMap.
The pill checks the timestamp too. Data older than 15 minutes is reported as stale rather than shown as operational.
{
"generatedAt": "2026-07-13T05:55:03Z",
"build": "72088b9",
"deployedAt": "2026-07-12T19:33:47Z",
"argocd": {
"sync": "Synced",
"health": "Healthy",
"syncedAt": "2026-07-12T19:32:48Z"
},
"nodes": { "ready": 6, "total": 6 },
"versions": { "talos": "v1.11.6", "kubernetes": "v1.34.0" },
"cert": { "notAfter": "2026-09-25T11:41:28Z" },
"history": [{ "d": "2026-07-13", "ok": 71, "total": 71 }, ...]
}the platform underneath
What keeps it honest.
The moving parts behind the diagrams above. Every manifest lives in the homelab repo.
Talos Linux
Immutable, API-managed Kubernetes OS. No SSH, no shell, no drift.
Cilium
eBPF CNI, L2 announcements and LB-IPAM for bare-metal VIPs.
Traefik
Gateway API implementation. HTTPRoutes, not Ingress annotations.
ArgoCD
App-of-apps GitOps. Git is the only write path to the cluster.
cert-manager
ACME certificates issued and rotated without human hands.
External Secrets
Secrets synced from an upstream store. None live in Git.
Prometheus + Grafana
kube-prometheus-stack, with dashboards versioned as code.
Loki + OTel
Log aggregation and traces via the OpenTelemetry collector.