Files
homelab-services/README.md
T
duynguyen 26526ecc50 fix: add ACTUAL_E2E_PASSWORD_1 to actual-budget-exporter
Budget is E2E-encrypted; exporter fails with 'File ... is encrypted' without
this. Sourced from the same hand-created Secret as the other credentials.
2026-09-03 15:44:19 +07:00

107 lines
4.9 KiB
Markdown

# Homelab Service — Apps
Third bootstrap layer, run after `cluster-bootstrap` and `cluster-platform`.
Personal/homelab apps (not cluster infra, not shared platform tooling) —
[Ignis](https://github.com/Nystik-gh/ignis) (self-hosted browser-based
Obsidian) and `actual-budget-exporter` (Prometheus exporter for a
docker-compose-hosted Actual Budget instance).
## Architecture
Same app-of-apps pattern as `cluster-platform`:
```
homelab-app.yaml ← root Application, applied once by hand (kubectl apply)
apps/<service>/
application.yaml ArgoCD Application
chart/ self-authored Helm chart (no upstream chart to point at)
```
`homelab-app.yaml` watches `apps/*/application.yaml` (recurse) only.
**Sync policy differs from `cluster-platform` on purpose:** only the root
`homelab` Application is automated (`prune: true`, `selfHeal: true`) — it
picks up new/changed `apps/*/application.yaml` files automatically. Each
per-service Application (`ignis`, and any future one) has **no**
`syncPolicy.automated` — new services or config changes sit `OutOfSync` in
ArgoCD until manually synced (UI "Sync" button or `argocd app sync <name>`).
These are personal services, not cluster infra — a manual gate before an
update actually rolls out is worth it here.
## Bootstrap
```bash
kubectl apply -f homelab-app.yaml
```
## Ignis
- Image: `nobbe/ignis:latest` — no official Helm chart, chart here is
self-authored from the docker-compose example in the upstream repo.
- 3 PVCs on `nfs-delete`: `ignis-vaults` (your actual vault data),
`ignis-data` (plugin config/state), `ignis-obsidian-app` (downloaded
Obsidian binary, avoids re-download on every restart).
- Single replica only — app has an in-process file watcher + write coalescer,
not built for multiple instances sharing a vault concurrently.
- `ignis-vaults` PVC has `argocd.argoproj.io/sync-options: Delete=false` — the
`nfs-delete` StorageClass has `reclaimPolicy: Delete`, so without this
annotation an accidental prune (app removed from git, or `helm uninstall`)
would delete your vault data on the NAS. The annotation only protects
against ArgoCD prune, not `kubectl delete pvc` by hand.
- No dedicated health endpoint upstream; probes hit `/api/version` (only
documented stable route once the server is up).
- **No built-in auth** (upstream docs explicitly warn about this). HTTPRoute
is exposed at `ignis.fireflylab.local` with no auth in front — same
LAN-only tradeoff already accepted for Vault in `cluster-platform`. Add an
Envoy Gateway `SecurityPolicy` (basic auth) later if that's not enough.
### Migrating your existing vault
The `ignis-vaults` PVC is backed by `nfs-delete` (NFS subdir provisioner) —
data physically lives on the NAS, not on any worker node. After the PVC first
binds, a subdir appears under the NAS export
(`<nfs path>/ignis-<pvc-name>-<uid>`); mount that export directly (NFS/SMB
client) or `kubectl cp` your existing vault folder into the running pod's
`/vaults` mount.
### First login / verification
```bash
kubectl get pods -n ignis
kubectl logs -n ignis deploy/ignis # first boot downloads Obsidian, 1-2 min
```
Visit `http://ignis.fireflylab.local` once the pod is Ready.
## actual-budget-exporter
- Image: `docker.io/sakowicz/actual-budget-prometheus-exporter:latest`
Prometheus exporter for [Actual Budget](https://actualbudget.org/), no
official Helm chart, chart here is self-authored.
- `actual_server` itself is **not** in this cluster — it's a plain
docker-compose container on the homelab host
(`homelab-docker-compose-prod/actualbudget`), published on the host LAN IP.
`values.yaml` points `ACTUAL_SERVER_URL` at that host IP:port, same as
`actual-http-api` does in that repo.
- No HTTPRoute — this only serves `/metrics`. A `ServiceMonitor` (labeled
`release: kube-prometheus-stack` to match that stack's default selector)
gets it scraped by the cluster Prometheus instead.
- `ACTUAL_PASSWORD` / `ACTUAL_BUDGET_ID_1` / `ACTUAL_E2E_PASSWORD_1` are
**not** in `values.yaml` — plaintext Actual credentials don't belong in a
git-committed file. They come from a Secret you create by hand once, after
the Application syncs and the `actualbudget` namespace exists.
`ACTUAL_E2E_PASSWORD_1` is required if the budget has E2E encryption
enabled — the exporter fails with `File ... is encrypted. Please provide a
password.` otherwise; pass an empty string if the budget isn't encrypted:
```bash
kubectl create secret generic actual-budget-exporter-secrets \
-n actualbudget \
--from-literal=ACTUAL_PASSWORD='<your actual budget password>' \
--from-literal=ACTUAL_BUDGET_ID_1='<sync ID from Settings → Show advanced settings>' \
--from-literal=ACTUAL_E2E_PASSWORD_1='<E2E encryption password, empty string if none>'
```
Restart the deployment after creating/rotating it:
`kubectl rollout restart deployment/actual-budget-exporter -n actualbudget`.