Skip to content

mdapi Homelab

A self-hosted, production-grade Kubernetes homelab running on bare metal — built around GitOps, zero-trust secrets, and modern DevSecOps practices.

What is this?

This site documents the architecture of mdapi, a personal homelab that runs a full-stack cloud-native environment at home. It is intended as a reference for architecture decisions, security practices, and operational patterns — not a tutorial, but a real-world example of how these technologies fit together.

The stack is built to mirror enterprise-grade principles: declarative GitOps configuration, hardware-backed secret management, automated certificate lifecycle, container image CVE scanning, and a multi-cluster management plane.

Stack at a Glance

Layer Technology
Kubernetes distribution Harvester HCI (RKE2 + KubeVirt)
Cluster management Rancher
GitOps Fleet (multi-cluster)
Ingress ingress-nginx + ModSecurity WAF
TLS cert-manager + Let's Encrypt (DNS-01 via RFC 2136)
Storage Longhorn (block, 2-replica) + MinIO (S3) + TrueNAS (NFS/iSCSI via democratic-csi)
Secrets Akeyless with customer fragment on CipherTrust Manager
Identity Keycloak (OIDC/SSO) + OpenLDAP
Image updates Keel (digest-based polling) + Diun
CI/CD GitLab (self-hosted EE) with Grype+Syft CVE scanning
Automation Windmill (scheduled infrastructure health monitoring)
Edge router BPI-R4 running OpenWrt 25.12 (custom fork)
External access sslh (protocol demux: HTTPS / SSH / OpenVPN on a single port)

Cluster Contexts

Three Kubernetes clusters, all managed through Rancher and Fleet:

Cluster Location Purpose
mdapi-rancher Local (Rancher management) Fleet controller, cluster-scoped resources
mdapi-prod Bare metal (homelab) All production workloads
mdapi-test / mdapi-dev Rackspace Spot Ephemeral test/dev environments

Design Principles

Everything is declarative. All cluster state lives in the mdapi/fleet GitLab repo. No kubectl apply is ever run directly — every change is a git commit.

Secrets never touch git. Secrets are stored in Akeyless SaaS with an on-premise customer fragment (the plaintext never leaves the local network). Kubernetes workloads fetch them via the External Secrets Operator at runtime.

TLS everywhere, automated. cert-manager issues certificates for every service via Let's Encrypt DNS-01 challenges, signed against a self-hosted BIND9 authoritative nameserver with TSIG.

Security is layered. ModSecurity WAF on all ingresses, OIDC for user-facing apps, CVE scanning in every CI pipeline, network-level protocol demultiplexing at the edge.

Source