Skip to content

Latest commit

Β 

History

934 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🏠 Homelab v2 - Kubernetes Edition

Kubernetes Talos Services Status Last Updated

A modern homelab running on Kubernetes with Talos Linux, migrated from Proxmox/Docker

Architecture β€’ Services β€’ Infrastructure β€’ Deployment β€’ Roadmap


πŸ“– Quick Overview

What: Production-grade Kubernetes homelab for self-hosted services
Why: GitOps automation, better scalability, and learning cloud-native tech
How: Talos Linux bare-metal cluster with declarative configuration
Board: Project Board on Jira


πŸ—οΈ Architecture

graph TB
    subgraph "External Access"
        Internet((Internet))
        CF[Cloudflare DNS]
        DD[DuckDNS]
    end

    subgraph "Homelab Network"
        Router[Router<br/>192.168.10.1]

        subgraph "Kubernetes Cluster (Talos Linux + Cilium CNI)"
            subgraph "Control Plane"
                CP[beelink-1<br/>192.168.10.147<br/>Intel N100 Β· 16GB]
            end

            subgraph "Worker Node"
                W1[proxmox<br/>192.168.10.165<br/>i5-7400 Β· 16GB Β· GT-730]
            end

            subgraph "Network Layer"
                MLB[MetalLB<br/>Load Balancer]
                TRF[Traefik v3<br/>Ingress + SSL]
                AUTH[Authentik<br/>SSO / ForwardAuth]
            end

            subgraph "Observability"
                PROM[Prometheus<br/>+ Grafana]
                LOKI[Loki<br/>+ Alloy]
            end

            subgraph "GitOps"
                ARGO[ArgoCD<br/>24 Apps]
                AIU[Image Updater]
                VELERO[Velero<br/>Daily Backups]
            end
        end

        subgraph "Storage"
            NAS[Synology DS423+<br/>36TB Raw / 24TB Usable<br/>NFS + 19 iSCSI LUNs]
        end

        subgraph "DNS"
            PIHOLE[PiHole<br/>+ External-DNS]
        end
    end

    Internet --> CF
    Internet --> DD
    CF --> Router
    DD --> Router
    Router --> MLB
    MLB --> TRF
    TRF --> AUTH
    TRF --> CP
    TRF --> W1
    CP -.-> W1
    W1 --> NAS
    CP --> NAS
    ARGO --> AIU
    PROM -.-> LOKI

    classDef control fill:#326CE5,stroke:#fff,stroke-width:2px,color:#fff
    classDef worker fill:#00ADD8,stroke:#fff,stroke-width:2px,color:#fff
    classDef network fill:#FF7300,stroke:#fff,stroke-width:2px,color:#fff
    classDef storage fill:#40C463,stroke:#fff,stroke-width:2px,color:#fff
    classDef gitops fill:#E96D4B,stroke:#fff,stroke-width:2px,color:#fff
    classDef obs fill:#7B61FF,stroke:#fff,stroke-width:2px,color:#fff

    class CP control
    class W1 worker
    class MLB,TRF,AUTH network
    class NAS,PIHOLE storage
    class ARGO,AIU,VELERO gitops
    class PROM,LOKI obs
Loading

βœ… What's Running

🎬 Media Stack (arr-stack namespace)

Service Purpose Access
πŸ”’ VPN Group (Gluetun Sidecar)
└─ qBittorrent Torrent downloads Port 8080
└─ NZBGet Usenet downloads Port 6789
└─ Prowlarr Indexer management Port 9696
πŸ“Ί Media Management
Sonarr / Sonarr2 TV show automation Ports 8989 / 8990
Radarr / Radarr2 Movie automation Ports 7878 / 7879
Bazarr / Bazarr2 Subtitle management Ports 6767 / 6768
Notifiarr Discord notifications Port 5454

🎭 Media Frontend (jelly namespace)

  • Jellyfin - Media streaming server with Intel GPU transcoding
  • Jellyseerr - Media request management

πŸ“Š Monitoring & Observability (monitoring namespace)

Service Purpose
Prometheus (kube-prometheus-stack) Metrics collection & alerting
Grafana Dashboards & visualization
Loki Log aggregation
Alloy Telemetry collector (logs & metrics)
Discord Webhook Proxy Routes critical/warning/status alerts to separate Discord channels

Custom homelab alert rules fire every 30 minutes with cluster status reports, plus event-driven alerts for pod failures, node issues, and PVC pressure.

πŸ”’ Identity & Access (authentik namespace)

  • Authentik (v2025.12.4) - Self-hosted SSO/Identity Provider with passkey login flows
    • Middleware applied to services via Traefik ForwardAuth
    • Backed by CNPG PostgreSQL database

πŸ”„ Automation & GitOps

  • n8n (v2.10.0, n8n namespace) - Visual workflow automation, backed by CNPG PostgreSQL
  • ArgoCD Image Updater - Automatically commits new container image tags back to Git

πŸ—„οΈ Data & Backup

  • CloudNativePG (CNPG) (default namespace) - PostgreSQL operator managing databases for Authentik and n8n
  • Velero (velero namespace) - Cluster backup & disaster recovery
    • Daily backups at 2 AM SGT to S3, 12-day retention
    • Covers all user namespaces + cluster-scoped resources (PVs, namespaces, RBAC)

πŸ› οΈ Infrastructure Services

Service Namespace Purpose
Traefik v3 traefik Ingress controller & reverse proxy (2-replica HA)
Cert-Manager traefik Automatic SSL certificates via DuckDNS
MetalLB metallb Bare-metal load balancer
Cilium kube-system eBPF-based CNI networking
Sealed Secrets kube-system Encrypted secrets safe to commit to Git
External-DNS misc Automatic DNS record management via PiHole webhook
K8s-Cleaner k8s-cleaner Cleanup completed pods/jobs
Descheduler kube-system Workload distribution optimization
NFS Provisioner synology-csi Dynamic volume provisioning

πŸ”§ Infrastructure Details

Cluster Configuration

Cluster:
  OS: Talos Linux v1.12.4
  Kubernetes: v1.35.0
  CNI: Cilium (eBPF)
  GitOps: ArgoCD (24 applications)

Nodes:
  - Name: beelink-1
    Role: Control Plane
    IP: 192.168.10.147
    Specs: Intel N100, 16GB RAM

  - Name: proxmox
    Role: Worker
    IP: 192.168.10.165
    Specs: Intel i5-7400, 16GB RAM, NVIDIA GT-730

Storage Architecture

Synology DS423+ (24TB Raw / ~10.9TB Usable) 1 drive fault tolerance
β”œβ”€β”€ /volume1/
β”‚   β”œβ”€β”€ NAS/
β”‚   β”‚   β”œβ”€β”€ Movies
β”‚   β”‚   β”œβ”€β”€ Shows
β”‚   β”‚   β”œβ”€β”€ Music
β”‚   β”‚   β”œβ”€β”€ Youtube
β”‚   β”‚   └── Downloads/
β”‚   β”‚       β”œβ”€β”€ Qbittorrent/
β”‚   β”‚       β”‚   β”œβ”€β”€ Torrents
β”‚   β”‚       β”‚   β”œβ”€β”€ Completed
β”‚   β”‚       β”‚   └── Incomplete
β”‚   β”‚       └── Nzbget/
β”‚   β”‚           β”œβ”€β”€ Queue
β”‚   β”‚           β”œβ”€β”€ Nzb
β”‚   β”‚           β”œβ”€β”€ Intermediate
β”‚   β”‚           β”œβ”€β”€ Tmp
β”‚   β”‚           └── Completed
β”‚   β”‚
β”‚   β”œβ”€β”€ kube/                    # NFS-based PVCs
β”‚   β”‚   β”œβ”€β”€ jelly/
β”‚   β”‚   β”‚   └── jellyseerr-pvc
β”‚   β”‚   β”œβ”€β”€ ai-stuff/               # (legacy)
β”‚   β”‚   β”œβ”€β”€ default/
β”‚   β”‚   β”‚   └── test-pvc-worker
β”‚   β”‚   └── test-nfs/
β”‚   β”‚       └── test-nfs-pvc
β”‚   β”‚
β”‚   β”œβ”€β”€ TimeMachine/             # Macbook Backups
β”‚   β”‚
β”‚   └── Docker/                  # Legacy
β”‚       └── Pihole
β”‚
└── iSCSI LUNs (19 total)        # High-performance PVCs
    β”œβ”€β”€ jellyfin-config          # Jellyfin configs (5Gi)
    β”œβ”€β”€ jellyfin-data            # Jellyfin metadata
    β”œβ”€β”€ jellyfin-cache           # Transcoding cache
    β”œβ”€β”€ jellyfin-log             # Jellyfin logs
    β”œβ”€β”€ arr-stack configs        # All *arr app configs
    β”œβ”€β”€ misc service volumes     # Other app configs
    └── ... (other service volumes)

Storage Classes:

  • nfs-client - Dynamic NFS provisioning for general workloads
  • synology-iscsi - iSCSI LUNs for high-performance/database workloads
  • syno-storage - Synology CSI driver (alternative option)

Network Configuration

  • Load Balancer: MetalLB with IP pool 192.168.10.200-192.168.10.250
  • Ingress: Traefik v3 with automatic SSL
  • Domains:
    • Local: *.arkhaya.duckdns.org (internal services)
    • Public: *.arkhaya.xyz (external access)
  • Security: Cloudflare proxy for public services

πŸ“‹ Roadmap

Synced from Jira β€’ Updates every 6 hours and on push

To Do (5)

  • Configure Prometheus and Grafana with Alert Manager for dashboarding and alerts
  • Add Prometheus alerting rule for Velero backup failures
  • *arr Stack Migration (SQLite to PostgreSQL)
  • Monthly new movies and shows
  • Switch Velero to a helm install instead of velero cli

In Progress (1)

  • Install Jellyfin Stats

Done (42)

  • Figure out why aws s3 is more costly
  • Switch kanban to jira
  • Add kanban items to jira
  • Update Nvim config to add tab to fill and remove auto save reformat
  • Fix Traefik deprecated issues with routes
  • Fix n8n not updating to newest version via GitOps
  • Install Sealed Secrets
  • Convert all Secrets to sealed secrets
  • Work on lowering req and limits to allow Worker to run more
  • Random Kopia Job review and cleanup
  • Setup git-crypt for serena, claude etc
  • Look at how to be able to scrape and share the board in README
  • Issue with n8n connection to github using oauth2
  • Verify everything that needs to be backed up is being backed up
  • Add skills.md for claude to change how CLAUDE.md is used
  • Verify ArgoCD Helm argo image updater is working
  • Authentik - Identity Provider setup
  • Create manifests
  • Check secrets etc that is needed for CNPG
  • Configure Jellyfin
  • Expose specific path for SSO on internet only
  • Apply and configure Dashboard
  • Figure out why SSO doesn’t show admin dashboard when logging in as user
  • Switch to seerr v3
  • Fix loki degradation
  • N8N using authentik middleware for routes
  • Create Discord Bot (Self Hosted)
  • Issue with duckdns cert
  • Import all users into Authentik then disable normal login
  • Create N8N workflow to update me on cluster issues
  • Use bot to send messages
  • Create n8n workflow to connect to jellyfin and jellyseerr api
  • Use Bot to tell people to watch new shows or continue old ones
  • Use bot to inform about cluster status and issues
  • Fix Failing VPN pod
  • [BUG] Authentik crash due to low storage in CNPG
  • [BUG] Jellyfin data pvc full
  • Research/Install of Calendarr,Maintainarr
  • Configure Jellyfin known proxies and known local networks
  • Fix liveliness issues on gluetun and issues on other pods
  • jellyfin crashed due to filled pvc data
  • Authentik rollout stuck 19h: worker node CPU-request saturation (velero over-reserved)

πŸ”§ Troubleshooting

Cert-Manager DuckDNS Issues

When using cert-manager with DuckDNS webhook for wildcard certificates, you may encounter issues:

Common Problems:

  1. "no api token secret provided" - The ClusterIssuer is looking for a secret in the wrong namespace
  2. DNS propagation timeouts - DuckDNS can take 5-10 minutes to propagate DNS changes
  3. Wrong ClusterIssuer references - Ensure you're using the Helm-deployed issuer

Solution:

If you installed the webhook via Helm:

helm install cert-manager-webhook-duckdns cert-manager-webhook-duckdns/cert-manager-webhook-duckdns \
  --namespace cert-manager \
  --set duckdns.token=$DUCKDNS_TOKEN \
  --set clusterIssuer.production.create=true \
  --set clusterIssuer.staging.create=true \
  --set clusterIssuer.email=gauranshmathur1999@gmail.com

Then use the Helm-created ClusterIssuer in your Certificate resources:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: duckdns-wildcard-cert
  namespace: traefik
spec:
  secretName: duckdns-wildcard-tls
  issuerRef:
    name: cert-manager-webhook-duckdns-production # Helm-created issuer
    kind: ClusterIssuer
  dnsNames:
    - "arkhaya.duckdns.org"
    - "*.arkhaya.duckdns.org"

πŸ› οΈ Deployment Guide

Prerequisites

  1. Hardware: 2+ machines with 8GB+ RAM
  2. Network: Static IPs, router access for port forwarding
  3. Storage: NAS with NFS enabled
  4. Tools: kubectl, helm, talosctl

Quick Start

# 1. Apply Talos configuration
talosctl apply-config --nodes 192.168.10.147 --file controlplane.yaml
talosctl apply-config --nodes 192.168.10.165 --file worker.yaml

# 2. Bootstrap cluster
talosctl bootstrap --nodes 192.168.10.147

# 3. Get kubeconfig
talosctl kubeconfig --nodes 192.168.10.147

# 4. Install core services
kubectl apply -f kubernetes/namespaces/
helm install metallb metallb/metallb -n metallb -f helm/metallb/values.yaml
helm install traefik traefik/traefik -n traefik -f helm/traefik/values.yaml

# 5. Deploy applications
kubectl apply -k kubernetes/

Directory Structure

Homelab/
β”œβ”€β”€ kubernetes/         # Raw Kubernetes manifests
β”‚   β”œβ”€β”€ arr-stack/     # Media automation stack
β”‚   β”œβ”€β”€ jellyfin/      # Media server configs
β”‚   └── ...
β”œβ”€β”€ helm/              # Helm charts and values
β”‚   β”œβ”€β”€ traefik/       # Ingress controller
β”‚   β”œβ”€β”€ cert-manager/  # SSL certificates
β”‚   └── ...
β”œβ”€β”€ ansible/           # Migration playbooks
└── docs/             # Additional documentation

πŸ”„ Migration from v1

What Changed?

Component v1 (Proxmox/Docker) v2 (Kubernetes)
Platform Proxmox VE + LXC Talos Linux bare-metal
Containers Docker Compose Kubernetes deployments
Networking Manual port mapping Service mesh + ingress
Storage Local volumes Dynamic PVCs
Updates Manual per-service Rolling updates
Backups Scripts Persistent volumes

Key Improvements

βœ… Declarative Configuration - Everything as code
βœ… Self-Healing - Automatic pod restarts
βœ… Easy Scaling - Just update replica count
βœ… Better Isolation - Namespace separation
βœ… Unified Ingress - Single entry point
βœ… Automated SSL - Cert-manager handles certificates

Challenges Solved

  1. VPN Networking β†’ Gluetun sidecar pattern
  2. GPU Transcoding β†’ Intel device plugin
  3. Data Migration β†’ Ansible playbooks
  4. Service Discovery β†’ CoreDNS + Traefik

πŸ“š Resources


🀝 Contributing

This is a personal project, but suggestions and improvements are welcome! Feel free to open an issue.

πŸ“„ License

MIT License - Feel free to use this as inspiration for your own homelab!


Built with ❀️ and lots of β˜•

About

Kubernetes homelab on Talos Linux with automated media stack, GitOps workflows, and self-hosted services. Migrated from Proxmox/Docker to Bare Metal Kubernetes infrastructure.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages