Here is my pet-project of home/small-office cluster that can handle everything
you purchase as a service from the Google or Microsoft, but with significantly
more pain and fun. On the other hand, this would be enough for 20-30 employees
at 1000 USD setup and easy to scale. K3S is used because it's much simplier to
install and I don't really need all that cloud provider's drivers since the
goal was to be self-sustainable.
home-k3s is a homelab/small-office cluster built on k3s and managed mostly
through Argo CD manifests in this repository. The cluster runs user-facing
apps, shared platform services, observability, and storage.
Older photo:
Core platform:
- k3s
- Traefik
- Argo CD
- External Secrets
- Vault
- Longhorn
Data and messaging:
- PostgreSQL
- MySQL
- Redis (operator + app-specific instances)
- SeaweedFS (S3-compatible object storage)
- Elasticsearch (ECK operator + stack)
User-facing apps:
- Mail (Postfix + Dovecot + Rspamd)
- Bitwarden
- Nextcloud + Collabora
- Synapse (Matrix messaging server)
- Mastodon
- WordPress
- Plex
- Minecraft
- Keycloak
- Dawarich
- Karakeep
- Your Spotify
- Year calendar
- ConvertX
- Stirling PDF
- UniFi
- Home Assistant
Observability and security:
- Prometheus + exporters
- Thanos
- Loki
- ClamAV
- Connectivity exporter
- CA scanner UI (
canitiser/)
argocd/: Argo CDApplicationmanifests (main deployment entrypoint).argocd-deploy/: Argo CD post-install cluster manifests (ConfigMap and Ingress).<service>/: Namespace-scoped manifests/charts for each service.DEPRECATED/: Old manifests kept for reference.docs/upgrade-playbook.md: Pre-merge runtime checklist for upgrades.k3s-config.yaml: Baseline k3s server config used by this cluster.
- Prepare Linux sysctl settings on all nodes.
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra = 2
vm.swappiness = 10-
Install the first (server) node.
Update
tls-sanink3s-config.yaml, copy it to/etc/rancher/k3s/config.yaml, then install:
curl -sfL https://get.k3s.io | \
INSTALL_K3S_EXEC="server --cluster-cidr=10.42.0.0/16,2001:cafe:42:0::/56 \
--service-cidr=10.43.0.0/16,2001:cafe:42:1::/112 \
--flannel-ipv6-masq --disable traefik --disable servicelb" sh -s -These would result the config:
write-kubeconfig-mode: "0644"
tls-san:
- "w386.k8s.my.lan"
- "localhost"
cluster-cidr: "10.42.0.0/16"
cluster-cidr-ipv6: "2001:cafe:42:0::/56"
service-cidr: "10.43.0.0/16"
service-cidr-ipv6: "2001:cafe:42:1::/112"
flannel-backend-type: "vxlan"
flannel-ipv6-masq: true
disable:
- traefik
- servicelb- Join worker nodes.
cat /var/lib/rancher/k3s/server/node-token
curl -sfL https://get.k3s.io | \
K3S_URL=https://master.k8s.my.lan:6443 K3S_TOKEN=<node-token> sh -- Configure local
kubectlaccess.
cat /etc/rancher/k3s/k3s.yaml > ~/.kube/config
chmod 600 ~/.kube/config- Install and bootstrap Argo CD.
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl apply -f argocd-deploy/config-map-argocd-cmd-params-cm.yaml
kubectl apply -f argocd-deploy/ingress-argocd-ingress.yamlApply all Argo CD Applications from this repo:
Get-ChildItem .\argocd\*.yaml | ForEach-Object { kubectl apply -f $_.FullName }Container image cleanup:
docker system prune -a
crictl rmi --pruneCustom images used by this cluster are in
shaman007/Dockerfiles. They are
mainly used when upstream images do not support aarch64 or are missing
required features.
Historical manifests are kept under DEPRECATED/.