Auto-Populating Pi-hole DNS from Kubernetes Ingresses

Managing DNS records for a homelab with dozens of services is tedious. Every time you deploy something new, you have to remember to add a DNS record. I solved this by using external-dns to automatically create Pi-hole DNS entries from Kubernetes ingress resources. The Goal When I create an ingress like this: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: frigate annotations: external-dns.alpha.kubernetes.io/hostname: frigate.bowerha.us spec: rules: - host: frigate.bowerha.us # ... I want Pi-hole to automatically create a DNS record pointing frigate.bowerha.us to my ingress controller’s IP. No manual steps, no forgetting to update DNS. ...

January 17, 2026 · Rusty Bower

Building a Self-Updating Dashboard with Homepage and Kubernetes

One of the challenges of running a homelab with dozens of services is keeping track of what’s running and where. I recently deployed Homepage - a modern, fully static dashboard that automatically discovers services from Kubernetes ingresses. Why Homepage? I evaluated several dashboard options including Homarr and Heimdall. Homepage stood out for a few reasons: Kubernetes-native service discovery - no manual configuration needed Real-time pod status - shows if services are actually running Clean, modern UI - dark theme, customizable layout Lightweight - just a static site with no database The Setup Homepage runs as a simple deployment in Kubernetes with a ServiceAccount that has read access to the cluster. The magic happens through ingress annotations. ...

January 17, 2026 · Rusty Bower

From Keel to Renovate: Better Container Image Updates for GitOps

For years I used Keel to automatically update container images in my Kubernetes clusters. It worked, but as I moved to GitOps with ArgoCD, Keel’s push-based approach became a liability. I migrated to Renovate for PR-based image updates, and it’s been a significant improvement. The Problem with Keel Keel watches for new container images and updates deployments directly in the cluster. You can configure it via annotations: metadata: annotations: keel.sh/policy: major keel.sh/trigger: poll When a new image appears, Keel modifies the deployment in-place. ...

January 17, 2026 · Rusty Bower

GitOps for Homelabs: Kustomize + ArgoCD Patterns and Pitfalls

I manage two Kubernetes environments - a home cluster (bowerhaus) and a cloud cluster (rustycloud) - using GitOps with Kustomize and ArgoCD. After running this setup for a while, I’ve learned what works, what doesn’t, and some non-obvious gotchas. The Architecture kustomize/ ├── base/ # Shared, environment-agnostic configs │ ├── media/ │ │ ├── lidarr/ │ │ ├── radarr/ │ │ └── sonarr/ │ ├── home-automation/ │ │ ├── home-assistant/ │ │ └── frigate/ │ └── data-analytics/ │ ├── prometheus/ │ └── grafana/ ├── environments/ │ ├── bowerhaus/ │ │ ├── applicationsets/ # ArgoCD ApplicationSet │ │ └── apps/ # Per-app overlays │ │ ├── frigate/ │ │ ├── home-assistant/ │ │ └── prometheus/ │ └── rustycloud/ │ ├── applicationsets/ │ └── apps/ │ ├── plex/ │ ├── sonarr/ │ └── grafana/ The key principle: base contains environment-agnostic resources, environments contain overlays that customize for each cluster. ...

January 17, 2026 · Rusty Bower

Self-Hosted CI/CD with Drone, Gitea, and Harbor

I run a fully self-hosted CI/CD pipeline using Drone for builds, Gitea for git hosting, and Harbor for container registry. No GitHub Actions, no Docker Hub, no external dependencies. Here’s how it all fits together. The Stack Gitea - Lightweight git server with OAuth2 support Drone - Container-native CI/CD platform Harbor - Enterprise container registry with vulnerability scanning BuildKit - Modern Docker builder for efficient image builds Why Self-Hosted? Privacy - Code never leaves my network No rate limits - Build as often as needed Offline capability - Works during internet outages (for local images) Learning - Understanding the full DevOps stack Cost - No per-minute billing for CI runners Architecture ┌─────────────────────────────────────────────────────────────┐ │ Kubernetes │ │ │ │ ┌──────────┐ ┌─────────────────────────────┐ │ │ │ Gitea │────▶│ Drone │ │ │ │ (git) │ │ ┌───────┐ ┌──────────┐ │ │ │ └──────────┘ │ │Server │ │ Runner │ │ │ │ │ └───────┘ └────┬─────┘ │ │ │ └────────────────────│────────┘ │ │ │ │ │ ┌──────────┐ ┌──────▼─────┐ │ │ │ Harbor │◀──────────────────│ BuildKit │ │ │ │(registry)│ │ (builds) │ │ │ └──────────┘ └────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ Push code to Gitea Gitea webhook triggers Drone Drone spawns a build job via the Kubernetes runner BuildKit builds the container image Image is pushed to Harbor ArgoCD deploys the new image (separate workflow) Gitea Setup Gitea is straightforward - a single deployment with PostgreSQL backend. The key configuration is creating an OAuth2 application for Drone: ...

January 17, 2026 · Rusty Bower