portfolio pass: correct the CSP claim to match what nginx sends, rename the project outcome label, plain-english the projects intro and bio, standardise on Argo CD and single-touch, drop the education filler line
build-and-deploy / build (push) Failing after 14m34s
build-and-deploy / build (push) Failing after 14m34s
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: "Shipping this site: GitOps from a homelab to the public internet"
|
||||
date: 2026-06-15
|
||||
summary: "How this portfolio is built and served - Astro to a container image, a self-hosted Gitea registry, ArgoCD, and a Cloudflare Tunnel - with security as acceptance criteria, not polish."
|
||||
summary: "How this portfolio is built and served - Astro to a container image, a self-hosted Gitea registry, Argo CD, and a Cloudflare Tunnel - with security as acceptance criteria, not polish."
|
||||
tags: ["gitops", "astro", "homelab", "security"]
|
||||
hero: "/blog/shipping-this-site.webp"
|
||||
heroAlt: "A glowing data container travels a luminous rail from a small server rack toward a softly glowing globe of Earth, wrapped by a reconcile loop."
|
||||
@@ -18,7 +18,7 @@ by GitOps. No special case for "it's just a website."
|
||||
The build is baked into a hardened `nginx-unprivileged` image and pushed to a **self-hosted public
|
||||
Gitea registry**, deliberately a separate instance from the private one holding my infrastructure
|
||||
code, so the public artifact and the private estate never share a trust boundary. The image digest
|
||||
is then pinned in a private `home-ops` repo, **ArgoCD** reconciles that repo onto the cluster, and
|
||||
is then pinned in a private `home-ops` repo, **Argo CD** reconciles that repo onto the cluster, and
|
||||
a **Cloudflare Tunnel** exposes exactly one service, this site, outbound-only.
|
||||
|
||||
Follow the chain and notice what's missing. No open ports: the tunnel dials out. No server runtime:
|
||||
@@ -33,7 +33,7 @@ gesture at. The site didn't ship until every box was ticked:
|
||||
|
||||
```text
|
||||
[x] Static output - no server runtime to attack
|
||||
[x] Strict CSP, no unsafe-inline / unsafe-eval
|
||||
[x] CSP: script-src 'self', no inline or eval JavaScript (style-src keeps 'unsafe-inline' for Shiki)
|
||||
[x] Self-hosted fonts - zero third-party requests
|
||||
[x] No secrets in the client bundle (verified by build-time grep)
|
||||
[x] Outbound-only tunnel, single hostname, no catch-all
|
||||
|
||||
@@ -48,7 +48,7 @@ traffic on the way out), pin-downable with a `/32`. That's how the LLM gateway's
|
||||
be a single line: one legitimate consumer, the agent cluster next door, exactly one `/32` allowed in.
|
||||
|
||||
Here's the one that costs a 2am. I made that change with `kubectl patch` - quick, out-of-band, worked
|
||||
immediately. The service was GitOps-managed with self-heal on. Within seconds ArgoCD noticed the live
|
||||
immediately. The service was GitOps-managed with self-heal on. Within seconds Argo CD noticed the live
|
||||
object differed from git and put it back the way the repo said, which re-enabled the SNAT, which
|
||||
re-broke the policy, which took DNS down with it. **The change must be committed**, or the platform
|
||||
will politely undo your fix while you sleep.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: "Single-Touch Edge AI Platform"
|
||||
outcome: "Turned a high-level edge-AI design into a single-press deployment running on Kubernetes at the store edge."
|
||||
outcome: "Turned a high-level edge-AI design into a single-touch deployment running on Kubernetes at the store edge."
|
||||
summary: "Store-edge Kubernetes running GPU-backed AI workloads, deployed from one command, with readiness-gated GPUs so inference never starts before the hardware is ready."
|
||||
role: "Infrastructure / DevOps Engineer · Woolworths"
|
||||
period: "2025 - Present"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "Self-Hosted AI & Homelab Platform"
|
||||
outcome: "A production-grade homelab - GitOps from bare metal to local AI, and the platform that serves this very site."
|
||||
summary: "Proxmox with PCIe passthrough under Talos and OpenShift clusters, all driven by ArgoCD GitOps: local LLM inference, split-horizon DNS, 2FA/SSO VPN, full observability and NAS-backed backups."
|
||||
summary: "Proxmox with PCIe passthrough under Talos and OpenShift clusters, all driven by Argo CD GitOps: local LLM inference, split-horizon DNS, 2FA/SSO VPN, full observability and NAS-backed backups."
|
||||
role: "Owner / Operator"
|
||||
period: "Ongoing"
|
||||
stack: ["Talos", "OpenShift", "ArgoCD", "Proxmox", "Local LLM", "Cloudflare Tunnel"]
|
||||
stack: ["Talos", "OpenShift", "Argo CD", "Proxmox", "Local LLM", "Cloudflare Tunnel"]
|
||||
featured: true
|
||||
order: 15
|
||||
cover: "self-hosted-ai-homelab"
|
||||
@@ -26,7 +26,7 @@ genuine proving ground for Kubernetes, GPUs, AI and security, not a pile of cont
|
||||
## Design
|
||||
|
||||
Proxmox provides the hypervisor layer with **PCIe passthrough** (GPU and storage) into
|
||||
single-node **Talos** and **OpenShift** clusters. Everything is **ArgoCD GitOps** - the
|
||||
single-node **Talos** and **OpenShift** clusters. Everything is **Argo CD GitOps** - the
|
||||
cluster state lives in git and reconciles itself. On top: **local LLM inference** on a
|
||||
Blackwell-class GPU, **split-horizon DNS** via Pi-hole, a VPN with **2FA/SSO**, and a
|
||||
**Prometheus / Grafana** observability stack. ZFS handles storage tiering; restic ships
|
||||
|
||||
Reference in New Issue
Block a user