Full-infrastructure audit (all 4 nodes, 15 running LXCs, 1 VM β read-only; nothing was changed). Ordered by severity. Tick items off as they're addressed and note the date.
1. Backup job misses 9 guests. The weekly vzdump covers 105β111 + 400/401/109 but not 112 (Kitchen), 113 (Ghost), 114 (Storj), 115 (Frigate), 116 (MQTT), 117 (Authentik), 118 (OpenProject), 119 (uptime), 120 (Wiki.js). Losing 117 loses every SSO identity; 118/120 hold project + documentation data. β Add them to the job (Storj's 423G data disk arguably stays out, but its 20G rootfs + identity should be in; the Storj identity folder is irreplaceable).
2. Ceph pools at size 2 / min_size 1. One disk failure = data in single-copy while recovering; min_size 1 also risks inconsistency on flapping OSDs. β ceph osd pool set <pool> min_size 2 at minimum. Also note ~75% of capacity sits in one host (NAS): a NAS outage takes most PGs to single-copy simultaneously.
3. osd.0 (M910q, /dev/sdb, 12TB) is a failing disk β diagnosed 2026-07-12. SMART: 40,464 reallocated sectors, 205 reported-uncorrectable (normalized value bottomed at 1), active medium error / unrecovered read on Jul 9 (during the 06:00 deep-scrub window); commit latency 42ms vs 8β24ms for all NAS OSDs; 261 slow KV commits. SMART still says PASSED β it will until nearly dead; the trend is what matters. Criticality: CRUSH failure domain is host and only 2 hosts have OSDs, so osd.0 holds one full replica of ALL data (2.7 TiB, 60 PGs). If it dies, the cluster runs single-copy with nowhere to recover until the disk is replaced. β (a) order a replacement now; (b) ideally add an OSD to SuperPC first (third host = automatic re-replication); (c) to replace in place: add new disk as a new OSD on M910q, then ceph osd out 0, wait for rebalance, purge osd.0; (d) enable smartd alerts on M910q and watch Reallocated/Uncorrectable weekly β replace immediately if pending sectors stick non-zero or reallocations jump.
4. OpenProject data is in unnamed-node docker volumes on the LXC rootfs β and 118 isn't in the backup job. Postgres data would not survive an accidental docker compose down -v and has no backup. β bind-mount to cephfs like other services, add to vzdump.
5. Frigate's config lives on SuperPC local-lvm (non-Ceph) and 115 isn't in the backup job. Recordings are on cephfs, but the config/db would vanish with that NVMe. β back up /opt/frigate/config, add 115 to vzdump, consider moving rootfs to ceph-storage.
6. One password everywhere. The same standard password is used for: OS root logins, Ghost's MariaDB (root + app user), camera RTSP/ONVIF accounts, Kuma admin, Wiki.js admin. Single credential compromise = full lab compromise. β introduce a password manager + per-service generated secrets; rotate the most exposed ones first (cameras talk to vendor cloud firmware; Mailgun SMTP creds are also sitting in Ghost's compose).
7. Secrets inline in compose files (Ghost DB + Mailgun, Karakeep NEXTAUTH_SECRET, OpenProject SECRET_KEY_BASE, gluetun WireGuard private key). Authentik and Storj already use the .env pattern β extend it everywhere so compose files are safe to commit/share/back up.
8. Privileged LXCs: 107 (Immich), 110 (Arr-Stack), 115 (Frigate β which also runs its docker container privileged: true). None obviously needs it (Immich/Arr are plain Docker stacks; unprivileged+nesting works β proven by 8 other containers). β rebuild as unprivileged at next maintenance; Frigate may keep container-privileged for hwaccel but the LXC itself can likely drop it.
9. Dead corosync nodes (R610, R710-2) leave quorum at 4-of-6 β one more node down freezes cluster management. β pvecm delnode both (they're a month cold), or plan their return.
10. Auto-updates almost nowhere. unattended-upgrades runs only in the Wiki.js LXC and Jellyfin VM. Debian LXCs otherwise collect security debt silently. β apt install unattended-upgrades + enable, everywhere (5-minute loop over pct exec).
11. Proxmox firewall is decorative. firewall=1 on most NICs but no cluster/VM rules exist β zero filtering. Either write rules (at least isolate cameras once VLANs exist) or remove the flags to avoid false confidence.
12. Ollama API (.208:11434) is LAN-open with no auth β anyone on the LAN can run models / pull data through it. Odysseus binds its other components to loopback correctly. β bind Ollama to 127.0.0.1 (compose already reaches it via host-gateway) or firewall it.
vm-102-disk-0 (wrong-VMID name from an old migration) on the aliased immich-data storage entry, plus an orphaned unused0: immich-data:vm-107-disk-1. Clean up the unused disk; optionally rename the image at next maintenance.docker.io 26.x in 105/106/108/110 vs upstream docker-ce 29.x elsewhere. Standardize on docker-ce when convenient.searchdomain: 8.8.8.8 junk value on all LXCs (harmless).N8N_SECURE_COOKIE=false β fine for LAN/HTTP access, but since n8n.codycodez.com serves HTTPS via NPM it could be re-enabled.hanna-household on tailnet) has no discoverable LAN address β undocumented device; Kuma only pings its tailnet name.