• Go Template 73.9%
  • Shell 19%
  • Nix 4.5%
  • Makefile 2.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Morten Olsen 93053008bc
Some checks failed
Release Charts / release (push) Failing after 7s
ci/woodpecker/push/scan Pipeline was successful
fix: increase shared PostgreSQL connection capacity
2026-09-05 09:35:02 +02:00
.devcontainer init 2025-12-27 14:03:08 +01:00
.github/workflows Update all-major (#17) 2026-04-23 18:12:05 +02:00
.woodpecker Add advisory Trivy scan workflow 2026-04-30 11:25:45 +02:00
charts fix: increase shared PostgreSQL connection capacity 2026-09-05 09:35:02 +02:00
docs updates 2026-07-14 17:13:50 +02:00
scripts manage argo 2026-03-23 22:21:45 +01:00
.gitignore init 2025-12-27 14:03:08 +01:00
AGENTS.md add monitoring 2026-01-06 23:30:46 +01:00
flake.lock init 2025-12-27 14:03:08 +01:00
flake.nix updates 2026-07-14 17:13:50 +02:00
Makefile init 2025-12-27 14:03:08 +01:00
README.md Switch ServiceEntries to STATIC resolution via gatewayAddress 2026-04-22 18:43:42 +02:00
renovate.json chore(config): migrate Renovate config (#18) 2026-05-05 08:03:29 +02:00

Homelab Platform

Note: This project powers my personal homelab. It is shared as a reference and starting point, not as a supported product. Breaking changes happen without warning and versions are not guaranteed to be stable. If you want to use this, fork it rather than depending on it directly.

A turnkey Kubernetes platform built with Helm and ArgoCD. Provides a complete, standards-based foundation for running applications on Kubernetes — from a single-node homelab to a production cluster.

What you get: GitOps deployment, service mesh with ingress, TLS certificates, OIDC authentication, managed databases, monitoring and alerting, security scanning, encrypted backups, and DNS management — all controlled through feature flags in a single values file.

What you deploy on top: Applications using the homelab-common library chart, which abstracts Kubernetes resources into a high-level interface, or raw Kubernetes manifests when you need full control.

Helm Repository

All charts are published to a Helm repository:

helm repo add homelab https://mortenolsen.pro/homelab-core/
helm repo update
helm search repo homelab/

Published charts:

Chart Description
homelab/homelab Umbrella chart — the entry point for deploying the platform
homelab/homelab-core Operators sub-chart (wave 0)
homelab/homelab-shared Platform resources sub-chart (wave 1)
homelab/homelab-monitor Monitoring stack sub-chart (wave 2)
homelab/homelab-common Library chart for deploying applications on the platform

Architecture

┌─────────────────────────────────────────────┐
│           homelab (Umbrella Chart)           │
│     Feature flags + platform config          │
│     Creates ArgoCD Applications              │
└──────────────┬──────────────────────────────┘
               │
       ┌───────┴──────────┬──────────────┐
       │                  │              │
   ┌───▼────────┐   ┌────▼─────────┐  ┌─▼──────────┐
   │  operators  │   │   platform   │  │  monitoring │
   │  (wave 0)   │   │   (wave 1)   │  │  (wave 2)  │
   │             │   │              │  │            │
   │  ArgoCD     │   │  Gateways    │  │ Prometheus │
   │  Istio      │   │  Certs       │  │ Grafana    │
   │  cert-mgr   │   │  Databases   │  │ Alertmgr   │
   │  CNPG       │   │  Auth        │  │ Blackbox   │
   │  Kyverno    │   │  DNS         │  │            │
   │  ...        │   │  Backups     │  │            │
   └─────────────┘   └──────────────┘  └────────────┘

Charts deploy in sync-wave order: operators first (installing CRDs), then platform resources that depend on those CRDs, then monitoring last.

Quick Start

Prerequisites

  • Kubernetes cluster (K3s, Kind, or any conformant distribution)
  • ArgoCD installed on the cluster
  • Helm 3.x
  • A domain with DNS management (Cloudflare for default TLS setup)

1. Add the Helm repo

helm repo add homelab https://mortenolsen.pro/homelab-core/
helm repo update

2. Configure

Create a values file for your cluster:

# my-cluster.yaml
source:
  repoUrl: https://github.com/<your-fork>/homelab-core.git
  targetRevision: main

platform:
  domain: example.com
  ip: 10.0.0.1
  gatewayAddress: ""  # set after first deploy — see note below
  email: admin@example.com
  timezone: UTC
  acme: staging  # use "prod" once DNS is verified

features:
  gitops: true
  serviceMesh: true
  certificates: true
  auth: true
  postgres: true
  mariadb: false       # disable what you don't need
  monitoring: true
  security: true
  secrets: true
  backup: true
  dns: true
  reflection: true
  reloader: true
  storage: true
  demo: false

backup:
  nfs:
    server: 10.0.0.2
    path: /backups

monitoring:
  ntfy:
    url: http://ntfy.prod.svc.cluster.local
    topic: alerts

3. Deploy

helm template homelab homelab/homelab -f my-cluster.yaml | kubectl apply -f -

Or from a local clone:

helm template homelab ./charts/homelab -f my-cluster.yaml | kubectl apply -f -

4. Set the gateway address (after first deploy)

After the initial deploy creates the Istio gateway Service, set platform.gatewayAddress to its ClusterIP:

kubectl get svc -n istio-ingress gateway -o jsonpath='{.spec.clusterIP}'

Add this to your values file and re-deploy. This enables STATIC ServiceEntry resolution, which prevents mesh-internal DNS hairpinning without generating DNS queries from every Envoy sidecar. Without this value, ServiceEntries are omitted and mesh-internal routing via public hostnames won't work (external routing is unaffected).

ArgoCD takes over from here — it creates the sub-chart Applications and syncs them in order.

4. Verify

kubectl get applications -n argocd

All applications should show Synced and Healthy within a few minutes.

Features

Each feature flag controls one or more operators and the platform resources that depend on them.

Feature Flag Operators Platform Resources
GitOps gitops ArgoCD
Service Mesh serviceMesh Istio base, istiod Ingress class, gateway pod, public/private Gateway CRs
TLS Certificates certificates cert-manager Cluster issuer (Cloudflare DNS01), wildcard certificate
Authentication auth Authentik operator Authentik server, OIDC provider
PostgreSQL postgres CloudNative-PG, postgres operator Managed PostgreSQL cluster
MariaDB mariadb MariaDB operator + CRDs — (databases created by apps)
Monitoring monitoring Prometheus, Grafana, Alertmanager, blackbox exporter
Security security Falco, Trivy, Kyverno Runtime detection, vulnerability scanning, policy engine
Secrets secrets Sealed Secrets, External Secrets — (secrets created by apps)
Backup backup VolSync Restic-based PVC backup to NFS
DNS dns DNS operator Pi-hole, DNS sidecar
Reflection reflection Reflector Cross-namespace secret/configmap mirroring
Reloader reloader Reloader Auto-restart pods on config changes
Storage storage Local-path storage class configuration

See Features for detailed documentation including dependency graph and configuration options.

Overriding Defaults

For fine-grained control, use the overrides section to pass values directly to any sub-chart:

overrides:
  operators:
    operators:
      istiod:
        version: "1.26.0"
  platform:
    resources:
      postgresCluster:
        instances: 3
        storage:
          size: 50Gi
  monitoring:
    monitoring:
      prometheus-operator:
        values:
          prometheus:
            prometheusSpec:
              retention: 60d

Deploying Applications

The platform publishes homelab-common, a Helm library chart that provides high-level abstractions for deploying applications. A minimal app needs three files:

Chart.yaml:

apiVersion: v2
version: 1.0.0
name: my-app
dependencies:
  - name: homelab-common
    version: ">=0.1.0"
    repository: https://mortenolsen.pro/homelab-core/

templates/common.yaml:

{{ include "common.all" . }}

values.yaml:

image:
  repository: ghcr.io/org/my-app
  tag: latest
subdomain: myapp
container:
  port: 8080
  healthProbe:
    type: httpGet
    path: /health
service:
  port: 80
virtualService:
  enabled: true
  gateways:
    private: true

Then build and deploy:

helm dependency build
helm template my-app . --set globals.domain=example.com | kubectl apply -f -

The common library handles Deployment, Service, VirtualService, PVC, DNS, OIDC, database provisioning, secrets, backups, and monitoring probes — all driven by values.

What the common chart provides

Template Resource Triggered by
common.deployment Deployment image + deployment
common.service Service(s) service
common.pvc PersistentVolumeClaim(s) persistentVolumeClaims
common.virtualService Istio VirtualService virtualService.enabled
common.serviceEntry Istio ServiceEntry virtualService.enabled
common.dns DNSRecord dns.enabled
common.oidc AuthentikClient oidc.enabled
common.database PostgresDatabase database.enabled
common.externalSecrets ExternalSecret + Password externalSecrets
common.probe Blackbox Probe service (auto)
common.backup VolSync ReplicationSource PVC with backup: true

Use {{ include "common.all" . }} to render everything automatically, or include individual templates for more control.

Local Development

This repo uses a Nix flake for development dependencies. With Nix and direnv:

cd homelab-core        # direnv activates the Nix shell
make recreate          # Create Kind cluster + install ArgoCD + deploy stack

ArgoCD UI: localhost:30080 (password in argo-password.txt).

See Local Development for details.

Documentation

Document Description
Architecture Chart hierarchy, sync waves, template patterns
Features Detailed feature reference with dependencies
Networking Istio gateways, VirtualServices, DNS, TLS
Authentication Authentik OIDC setup and integration
Secrets External Secrets, Sealed Secrets, Reflector
Monitoring Prometheus, alerts, Grafana, Blackbox probes
Backups Volsync + restic, schedules, restore procedures
Disaster Recovery Full cluster restore runbook
Local Development Nix shell, Kind, Makefile targets

Troubleshooting

# Check all applications
kubectl get applications -n argocd

# Inspect a specific application
argocd app get <name>

# Check operators
kubectl get applications -n argocd | grep -v Synced

# Certificate issues
kubectl get certificates -A
kubectl describe certificate -n shared wildcard-tls

# Render charts locally to debug
helm template homelab homelab/homelab -f my-cluster.yaml
helm template shared ./charts/shared