A complete homelab built on a single Proxmox node — no cloud, no managed services. Two active VMs running 30 Docker services, a full k3s Kubernetes cluster managed by Rancher, GitLab CI/CD pipelines deploying Zabbix environments via Terraform and Helm, and 16 publicly accessible subdomains behind Cloudflare Tunnel. Everything documented here is real, running, and maintained as a learning platform.
Single flat /24 LAN · all VMs on vmbr0 bridge · k3s uses Flannel CNI (10.42.0.0/16) · all external access via Cloudflare Tunnel, no open inbound ports
All subdomains protected by Authentik SSO (except where noted). No inbound firewall ports — all traffic via Cloudflare Tunnel.
Single bare-metal node · 8 vCPUs (4 cores + HT) · 23.3 GB RAM · ~960 GB ci-storage pool · Legacy BIOS · pve-manager/9.1.5
| VMID | Name | Status | RAM | Disk | Notes |
|---|---|---|---|---|---|
| 400 | homelab-docker | ● running | 10 GB | 150 GB | Docker host · GitLab Runner · 192.168.178.215 · Ubuntu 24.04 |
| 500 | cicd-automation | ● running | 10 GB | 320 GB | k3s v1.34 · Rancher 2.14 · 192.168.178.220 · Debian 12 |
| 200 | terra-automation | stopped | 4 GB | 35 GB | Archived — early Terraform VM experiments |
| 203 | terra-monitoring | stopped | 4 GB | 30 GB | Archived — standalone monitoring VM experiment |
| 204 | terra-k8s-master | stopped | 4 GB | 40 GB | Archived — multi-node K8s experiment (master node) |
| 205 | terra-k8s-worker1 | stopped | 1 GB | 15 GB | Archived — multi-node K8s worker 1 |
| 206 | terra-k8s-worker2 | stopped | 1 GB | 15 GB | Archived — multi-node K8s worker 2 |
| 300 | debian-12-template | stopped | 2 GB | 20 GB | Base template for cloning new VMs |
| 301 | zabbix-db | stopped | 1 GB | 20 GB | Archived — standalone Zabbix DB experiment |
| 302 | zabbix-server1 | stopped | 512 MB | 20 GB | Archived — Zabbix HA experiment server 1 |
| 303 | zabbix-server2 | stopped | 512 MB | 20 GB | Archived — Zabbix HA experiment server 2 |
| 304 | zabbix-web | stopped | 512 MB | 20 GB | Archived — Zabbix HA web frontend experiment |
No LXC containers in use. All workloads run as full VMs. Archived VMs document the evolution from standalone Zabbix/K8s VMs to the current consolidated architecture.
VM 400 · Ubuntu 24.04 · 192.168.178.215
Traefik · Cloudflare Tunnel · Authentik · CrowdSec · Pihole
Graylog · MongoDB · Netdata · Uptime Kuma · zabbix-postgres:5432
Immich · Jellyfin · Actual Budget · FinanzBlick
Ollama · n8n · Telegram bot · Proxmox API
Executes CI/CD jobs → kubeconfig → VM 500
Portainer · Homepage · Watchtower ⚠ restart loop
VM 500 · Debian 12 · 192.168.178.220
Traefik LB · cert-manager · K8s Dashboard · metrics-server
9 revisions · ✓ healthy
2 revisions · ✓ healthy
prod env · ✓ healthy
Terraform v1.15 · Helm v3.20 · GitLab HTTP state
Plan (auto) → Apply (manual) · 360+ runs
Fleet · CAPI (rancher-turtles) · upgrade-controller
Ubuntu 24.04 · 10 GB RAM (4.1 GB used) · 148 GB disk (47% used) · Kernel 6.8.0-111 · Two Compose stacks: home-lab (25 services) + crowdsec (2 services)
Debian 12 · 10 GB RAM (7.3 GB used) · 320 GB disk (12% used) · Kernel 6.1.0-44-amd64 · containerd 2.2.2 · Single control-plane node · 34d uptime
| Release | Namespace | Chart | App version | Rev. | Status |
|---|---|---|---|---|---|
| zabbix-dev | zabbix-dev | zabbix-7.0.12 | 7.0.16 | 9 | ✓ healthy |
| zabbix-staging | zabbix-staging | zabbix-7.0.12 | 7.0.16 | 2 | ✓ all healthy |
| zabbix-prod | zabbix-prod | zabbix-7.0.12 | 7.0.16 | 1 | ✓ healthy |
| rancher | cattle-system | rancher-2.14.1 | v2.14.1 | 3 | ✓ healthy |
| fleet | cattle-fleet-system | fleet-109.0.1 | 0.15.1 | 4 | ✓ healthy |
| rancher-turtles | cattle-turtles-system | rancher-turtles-109.0.1 | 0.26.1 | 2 | ✓ healthy |
| rancher-webhook | cattle-system | rancher-webhook-109.0.1 | 0.10.4 | 3 | ✓ healthy |
| traefik | kube-system | traefik-39.0.501 | v3.6.10 | 1 | ✓ healthy |
| system-upgrade-controller | cattle-system | system-upgrade-controller-109.0.1 | v0.19.1 | 2 | ✓ healthy |
| Namespace | Host | Ports | Address |
|---|---|---|---|
| cattle-system | rancher.abc-server.date | 80, 443 | 192.168.178.220 |
| zabbix-dev | zabbix-dev.abc-server.date | 80 | 192.168.178.220 |
| zabbix-staging | zabbix-staging.abc-server.date | 80 | 192.168.178.220 |
| zabbix-prod | zabbix-prod.abc-server.date | 80 | 192.168.178.220 |
GitLab Runner on VM 400 executes jobs targeting VM 500 via kubeconfig · Terraform manages K8s state · Remote state in GitLab HTTP backend
terraform plan — auto, shows diff, no changeterraform apply → Helm release update| Version | v1.15.1 (v1.15.4 available) |
| Backend | GitLab HTTP (remote state) |
| Providers | hashicorp/helm + hashicorp/kubernetes |
| Resources | helm_release + kubernetes_ingress_v1 |
| Chart | zabbix-community/zabbix v7.0.12 |
| Secrets | Masked CI/CD variables in GitLab |
| Total runs | 360+ pipeline executions |
All three environments share the same Terraform config and Helm chart. The namespace variable switches between them.
| Env | Namespace | DB | Revisions | Current state |
|---|---|---|---|---|
| zabbix-dev | zabbix-dev | 192.168.178.215:5432 | 9 | ✓ All pods healthy |
| zabbix-staging | zabbix-staging | 192.168.178.215:5432 | 2 | ✓ All 3 pods healthy |
| zabbix-prod | zabbix-prod | 192.168.178.215:5432 | 1 | ✓ All pods healthy |
Real infrastructure experiments — built to understand, not to impress. AI-assisted where noted. These projects are also featured on the main portfolio page.
Homelab CI/CD project — GitLab pipelines trigger Terraform + Helm to deploy Zabbix 7.4 to a Kubernetes cluster (Rancher). Three isolated environments (zabbix-dev, zabbix-staging, and zabbix-prod) deployed fully from code. Apply stage is manual — plan runs automatically. All secrets stored as masked CI/CD variables. GitLab Runner runs on the Docker host (VM 400); the runner executes Terraform and Helm commands that target the k3s cluster on a separate VM (VM 500 / cicd-automation) via kubeconfig. Terraform state is stored remotely in GitLab's HTTP backend. Built to learn IaC and K8s deployment pipelines hands-on.
Custom dashboard built on top of the Zabbix API — shows live CPU, RAM, disk, ping, problems and maintenance status for all monitored hosts. Includes per-host drawer with enable/disable/maintenance actions. AI-assisted development — I designed the architecture and monitoring logic; code generated with AI help.
Self-hosted Docker Compose platform running 30+ services on a single VM (Ubuntu 24.04, 10 GB RAM). Traefik as reverse proxy, Cloudflare Tunnel for zero-trust external access, Authentik SSO protecting every service, CrowdSec for intrusion detection. Graylog + OpenSearch for centralised log aggregation, Netdata + Uptime Kuma for real-time monitoring. Notable apps: Immich (photo backup), Jellyfin (media), Actual Budget, Pihole DNS, Portainer, and a Homepage dashboard aggregating all services.
Infrastructure: Single Proxmox node (PVE 9.1, 8 vCPUs, 24 GB RAM, ~960 GB storage) running two active VMs: homelab-docker (all Docker services + GitLab Runner) and cicd-automation (k3s cluster + Terraform + Helm). Previously explored multi-VM Zabbix HA and multi-node K8s setups — consolidated to the current architecture.
n8n workflow that queries the Docker socket proxy daily at 15:00, sends container health data to a local Ollama LLM for analysis, then pushes a formatted status report to Telegram. A second flow responds to on-demand commands like /proxmox with live VM CPU/RAM/status from the Proxmox API. No coding required — built entirely with n8n's visual workflow builder.
Self-hosted personal finance app — PDF/CSV import from ING bank, monthly analytics, savings rate, recurring transaction detection, and year-over-year comparisons. AI-assisted development — I designed the features and data model; code generated with AI help. Runs as a container in K8s, deployed manually.
Progressing from enterprise monitoring expert into Kubernetes/DevOps/IaC territory — building evidence through real homelab projects, not just tutorials.
Two live workflows running in the homelab — one scheduled daily report, one on-demand Telegram command handler. No coding required — built entirely with n8n's visual workflow builder.
Every day at 15:00, n8n queries the Docker socket proxy to get the status of all 30 containers, passes the data through JavaScript to prepare and aggregate it, sends it to the local Ollama LLM for analysis, then pushes a formatted health report to Telegram.
Send /proxmox to the Telegram bot and get an instant reply with live VM stats — CPU %, RAM %, disk usage, and running/stopped status for all 12 VMs — pulled directly from the Proxmox API.