Live build log

Kubernetes homelab

Why

I wanted to build a Kubernetes platform myself, from the hardware up, instead of consuming a managed one.

Everything here is set up manually before any Infrastructure as Code. The point is to understand each layer before writing the tool that replaces me.

01

Stack

deployed in progress planned
LAYER 01

Hardware and hypervisor

Dual Xeon Silver 4116, 128 GB RAM, running Proxmox VE. Key-only SSH, deny-by-default firewall, TOTP on the root account.

DECISION: WHY AN EXTERNAL SSD

Proxmox runs from a dedicated external SSD, booted on demand. The Windows install on the internal drives stays untouched. No dual boot, no partitioning. It also means the lab is not running around the clock: every session starts with a full boot of the cluster, which makes it a reproducibility test as much as a lab.

DEPLOYED
LAYER 02

k3s cluster

Three Debian VMs provisioned from the Proxmox CLI with cloud-init. One server, two agents, SQLite datastore.

DEPLOYED
LAYER 03

Ingress and TLS

Traefik as ingress controller, cert-manager issuing and renewing Let's Encrypt certificates over the DNS-01 challenge on Route 53. The cluster stays private, but every service is reachable over HTTPS on a real domain, with an IAM user scoped to a single hosted zone.

DEPLOYED
LAYER 04

GitOps

Gitea deployed via Helm as the internal forge, ArgoCD watching a single repository as the source of truth and reconciling the cluster against it.

DEPLOYED
LAYER 05

Continuous integration

Gitea Actions enabled, a self-hosted Gitea Runner registered against the organisation in rootless Docker-in-Docker mode, with per-job container isolation.

DECISION: RUNNER TOPOLOGY

Privileged Docker-in-Docker gives the pod near-total access to the host, so it was out. A pod-per-job runner is the cloud-native answer, but it ships only with the Enterprise edition. That leaves rootless DinD: no privileged pod, real isolation between jobs.

DEPLOYED
LAYER 06

Supply chain security

Image builds pushed to a registry, vulnerability scanning and signing before deployment. Buildah in rootless mode is the next step, once the daemon-based path is fully understood.

BUILDING
LAYER 07

Observability

Prometheus and Grafana, on a node outside the cluster they monitor.

PLANNED
LAYER 08

Infrastructure as Code

Terraform and Ansible, once the manual flow is fully understood.

PLANNED
02

Architecture

How the stack is built, from the disk it boots off to the cluster on top.

Proxmox VE 2 x Xeon Silver 4116, 128 GB RAM, 3 Debian VMs, 192.168.1.200 k3s cluster SQLite datastore, no HA k3s-server-1 .211, 4 vCPU, 8 GB k3s-agent-1 .212, 4 vCPU, 8 GB k3s-agent-2 .213, 4 vCPU, 8 GB External SSD Proxmox root, booted on demand Key-only SSH, deny-by-default firewall, TOTP on root

How a change reaches the cluster. CI writes to Git and to the registry, and stops there.

Gitea Manifests, source of truth writes image tag watches CI No cluster credentials Gitea Runner Rootless DinD Build, scan, sign Grype, cosign Delivery Runs inside the cluster ArgoCD Applies what Git declares Workloads Converge to declared state Registry Gitea built-in, then Harbor pushes pulls
← Back to projects