[ ['label' => 'lab.sh', 'path' => 'lab.sh'], ['label' => 'cluster/main.tf', 'path' => 'bootstrap/cluster/main.tf'], ['label' => 'provisioning/main.tf', 'path' => 'bootstrap/provisioning/main.tf'], ], 'blog_stack_2' => [ ['label' => 'cluster/main.tf', 'path' => 'bootstrap/cluster/main.tf'], ['label' => 'provisioning/main.tf', 'path' => 'bootstrap/provisioning/main.tf'], ], 'blog_stack_3' => [ ['label' => 'lab.sh', 'path' => 'lab.sh'], ['label' => 'cluster', 'path' => 'bootstrap/cluster/main.tf'], ['label' => 'platform', 'path' => 'bootstrap/platform/main.tf'], ['label' => 'apps', 'path' => 'bootstrap/apps/main.tf'], ['label' => 'provisioning', 'path' => 'bootstrap/provisioning/main.tf'], ['label' => 'edge', 'path' => 'bootstrap/edge/main.tf'], ], 'blog_stack_4' => [ ['label' => 'platform/main.tf', 'path' => 'bootstrap/platform/main.tf'], ], 'blog_stack_5' => [ ['label' => 'apps/main.tf', 'path' => 'bootstrap/apps/main.tf'], ], 'blog_stack_6' => [ ['label' => 'edge/main.tf', 'path' => 'bootstrap/edge/main.tf'], ['label' => 'nginx template', 'path' => 'bootstrap/edge/templates/default.conf.tftpl'], ['label' => 'HAProxy template', 'path' => 'bootstrap/edge/templates/haproxy.cfg.tftpl'], ], 'blog_stack_7' => [ ['label' => 'cv-theme.js', 'path' => 'apps/website/cv-theme.js'], ['label' => 'cv.php', 'path' => 'apps/website/cv.php'], ['label' => 'styles.css', 'path' => 'apps/website/styles.css'], ], 'blog_stack_8' => [ ['label' => 'media-cruncher.js', 'path' => 'apps/demos-static/public/media-cruncher/media-cruncher.js'], ['label' => 'media-cruncher page', 'path' => 'apps/demos-static/public/media-cruncher/index.html'], ], 'blog_stack_9' => [ ['label' => 'demo catalog', 'path' => 'apps/demos-static/public/index.html'], ['label' => 'network-quality.js', 'path' => 'apps/demos-static/public/network-quality/network-quality.js'], ['label' => 'dev-toolbelt.js', 'path' => 'apps/demos-static/public/dev-toolbelt/dev-toolbelt.js'], ['label' => 'architecture-simulator.js', 'path' => 'apps/demos-static/public/architecture-simulator/architecture-simulator.js'], ], 'blog_stack_10' => [ ['label' => 'sentiment-sandbox.js', 'path' => 'apps/demos-static/public/sentiment-sandbox/sentiment-sandbox.js'], ['label' => 'model-drift.js', 'path' => 'apps/demos-static/public/model-drift/model-drift.js'], ['label' => 'privacy-redactor.js', 'path' => 'apps/demos-static/public/privacy-redactor/privacy-redactor.js'], ], 'blog_stack_11' => [ ['label' => 'demos Dockerfile', 'path' => 'apps/demos-static/Dockerfile'], ['label' => 'demos web-app.yaml', 'path' => 'apps/demos-static/web-app.yaml'], ['label' => 'website demos.php', 'path' => 'apps/website/demos.php'], ], 'blog_stack_12' => [ ['label' => 'provisioning/main.tf', 'path' => 'bootstrap/provisioning/main.tf'], ['label' => 'lab.sh Pimox pipeline', 'path' => 'lab.sh'], ], 'blog_stack_13' => [ ['label' => 'preseed.cfg', 'path' => 'bootstrap/provisioning/templates/preseed.cfg.tftpl'], ['label' => 'golden-node prepare', 'path' => 'bootstrap/provisioning/templates/golden-node-prepare.sh.tftpl'], ['label' => 'prepare-template', 'path' => 'bootstrap/provisioning/templates/prepare-template.sh.tftpl'], ], ]; function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $sourceBase): void { if (!isset($sourceLinks[$stackKey])) { return; } echo ''; } ?> <?php echo $text['blog_title']; ?> - <?php echo $text['name']; ?>

Homelab architecture map Git push enters Gitea, Gitea Actions validates and builds app images, OpenTofu manages the cluster and provisioning layers, Debian serves PXE and preseed content, Pimox builds Debian VM templates, Argo CD syncs manifests, and the OCI edge routes traffic into Kubernetes services. Source, validation, and images Debian node 192.168.100.68 Edge access and workloads Developer laptop edit, test, push main Gitea repository https://lab2025.duckdns.org/git/ main is the release branch Gitea Actions runner Debian hosted runner runs app-only deploys Validation gates Gitleaks secret scan Trivy IaC and image posture Buildx image build linux/arm64 website + demos OpenTofu + lab.sh manual infra apply path apps command for CI deploys PXE + preseed service dnsmasq TFTP, nginx HTTP Debian 13 arm64 netboot golden-node prep scripts kubeadm control plane API server, scheduler, controller Calico pod networking GitOps mirror validated commit copied locally Argo CD reads deploy state Argo CD container-registry, website gitea and demos-static apps Storage and backups OpenEBS retained hostpath PVs Gitea dumps and external SSD OCI edge host nginx, HAProxy, Varnish, Squid TLS, routing, caching public DNS entry point Tailscale + NodePorts 30080 website, 30081 demos 30300 Gitea service path Raspberry Pi 192.168.100.89 arm64 Kubernetes worker website-production pods demos-static and lab apps Orange Pi 5 Plus Pimox VM 9000 Debian template OVMF, virtio-scsi, qemu agent future worker clones waiting on more disk Local registry :30500 php-website and demos-static pulled by arm64 workloads push workflow scan build manual infra validated Git serve boot join path Pimox template sync apps secure tunnel service traffic image pulls

    $activityKey): ?>