Skip to content

πŸ—ΊοΈ Cluster Navigation Map

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         KUBERNETES CLUSTER                       β”‚
β”‚                        (192.168.30.51:6443)                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                    β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                           β”‚                           β”‚
        β–Ό                           β–Ό                           β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   my-apps/    β”‚         β”‚  kube-system/   β”‚         β”‚  flux-system/  β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                   β”‚     β”‚                   β”‚         β”‚                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”      β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚   media/         β”‚  β”‚    β”‚   core/      β”‚      β”‚    β”‚   ...    β”‚  β”‚
β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”˜      β”‚    β”‚          β”‚  β”‚
β”‚  β”‚  β”‚ jellyfin/  β”‚  β”‚  β”‚    β”‚                   β”‚      β”‚            β”‚  β”‚
β”‚  β”‚  β”‚ immich/    β”‚  β”‚  β”‚    β”‚   networking/     β”‚      β”‚            β”‚  β”‚
β”‚  β”‚  β”‚ owncast/   β”‚  β”‚  β”‚    β”‚  └────────────────┼─┐  β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” β”‚  β”‚
β”‚  β”‚  β”‚ lidarr/    β”‚  β”‚  β”‚    β”‚  β”‚                   β”‚    β”‚    β”‚       β”‚ β”‚  β”‚
β”‚  β”‚  β”‚ radarr/    β”‚  β”‚  β”‚    β”‚  β”‚     system/      β”‚    β”‚    β”‚       β”‚ β”‚  β”‚
β”‚  β”‚  β”‚ ...        β”‚  β”‚  β”‚    β”‚  β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”˜    β”‚    β”‚       β”‚ β”‚  β”‚
β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚  β”‚    β”‚  └─────────────────┐ β”‚      β”‚    β”‚       β”‚ β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”˜    β”‚                     β”‚   β”‚      β”‚    β”‚       β”‚ β”‚  β”‚
β”‚                              β”‚       system pods    β”‚   β”‚       β”‚    β”‚       β”‚ β”‚  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”˜
                                    β”‚
                                    β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  Apps are deployed via   β”‚
                    β”‚  Flux (GitOps)           β”‚
                    β”‚                          β”‚
                    β”‚  Source:                 β”‚
                    β”‚  ~/Projects/truecharts/  β”‚
                    β”‚                          β”‚
                    β”‚  Edit config β†’ Commit β†’  β”‚
                    β”‚  Push β†’ Flux auto-appliesβ”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Directory tree

GitOps repo (truecharts):

truecharts/
β”œβ”€β”€ clusters/main/
β”‚   β”œβ”€β”€ kubernetes/     # Flux manifests (core, system, my-apps, …)
β”‚   β”œβ”€β”€ talos/           # Talos machine config
β”‚   └── clusterenv.yaml  # Cluster vars (encrypt via clustertool)
β”œβ”€β”€ repositories/        # HelmRepository defs
β”œβ”€β”€ custom_images/       # Images built to GHCR
β”œβ”€β”€ .sops.yaml
└── README.md            # Points here for docs

Docs repo (nerd.dad):

nerd.dad/docs/homelab/
β”œβ”€β”€ guides/              # Cluster guides (this section)
└── kubernetes/          # Service notes + runbooks

🎯 Quick Find: Commands by Goal

Goal: Find Jellyfin Data

# 1. Check what's running
kubectl get pods -n media

# 2. Find the data volume
kubectl get pvc -n media | grep jellyfin

# 3. Access files
kubectl exec -n media jellyfin-<pod> -- ls /config/

# 4. Check pod logs
kubectl logs -n media jellyfin-<pod>

Goal: Find Immich Data

kubectl get pods -n immich
kubectl get svc -n immich

Goal: Access Downloader Apps

kubectl get pods -n downloaders

Goal: View Dashboards

kubectl get deployment -n my-apps dashboards

πŸ”— External URLs

Your cluster exposes these services externally:

Service URL/Port Namespace Purpose
Jellyfin jellyfin.hoth.systems media Media server
Immich (configured via ingress) immich Photo library
OwnCast (configured via ingress) owncast Radio host
Dashboards (configured via ingress) my-apps Monitoring

To find ingress URLs:

kubectl get ingress -A


πŸ› οΈ Workflow Examples

Deploying a New App

# 1. Go to my-apps/<app-name>/
cd ~/Projects/truecharts/clusters/main/kubernetes/my-apps/

# 2. Create app directory
mkdir <app-name>

# 3. Create ks.yaml with app definition
# 4. Create app/kustomization.yaml
# 5. Create app/helm-release.yaml

# 6. Commit and push
git add my-apps/<app-name>/
git commit -m "Add <app-name> app"
git push

# 7. Flux will automatically deploy!
# 8. Monitor with:
kubectl get pods -n <namespace>

Finding Secrets

# List all secrets
kubectl get secrets -A

# Find secret for specific app
kubectl get secrets -n media | grep -i jellyfin

# View secret contents
kubectl get secret <secret-name> -n namespace -o yaml

πŸ“Š Architecture Overview

Components

  • Talos 1.11.2 - Container-native Linux OS
  • Kubernetes 1.35+ - Container orchestration
  • Flux v2.7.2 - GitOps controller
  • Helm - Chart/package manager
  • TrueCharts - Helm charts library
  • Longhorn - Distributed storage (for PVCs)

Storage

  • PVCs claim from storage class
  • Longhorn provides RWO/RWX storage
  • 100Gi PVCs common for media

🎨 Visual Structure

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 FLUX GITOPS SYSTEM                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                     β”‚
β”‚  [Git Repo] ──► [Flux Controller] ──► [K8s API]  β”‚
β”‚       β”‚              β”‚                     β”‚       β”‚
β”‚       β–Ό              β–Ό                     β–Ό       β”‚
β”‚  [Config Files]  [Reconciliation]    [Running Podsβ”‚
β”‚                                                     β”‚
β”‚  Edit config β†’ Commit β†’ Push β†’ Flux applies        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ” Security Notes

Secrets Access

  • Never commit plain-text secrets
  • Use SOPS for encryption
  • age.agekey for decryption
  • .sops.yaml for SOPS configuration

Never Do

  • kubectl apply directly (breaks GitOps)
  • Manually edit cluster resources
  • Commit secrets to repo

πŸ“š File Formats

Kustomization (kustomization.yaml)

resources:
  - app/helm-release.yaml
  - app/kustomization.yaml

images:
  - name: jellyfin
    newName: ghcr.io/your-registry/jellyfin
    newTag: latest

Helm Release (helm-release.yaml)

apiVersion: helm.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: jellyfin
  namespace: media
spec:
  values: {...}
  helmParams:
    createCRDs: false

πŸš€ Flux Commands

# Check all releases
flux get helmrelease -A

# Watch reconciliation
flux watch helmrelease <name> -n <ns>

# Get events
kubectl get events -n flux-system

Maintained by: itzteajay
GitOps workflow: edit truecharts β†’ commit β†’ push β†’ Flux applies
Docs: nerd.dad Homelab