No description
  • Nix 60.8%
  • Shell 39.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
opencode 33e62f3645 incus: reconcile the host's DNAT entry points, and cut caddy over
Adds networkForward to an instance spec and reconciles it in apply.sh. For
caddy this is the cutover: the host's LAN address :80/:443 get DNAT'd to the
instance, so all twenty hostnames terminate TLS at Caddy and are handed back
to Traefik over the bridge.

Incus does this with an nftables rule rather than a socket bind, so Traefik
keeps holding the port the whole time and rollback is a single command with no
restart. The same asymmetry is what keeps the still-traefik catch-all loop-free:
the rule matches the host address, and the catch-all dials 10.0.0.1.

Applied last in apply_instance, after the instance is running and its secret
consumers have restarted, so a DNAT is never pointed at a dead container.

The reconcile is remove-then-add on an exact tuple match rather than add-what-is-
missing, because port add refuses a listen port an existing entry already claims
and a comma list ('80,443') is stored as one unremovable-by-parts entry. A
forward left over from an older target is otherwise unrepairable.

Verified against a throwaway listen address: create, idempotent no-op, stray port,
grouped entry with a stale target, dropping and adding ports, listen->target
remap, and retargeting the instance address.
2026-10-01 04:13:01 +02:00
apps fluxer: add hourly postgres dump to the backup tier 2026-09-30 20:16:37 +02:00
clusters/homelab add open-webui as the Ollama frontend 2026-09-27 20:03:37 +02:00
incus incus: reconcile the host's DNAT entry points, and cut caddy over 2026-10-01 04:13:01 +02:00
nixos incus: reconcile the host's DNAT entry points, and cut caddy over 2026-10-01 04:13:01 +02:00
.gitattributes chore: fix file modes (remove exec bit from text files) 2026-08-18 16:51:25 +02:00
.gitignore caddy: real Caddyfile, sops in the instance, and certs Caddy can get 2026-10-01 02:22:37 +02:00
.gitmodules pvc-explorer: pin the vendored submodule to main 2026-09-29 01:55:44 +02:00
.sops.yaml add open-webui as the Ollama frontend 2026-09-27 20:03:37 +02:00
README.md pvc-explorer: deploy the operator via upstream submodule + HelmRelease 2026-09-25 01:52:09 +02:00
renovate.json pvc-explorer: deploy the operator via upstream submodule + HelmRelease 2026-09-25 01:52:09 +02:00

HomeLab

This setup is currently tested with K3s and all its defaults, including the storage classes.

StorageClasses

However, for better data security, I would recommend to delete the default storage class K3s introduces:

kubectl delete storageclass local-path

The repository will provide alternative StorageClasses:

name reclaim policy
local-path-persistent Retain
local-path-volatile Delete

Flux Bootstrap

Once ready, deploy Flux with this repository:

flux bootstrap git \
  --url=ssh://git@github.com/SakulFlee/HomeLab.git \
  --branch=main \
  --private-key-file ~/.ssh/id_ed25519 \
  --path=clusters/homelab

This will bootstrap Flux and setup this repository as the flux-source for syncronization. When prompted to give access to the repository, type y.

The private key mentioned here isn't strictly required as the repository itself is public. However, the secret repository (... containing all the secrets, credentials, auth info, etc. ...) is private and requires access. You can also use a GitHub app, deploy key or other means, but since I am deploying from my work machine, which also uses this SSH key to access GitHub, I can just pass this on.

Flux Reconciliation

After a change has been pushed into this repository, FluxCD will automatically detect changes about every 10 minutes. If you want to force a reconciliation early, run the following command:

flux reconcile kustomization flux-system --with-source

flux-system is the main file handling this whole repository. If you just want to update a specific kustomization, simply exchange flux-system with the flux kustomization name of your choice!

Git Submodules

apps/pvc-explorer pulls in the upstream pvc-explorer repository as a git submodule, so the Helm chart, CRDs and RBAC are read straight from upstream at a pinned commit instead of being copied into this repository.

After cloning, initialize it:

git submodule update --init
# (or clone with: git clone --recurse-submodules <url>)

Without this, apps/pvc-explorer will fail to build locally because vendor/ is empty.

Flux only includes submodule content in its artifact when spec.recurseSubmodules: true is set on the flux-system GitRepository (see clusters/homelab/flux-system/gotk-sync.yaml). That file is regenerated by flux bootstrap, which drops the field unless you pass the flag — if it disappears, the pvc-explorer HelmRelease loses its chart. When re-bootstrapping, always run:

flux bootstrap git ... --recurse-submodules