Run your own media server, backups, monitoring, automation, and more — on hardware you control. This repository contains a collection of self-hosted apps, deployable on any Kubernetes cluster via Helm or ArgoCD.
Note
Personal Setup: This repository reflects a personal homelab setup. Domains, host paths, and secret names are specific to this environment. If you're adapting it for your own use, update the values.yaml in each app you deploy.
- Overview
- Prerequisites
- Getting Started
- How It Works
- System App Order
- Host Directories
- Secrets
- Deploying an App
- Apps
- Troubleshooting
- References
- Contributing
31 self-hosted apps across 7 categories, all deployed the same way — one Helm chart plus GitOps. The stack:
- Kubernetes — runs everything (distribution-agnostic: Talos, k3s, …)
- bjw-s app-template — the single Helm chart every app is built on, so configs stay consistent
- ArgoCD — GitOps controller; continuously syncs this repo to the cluster
- Traefik — ingress / reverse proxy (
<app>.<domain>) - Infisical — injects secrets into pods at deploy time
- Reloader — restarts pods when their config or secrets change
Every app lives in apps/<category>/<app>/ with its own Helm values, ArgoCD manifest, and README. Browse the full list under Apps.
- A Kubernetes cluster (any distribution — Talos, k3s, etc.)
- Helm — Kubernetes package manager
- kubectl — Kubernetes CLI
- ArgoCD — optional GitOps controller (see apps/system/argocd)
- Node.js + npm — optional, for regenerating the Apps table (see CONTRIBUTING.md)
Bring up any Kubernetes cluster and export a working kubeconfig. If this is your first cluster, k3s is the easiest way to start:
curl -sfL https://get.k3s.io | sh -Talos, kind, and other distributions work just as well.
git clone https://github.com/hobroker/selfhosted.git
cd selfhostedArgoCD watches this Git repo and syncs changes from it to your cluster — no manual helm install needed. It also provides a web UI to monitor and manage all your deployments. See apps/system/argocd for bootstrap instructions.
On a fresh cluster, bring up the system apps first (storage, ingress, secrets) — workload apps depend on them.
Pick an app and follow its README.md — each one has copy-paste commands for both ArgoCD and plain Helm. For example, to deploy Syncthing with ArgoCD:
kubectl apply -f apps/backup/syncthing/application.yamlPrefer plain Helm? Each app's README lists the exact helm upgrade --install commands. The apps install from the remote app-template chart (not a local one), so there's no helm install <path>. See Deploying an App for details.
flowchart LR
dev([git push]) --> repo[(Git repo)]
repo -->|watches & syncs| argo[ArgoCD]
argo -->|applies Helm manifests| cluster{{Kubernetes cluster}}
infisical[Infisical] -. injects secrets .-> cluster
storage[(Host / NFS storage)] -. mounts volumes .-> cluster
cluster --> apps[Apps]
user([You]) -->|request| traefik[Traefik]
traefik -->|routes by domain| apps
In short: you push a change, ArgoCD applies the updated Helm charts to your cluster, and Traefik routes each incoming request to the right app by domain. Infisical injects secrets into pods at deploy time, and volumes are mounted from the host or NFS.
This is simplified — real external access also depends on your DNS and (if enabled) TLS setup.
Not using ArgoCD? You can install any app directly with Helm (helm upgrade --install) — the same values.yaml drives both paths.
System apps must be running before any workload apps. A root app-of-apps (bootstrap/system.yaml) handles this — apply it once and ArgoCD deploys every system app in sync-wave order, waiting for each wave to become healthy before starting the next:
kubectl apply -f bootstrap/system.yamlThe resulting order (apps in the same wave deploy in parallel):
- metallb — load balancer (assigns external IPs)
- longhorn · traefik — persistent storage + ingress
- infisical-operator — secret injection
- reloader — rolling restarts on config/secret changes
These apps set
syncPolicy.automatedso the app-of-apps can drive them in order; workload apps stay manual-sync by default. Two system apps sit outside the wave and are deployed manually: argocd (bootstrapped separately, manages itself) and rancher (an optional management UI).
Apps use host-mounted volumes for persistent data. The paths are defined in each app's config/pv.yaml and must exist on the host before deploying.
The defaults below reflect this homelab's setup — update them to match your own environment:
/var/local/<app>— per-app config and database (hostPath on the node)/mnt/nebula— media library (movies, TV shows, downloads), mounted via NFS
To customize paths, edit the config/pv.yaml in each app you deploy.
Longhorn also provides a longhorn-retain StorageClass, whose Retain reclaim policy keeps your data even if a PVC is deleted — see longhorn.
Secrets are managed via Infisical using the infisical-operator. Each app's README.md lists the required secrets and the Infisical secret name they are sourced from.
If you don't use Infisical, you can create Kubernetes Secrets manually — just make sure the Secret names and keys match what each app's templates expect.
Before deploying any app, review its values.yaml and update domains, paths, and other environment-specific values to match your setup. Some apps contain hardcoded domains (e.g. jellyfin.hobroker.me) that must be changed.
Each app's README.md includes instructions for both ArgoCD and plain Helm deployment, along with any extra steps required (secrets, host volumes, config files).
Quick start with ArgoCD:
kubectl apply -f apps/<category>/<name>/application.yamlThen sync it in the ArgoCD UI or with argocd app sync <name>.
| App | Description | Source Code |
|---|---|---|
| hermes | Personal AI agent that connects to messaging platforms and runs tasks autonomously | https://github.com/NousResearch/hermes-agent |
| n8n | Workflow automation platform | https://github.com/n8n-io/n8n |
| openclaw | AI assistant that connects to messaging platforms and executes tasks autonomously | https://github.com/openclaw/openclaw |
| App | Description | Source Code |
|---|---|---|
| backrest | A web-accessible backup solution built on top of restic | https://github.com/garethgeorge/backrest |
| syncthing | Continuous file synchronization | https://github.com/syncthing/syncthing |
| App | Description | Source Code |
|---|---|---|
| code-server | VS Code running on a remote server, accessible through the browser | https://github.com/linuxserver/docker-code-server |
| http-https-echo | App that echoes request data as JSON (useful for debugging) | https://github.com/mendhak/docker-http-https-echo |
| App | Description | Source Code |
|---|---|---|
| bazarr | Companion application to Sonarr and Radarr that manages and downloads subtitles. | https://github.com/morpheus65535/bazarr |
| fileflows | File processing application | https://github.com/revenz/FileFlows |
| flaresolverr | Proxy server to bypass Cloudflare protection | https://github.com/FlareSolverr/FlareSolverr |
| jellyfin | An open-source media server | https://github.com/jellyfin/jellyfin |
| plex | A media server that organizes and streams video and audio content across devices. | https://www.plex.tv/ |
| prowlarr | Indexer manager/proxy built on the popular *arr stack to integrate with various PVR apps | https://github.com/Prowlarr/Prowlarr |
| qbittorrent | Bittorrent client with a feature rich Web UI for remote access | https://github.com/qbittorrent/qBittorrent |
| radarr | A movie tracking and automation tool that downloads movies as they become available. | https://github.com/Radarr/Radarr |
| recyclarr | Automatically sync TRaSH Guide settings to Radarr and Sonarr. | https://github.com/recyclarr/recyclarr |
| seerr | A modern media request and discovery tool. | https://github.com/seerr-team/seerr |
| sonarr | A TV series tracking and automation tool for downloading episodes as they air. | https://github.com/Sonarr/Sonarr |
| tautulli | A monitoring and analytics tool for Plex | https://github.com/Tautulli/Tautulli |
| threadfin | An M3U proxy for Kernel/Plex/Jellyfin/Emby based on xTeVe | https://github.com/Threadfin/Threadfin |
| App | Description | Source Code |
|---|---|---|
| grafana-backup | Cron job to backup Grafana settings by using the Grafana API | https://github.com/ysde/grafana-backup-tool |
| prometheus-operator | Operator that manages Prometheus, Grafana, and related monitoring components in K8s | https://github.com/prometheus-operator/prometheus-operator |
| scraparr | Prometheus Exporter for various components of the *arr Suite. | https://github.com/thecfu/scraparr |
| App | Description | Source Code |
|---|---|---|
| adguardhome | A network-wide DNS ad blocker and privacy filter | https://github.com/AdguardTeam/AdGuardHome |
| App | Description | Source Code |
|---|---|---|
| argocd | Declarative GitOps CD for Kubernetes | https://github.com/argoproj/argo-cd |
| infisical-operator | Operator to fetch secrets from Infisical. | https://github.com/Infisical/infisical |
| longhorn | Cloud-native distributed block storage for Kubernetes. | https://github.com/longhorn/longhorn |
| metallb | Layer 2 load balancer for bare-metal Kubernetes clusters | https://github.com/metallb/metallb |
| rancher | Container management platform | https://github.com/rancher/rancher |
| reloader | K8s controller that triggers rolling upgrades when ConfigMaps or Secrets change | https://github.com/stakater/Reloader |
| traefik | HTTP reverse proxy and load balancer | https://github.com/traefik/traefik |
- Pod stuck in
Pending— check that the PersistentVolume exists and the host directory has been created (kubectl describe pod <name>will show the exact error) - ArgoCD sync failed — run
argocd app get <name>or check the ArgoCD UI for error details - Ingress not reachable — verify Traefik is running (
kubectl get pods -n traefik) and that your domain's DNS points to the cluster's external IP - Secrets missing — ensure the Infisical operator is synced, or create the required Kubernetes Secrets manually (check the app's
README.mdfor the expected Secret names)
- Helm docs — Kubernetes package manager documentation
- kubectl cheat sheet — quick reference for common commands
- k3s — lightweight Kubernetes distribution
- Talos Linux — Kubernetes-focused Linux
- ArgoCD — GitOps continuous delivery
- Infisical — Secret management
See CONTRIBUTING.md.
If you find this useful: