Commit Graph

244 Commits

Author SHA1 Message Date
7e8860ab47 update seanime docs: qBittorrent config, extensions, container doc, arriman note 2026-07-05 21:17:04 +02:00
e04d943d5c fix VPS traefik backends after Phase 1+2 migration
- Jellyfin: 192.168.8.206 → 192.168.8.246 (stale after LXC 101 migration to strong)
- House: 192.168.8.212 → 192.168.8.244 (stale after LXC 129 migration to strong)
- Jellyseerr/qbit/sab: 192.168.8.132 → 192.168.8.245 (arriman on strong)
- Added migration pitfalls section to reference doc
2026-07-05 21:03:34 +02:00
7d5e7227ca Add RomM LXC 134 docs (strong, 192.168.8.249, roms.hubris.network) 2026-07-05 20:58:13 +02:00
ec52dfb6a2 add seanime LXC 133 on strong (anime media server, 192.168.8.248) 2026-07-05 17:12:38 +02:00
bb33963539 strong migration Phase 1+2: move 5 LXCs + library split to ludo-lvm 2026-07-05 16:24:48 +02:00
2709e79455 jellyfin: VAAPI HW accel + Authentik SSO + resource bump (2026-07-04)
- Upgraded 10.11.8 → 10.11.11, enabled VAAPI (Radeon 760M)
- Bumped to 4 cores / 8 GiB RAM / 1 GiB swap
- SSO-Auth plugin v4.0.0.4 with Authentik OIDC
- Removed Caddy forward-auth gate (incompatible with SSO plugin)
- Updated container doc with full SSO architecture + pitfalls
2026-07-04 22:00:46 +02:00
831794e98c docs(rclone): root-cause the "stalls" as OOM, not Proton; bump RAM to 2G
The recurring silent-freeze incidents on LXC 132 were rclone-rcd.service
getting OOM-killed under the original 1 GiB allocation, not a protondrive
backend quirk as first suspected. journalctl confirmed the OOM kill at the
exact freeze point. Bumped LXC memory to 2 GiB (live, no reboot) and the
full folder set (cloud/documents/repos) completed cleanly afterward.

Also documents two watchdog bugs found while chasing this: a wrong
stats-group key that made a healthy sync look falsely frozen, and a
blocking systemctl restart that caused the watchdog to silently disable
itself after firing once. Both fixed; watchdog kept as a safety net.
2026-07-03 22:04:43 +02:00
6669feafdc docs(rclone): document protondrive silent-stall incident + watchdog
Two silent stalls hit in LXC 132's first 24h of real traffic: rclone's own
--timeout didn't catch a protondrive-specific hang (transfer at 100%, zero
bytes/errors/retries for hours). Added a 5-min watchdog timer that restarts
rclone-backup.service if transferred bytes are frozen for 15+ min. Also
found and fixed a monitoring bug in the runner (wrong stats-group key) that
made a healthy sync look falsely stalled for 22h in its own log.
2026-07-03 12:32:53 +02:00
ba93c4709b docs(rclone): LXC 132 rclone -> Proton Drive backup; deprecate restic-on-USB
New off-host backup job replacing the disabled restic-on-USB backup: LXC 132
`rclone` mirrors selected /mnt/library folders to Proton Drive (plain rclone
sync, Proton's built-in E2E, no crypt overlay) on a monthly timer, with
rclone's Web GUI for LAN-only browsing/ad-hoc runs and live job status.

- containers/132-rclone.md: full design, Proton auth gotcha (TOTP secret vs
  live code), pct exec PATH gotcha, rc-API job-visibility runner rewrite,
  selected folder set (cloud/documents/repos), deferred tracked-repo note.
- infrastructure/backups.md: restic-on-USB marked DEPRECATED/superseded,
  leads with the new job now.
- containers/index.md, README.md, infrastructure/media-permissions.md:
  register the new container.
2026-07-02 00:37:10 +02:00
root
5887129202 client-add: rclone (finalize age_pubkey + grant shared secrets) 2026-07-01 23:50:37 +02:00
root
1ad31fe33a client-add: rclone 2026-07-01 23:37:32 +02:00
4e3ec61fb0 chore: ignore __pycache__/*.pyc
Left behind by py_compile-checking bin/homelab's syntax during today's
bugfix session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 22:51:44 +02:00
abb1476fc8 fix(homelab): cmd_sync missing the geteuid guard every other command has
Every other mutating subcommand (secret, refresh-creds, client add/remove)
already re-execs via sudo only when os.geteuid() != 0. cmd_sync was the
one exception, calling sudo unconditionally — fails with "No such file or
directory: 'sudo'" on minimal root-only images (no sudo binary at all),
hit live running `homelab sync` on strong over root SSH.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 14:02:07 +02:00
dee08b97a4 secrets: grant strong access to hello.yaml and gitea-pat.yaml
Standard baseline for an enrolled workstation-class client, matching
mac-mini/republic-laptop/etc: the bootstrap decrypt-test secret plus
the write-scoped Gitea PAT so strong can push to the wiki repo on its
own (homelab client add/remove, wiki edits from that host).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 14:01:00 +02:00
359f55a695 docs(strong): record age-key issuance and the 3 bootstrap.sh bugs found fixing it
strong now has its own age key (issued over LAN via --no-mesh),
pubkey recorded in inventory.yaml. Not yet granted to any secrets
file - that's a separate decision.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:40:47 +02:00
fc62cf38f7 fix(bootstrap): add --no-mesh so LAN-only secrets issuance doesn't block on Netbird SSO
Running bootstrap without --no-secrets always tried to install and
connect Netbird, even when the mesh-check right after it already knows
how to fall back to plain LAN reachability. On a host nobody's watching
interactively (e.g. driven over SSH), this hangs forever at the
device-code prompt — hit live on strong, had to kill the stuck
`netbird up` process manually. --no-mesh skips netbird install/up while
still allowing the existing LAN-fallback path to satisfy secrets
issuance.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:38:21 +02:00
b266c3f1d8 fix(bootstrap): sops has no apt/dnf package, fetch the binary directly
Discovered live re-running bootstrap on strong for secrets issuance:
apt-get install sops fails outright (no such Debian package — matches
what agent-enrollment.md's manual-install recipe already does, fetching
the binary from GitHub releases instead of a package manager). dnf would
have the same problem. Added install_sops_binary(), used on both the
dnf and apt paths; Darwin still installs via brew, which does carry sops.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:34:12 +02:00
fdab6282e6 fix(bootstrap): don't invoke sudo when already running as root
The pipx/mcp-CLI step and the Hermes goose installer both called
`sudo -u <user> ...` unconditionally. On minimal Linux images reached
via `ssh root@host` (no SUDO_USER, and often no `sudo` binary at all —
seen live on strong), this failed with "sudo: command not found" and
silently no-opped the mcp CLI install. Added a run_as() helper that
only shells out to sudo when there's a real invoking user distinct
from root.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:33:19 +02:00
e4b529b71b docs(strong): record homelab-context client enrollment
bootstrap.sh --no-secrets ran clean: sync timer, homelab CLI, and
AGENTS.md are live on strong. Noted two follow-ups: secrets issuance
is reachable over plain LAN (mesh: lan) so age-key enrollment doesn't
actually need Netbird, and bootstrap's pipx/mcp-CLI step silently no-ops
when run as root over SSH (missing `sudo` binary).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:30:05 +02:00
c012a9124f infra: join ludo-mini to hubris as Homelab cluster node "strong"
Reformatted the ludo-mini workstation to Proxmox VE 9.2.3 and joined it
to hubris's existing single-node "Homelab" cluster (2 nodes, no QDevice
yet). Added a second NVMe as its own LVM-thin pool (ludo-lvm). Renamed
the wiki/inventory identity from ludo-mini to strong to match the OS/
cluster hostname, since bootstrap's client-enrollment lookup depends on
that match. Also regenerated hosts/grimmory.yaml, which was missing from
git despite being referenced by inventory.yaml.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 12:28:24 +02:00
41df77fb20 docs(runbook): update budget-from-csv with API corrections and Cookie Share calc
- Fix subscription path to /budget/subscriptions (not /subscriptions/)
- Document RRULE rejection; use cycle_interval instead
- Add GET /budget/ vs ?month= behavior note
- Add full category/payment-method ID tables
- Add Cookie Share recommendation: 2,650 €/month based on 6-mo analysis

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 11:45:34 +02:00
b67389b137 docs(operations): add budget-from-csv runbook for Yuvomi
Step-by-step procedure to import N26 CSV transactions into Yuvomi's
Budget and Subscriptions modules using the yuvomi-mcp tools.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 10:55:25 +02:00
45b7813eb7 chore(grimmory): finalize age_pubkey for LXC 130
Fills in the age public key issued by secrets-issuance after
homelab client enrollment completed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 09:17:31 +02:00
8f6f43eeb1 docs(grimmory): fix IP assignment — PVE static config, not DHCP reservation
All LXCs use ip=<addr>/24 in pve net0 config directly. No Fritz!Box
lease needed. Updated container doc and migration runbook accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 08:52:34 +02:00
c2c257aa12 docs(grimmory): correct Authentik OIDC setup notes
OIDC config migrated from Booklore DB dump — Confidential client (not
PKCE), credentials intact. offline_access scope added to Authentik
provider. Backchannel logout URL set to permanent IP 192.168.8.213.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 08:48:52 +02:00
41fe34a3c3 migrate: Booklore → Grimmory on new LXC 130
Grimmory (grimmory-tools/grimmory) is the community fork/successor of
Booklore. Moving it off the shared apps LXC (105) onto a dedicated
container (130, 192.168.8.213) to avoid the Portainer-managed stack
footgun that wiped mariadb in April.

- containers/130-grimmory.md: new container doc with compose layout,
  Authentik OIDC notes (PKCE/Public client), media-GID setup
- plans/2026-06-29-grimmory-migration.md: step-by-step runbook for
  DB dump/restore, LXC provisioning, Caddy cutover, Authentik update
- inventory.yaml: add grimmory LXC 130
- containers/105-apps.md: remove Booklore section + hostname entry
- containers/index.md: update 105 row; add 130 row
- infrastructure/media-permissions.md: add LXC 130; update Booklore→Grimmory refs
- README.md: update 105 row; add 130 row

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-29 01:11:00 +02:00
b6c9184a7b decommission: destroy plato (LXC 126)
LXC 126 stopped and destroyed on hubris. Remove all live references:
inventory, container doc, host file, README, containers index, auto-deploy
pipeline, DNS entry, SSH access table, nfs-export mount list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 22:32:59 +02:00
root
636c90f99c secrets: populate hermes-house-users with household Signal numbers
+4917622791635 → Yuvomi user 1 (Taco)
+491726924525  → Yuvomi user 3 (Steffi)
2026-06-28 16:50:51 +02:00
root
cef1b836c2 sops: add yuvomi-api-token + hermes-house-users secrets (house + workstations) 2026-06-28 16:02:13 +02:00
root
335498d069 client-add: house (finalize age_pubkey + grant shared + hermes secrets) 2026-06-28 15:59:47 +02:00
root
867998e9c0 hosts: regenerate — add house, mac-mini, ludo-mini; remove stale orphans 2026-06-28 15:58:36 +02:00
cb0c1a5c0d house: add Google Calendar OAuth config to docs 2026-06-27 14:40:29 +02:00
ddf541ebd3 house: switch Paperless to native DMS connector (remove WebDAV bridge) 2026-06-26 19:57:50 +02:00
4472e73ae1 Yuvomi deployment: LXC 129 house.hubris.network, Docker, Caddy, DNS, VPS traefik, Authentik OIDC, Paperless WebDAV bridge 2026-06-26 19:06:49 +02:00
59261c7ef1 hosts: generate trmnl.yaml (prereq for SOPS enrollment of LXC 128) 2026-06-24 23:41:29 +02:00
41f22c2d85 trmnl (128): auto-deploy pipeline + LAN DNS record wired
- auto-deploy.md: dtoro/terminalito pipeline (webhook 12, :9797), ALLOWED_HOST_LIST
  += 192.168.8.211, changelog
- 128-trmnl.md: auto-deploy now wired, Technitium A record done, changelog
- 107-dns.md: A record trmnl -> 192.168.8.175 (changelog)
- 104-gitea.md: webhook id 12 + allowed host (changelog)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 18:06:56 +02:00
b7cfc350b3 trmnl (128): public path verified live; root-cause the mesh outage
Root cause of the provision-time 504s: netbird home-lab-network (192.168.8.0/24)
had no active routing peer — mac-mini routing peer's netbird daemon was down, so
all home-backed public services (artifacto/blog/trmnl) 504'd at the VPS edge.
netbird up on mac-mini restored it; verified trmnl public 200/401, artifacto 200.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:38:57 +02:00
fffa5560eb trmnl (128): provisioned — container page, inventory, ingress
LXC 128 trmnl hosts the TRMNL plugins middleware (dtoro/terminalito), polled by
TRMNL cloud. trmnl-plugins.service on :9851; Caddy block + LE cert; VPS traefik
router trmnl-public + cert mirror. Public path pending VPS<->home netbird route
recovery (was "No networks available" at provision time, artifacto/blog 504 too).
LAN Technitium record + SOPS enrollment + Google/MVG creds pending. Plan -> In Progress.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 17:24:31 +02:00
d6bfd7b8c9 plans: TRMNL plugins LXC (128) + middleware deploy pipeline
Pre-flight runbook for a dedicated trmnl LXC hosting self-hosted middleware for
TRMNL e-ink plugins (TRMNL cloud polls /<plugin>/dashboard). First consumer:
munich-home. Source repo dtoro/terminalito; this documents the fabric wiring
(provision via homelab client add, Shape-B auto-deploy, SOPS secret, caddy + VPS
traefik exposure). Status: Planned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:59:03 +02:00
b71402aaed add auth-outpost (106) and dns (107) to inventory + regenerate host files 2026-06-22 09:31:04 +02:00
2a7876c711 add caveman compression mode to agent bootstrap
AGENTS.md now instructs every agent to communicate
tersely. CAVEMAN.md holds the full rules. Agents
apply from first message in each session.
2026-06-21 23:36:06 +02:00
a5da521751 docs: Fritz!Box DNSv4 set to Technitium (192.168.8.2) — household LAN now resolves *.hubris.network 2026-06-18 00:41:36 +02:00
4c83960035 docs: sab.hubris.network Authentik auth — update arriman + caddy pages 2026-06-13 11:58:21 +02:00
ddc5e8771a docs: Authentik session lifetime investigation, fix docs, changelog 2026-06-06 23:45:59 +02:00
ebf521007d docs: emphasize Caddyfile must be edited via dtoro/caddy-conf repo, not directly on LXC 2026-06-06 14:17:12 +02:00
ab3d484824 docs: add investigation entry for 2026-06-05 authentik ident stage skip (broken Trust me policy) 2026-06-05 20:08:28 +02:00
35b1a25f08 fix: remaining DHCP drifts + improve validation script
- Fixed apps LXC 105: /etc/network/interfaces was still 'iface eth0 inet
  dhcp' -> changed to static 192.168.8.205/24, killed dhclient, applied
- Fixed mule-images LXC 120: DHCP client had overridden static .136 with
  DHCP lease .108 -> killed dhclient, restored .136
- Fixed sophia docs: inventory said .157, actual Proxmox config is .109
- Updated check-caddy-backends.sh: uses curl with connect-timeout for
  reliable TCP checks, distinguishes 'port open / no HTTP' from 'unreachable'
2026-06-05 17:59:46 +02:00
b3729a941e fix: gitea DHCP drift + add caddy backend validation script 2026-06-05 13:21:58 +02:00
3a2270ba86 fix: update paperless (192.168.8.130→243) and haos (192.168.8.101→241) after DHCP lease changes
- Caddyfile updated on caddy LXC with new backend IPs
- inventory.yaml updated to reflect current DHCP assignments
- hosts/{paperless,haos}.yaml regenerated from inventory
2026-06-05 10:51:51 +02:00
6d808a1fd8 arriman: SABnzbd HTTPS enabled on port 9090 2026-06-05 00:21:56 +02:00