Skip to content

plex-server

The home server itself: Ubuntu 24.04 on a Dell OptiPlex 7050, hostname Plex, 192.168.5.15. SnapRAID (3 data + 1 parity) under mergerfs, ~36 docker containers, Immich, Plex/Jellyfin, the Garmin→Calendar scheduler. Repo: not a repo — the working directory is /home/angel itself.

The notes for this machine are not in this vault. They live in an ICM system map at ~/Notes/map/ (its own git repo), because they document a live machine rather than a codebase: object cards for the nouns, process cards for the verbs, and a change-impact index.

Status

  • 2026-09-08: storage hardening at v9 — 15 of 21 items done. Item 05 (off-box copy of photos + EmbeddedEra) is the only remaining permanent-loss risk. Items 15, 16B, 17 run unattended this week from ~/maintenance/.

Decisions

  • Version history is a restic repo on the pool, not rsnapshot's tree in parity: 3.5M hardlinks rotating hourly can never be parity-protected (45k-file array, 500-deletion precheck limit); a few thousand immutable pack files can. Same repo replicates off-box unchanged. 2026-09-08.
  • Server facts live in ~/Notes/map/ cards, one home per fact; this vault keeps user/project context and links to them. Memory under ~/.claude/projects/-home-angel/memory/ stays for user and feedback facts only.
  • Root work goes through a scoped, revocable /etc/sudoers.d grant the human installs, then revokes — never blanket NOPASSWD. See ~/Notes/map/processes/root-maintenance.md.
  • Long maintenance runs as root systemd one-shot timers writing markdown reports, not as agent sessions — zero tokens, survives a dropped SSH connection.

Gotchas

  • History protection is "any one drive, from 2026-09-09 forward": the restic repo enters parity at the first 03:30 sync after each snapshot; pre-2026-09-08 history (rsnapshot, back to March) is still disk1-only; same-day writes are unprotected until 02:20/02:50/03:30; the NVMe case needs the restic password in the password manager. map/objects/storage/history-repo has the table.
  • sudo needs a password and tool shells have no tty: sudo fails silently in agent calls, and interactive commands like gh auth login hang forever rather than erroring.
  • Claude Code's background-Bash memory supervisor kills long jobs here — free reads ~300 MB because qbittorrent and page cache hold ~11 GB reclaimable. Run long things in the foreground or from cron.
  • Never a bare docker compose up -d (the samba service has drifted from the live samba-nas container) and never a bare snapraid sync (the guard + precheck exist to stop a mass delete reaching parity).
  • Read SMART history from /var/lib/smartmontools/attrlog.*.csv — world-readable, no root, and it does not wake a sleeping disk.
  • Ponytail (v4.9.0): /plugin commands must be typed at the Claude prompt; typed into bash they fail with No such file or directory. Its hooks are node-based and only load on a fresh session.

Open

  • erp-sandbox token prints a token but does not write it into ~/.config/assistant/env.sandbox (its header says it does). Every sandbox reset leaves the assistant-sandbox with a dead token until someone pastes it. Make erp-sandbox token rewrite the ERP_TOKEN_* lines (all five reuse one token today).
  • Kanboard project membership drift: the task migration (2026-09-13) made both people members of every project, so Yara can open Administration/Engineering/Finance/Production boards. onboard kanboard-sync only ADDS members by department; make it also remove membership a person's departments do not grant (keep the assignee rule: a task can only be assigned to a member). Found 2026-09-14 while scoping the intake close-out picker, which now uses departments.yml instead of membership.

See ~/Notes/tasks.md — this section is now generated from the task register.

Log

  • 2026-09-11: Listmonk added to the torrentvpn stack for the EmbeddedEra newsletter (listmonk + listmonk-db, postgres:16-alpine) — LAN-only by design, never exposed to the internet: 127.0.0.1:9000 loopback only, list.lan via NPM (host id 25) for admin access. Creds in ~/.config/credentials/listmonk.txt (admin login, db password, and an API-user token for list-sync scoped to just the "Engineering notes" list, id 3). Backup: docker-compose.yml.bak.20260911-listmonk. Site side (embeddedera-site-apple: functions/api/subscribe.ts, SubscribeBlock.astro, i18n) writes signups to R2 subscribers/; ~/.local/bin/list-sync (cron candidate, not yet installed — line printed for review, not added) pulls them in every 15 min and deletes the R2 object on success. Blocked on Angel: a Resend API key (or Workspace SMTP) before Listmonk can actually send the double opt-in confirmation — see Notes/projects/growth-plan.md §1.2.
  • 2026-09-10: Server secrets imported into Vaultwarden (Bitwarden JSON import, 12 items, folder "Plex server"); import file shredded. Only copies of ~/.config/{tesla,restic,credentials} are now NVMe + the vault (vault data in docker-backup nightly).
  • 2026-09-10: Vaultwarden LIVE at https://vault.embeddedera.com — Cloudflare A record (DNS-only, 192.168.5.15), Let's Encrypt via DNS-01 (Cloudflare token stored in NPM), NPM proxy host → vaultwarden:80 (websockets, force SSL). First account angelgdo7@gmail.com; SIGNUPS_ALLOWED=false. NPM admin password was lost → new ~/.local/bin/npmpass helper (needs sudo, data dir is root-owned); creds in ~/.config/credentials/npm.txt.
  • 2026-09-10: Added Vaultwarden (self-hosted Bitwarden) to the torrentvpn stack — vault.embeddedera.com, NPM-only, no host ports, data in ~/torrentvpn/vaultwarden/data (nightly docker-backup). Chosen over Bitwarden cloud/1Password (free rule) and KeePassXC (no sync). Map card map/objects/containers/vaultwarden.md. Angel still has to do DNS + cert + first account.
  • 2026-09-10: build-index.sh no longer hard-codes /home/angel (the Mac's silent-data-loss finding) — $HOME, no-op elsewhere; bin/notes-sync is now the single implementation (dry-run + auto message merged in), ~/.local/bin/notes-sync symlinks to it; weekly prompt adopts delete-not-tick; item 17 removed from Open per that rule (closed clean 09-09).
  • 2026-09-09 22:10: bin/notes-sync.cmd added for Windows. Chose PATH-plus-setx over symlinks so Developer Mode is never required; restore.sh stays Mac/Linux-only. .gitattributes added to keep *.cmd CRLF and the extensionless bin/ scripts LF. Not yet run on DESKTOP-1LK2GJK.
  • 2026-09-09 22:00: new-machine setup fixed. notes-sync and part-lookup existed only on the Mac in ~/.local/bin and were never tracked, so restore.sh handed every new machine rules it could not follow. Both are now vendored to bin/ and symlinked in by restore.sh (symlink, not copy, so a vault pull updates them); added a PATH check and split the mangled ponytail/i-have-adhd echo. Verified by running restore.sh on the Mac. Windows symlink support still unresolved.
  • 2026-09-09 16:30: notes-weekly installed (Sun 19:30, Opus, branch + PR gate, usage-limit retry until 22:30). Deadline for the race-week override removal: after 09-14.
  • 2026-09-09 16:15: routes repo created (github.com/angelEmbeddedEra/routes, private) with both Sandling bike courses; both loaded on the Garmin (courses 512961452/512962555) and the Magene C606 V2. Sunday multisport RACE PRACTICE workout 1693043006 with per-section speed/cadence. ~/maintenance/output -> map/reports/ symlink; notes-nightly cron 23:55. Tonight 23:00 badblocks; Fri 08:00 dedupe.
  • 2026-09-09 11:00: parity drill PASSED. Found and fixed the precheck waking the parity disk via SMART (sdb sat at 55 °C for 2.5 h doing nothing); hd-idle cannot see SMART spin-ups.
  • 2026-09-09: history repo is in parity (03:30 sync clean). False "SnapRAID FAILED" push at 23:00 was maint-badblocks's guard matching its own subshell — fixed, alert renamed, installer re-dates timers.
  • 2026-09-08: restic 0.19.1 installed user-space; history repo initialised on the pool; nightly 02:50 + Sunday 05:30 jobs in angel's crontab (duplicate 02:20 precious-sync line removed). Initial backup done 17:03: 27 min, 90 G / 5,399 packs, restore drill PASS. Parity covers it from the 09-09 03:30 sync.
  • 2026-09-08: built ~/Notes/map (15 object cards, 8 process cards); confirmed the WD idle3 fix latched; scheduled hardening items 15/16B/17; installed Obsidian and the icm-architect skill; linked these global rules.
  • 2026-09-14 Grafana landing pages: ee-start (links only) is the org default, ee-home (System folder, headline stat from every report) for Administration, per-team homes via reports-sync HOME_BY_TEAM. Verified through the auth proxy as adiaz (→ ee-home) and yrosado (→ ee-sales, 403 on System/Quality). See grafana.
  • 2026-09-14 Close-out loop live: Review column + close-on-Done in all projects (onboard kanboard-sync), SOP-017 v1.1 published, task-verify every 5 min (first real pass: task 177), sop-tasks and intake write Verify: blocks, sop-audit check renamed closed-unverified, Waiting on you shows human checks. See kanboard.
  • 2026-09-14 SOP-017 v1.2: every task needs assignee, due date, concept, Deliverables + Verify. 86 unowned tasks assigned to department defaults (Sales/Purchasing → Yara, rest → Angel); tasks-deliverables (Haiku, ~$0.004/task) backfills the blocks; audit checks open-unassigned / open-no-due / open-no-deliverables now read Kanboard over the API.
  • 2026-09-14 Intake gained New task (AI scrub to SOP-017 form) and Idea (Ideas project, no due/deliverables). Deliverables backfilled on 121 tasks; 30-day default due on 122. Open: tasks 72 and 128 still lack deliverables (Haiku could not parse them, write by hand).
  • 2026-09-14 Resend quota blown (200 emails: Kanboard per-event mail during the bulk assign). Kanboard email OFF for all; _mailbudget.py (60/day) now fronts tasks-digest, tasks-notify and the assistant mailer; tasks-notify hourly batched per person. SOP-017 v1.4. Books queue no longer shows intake tasks/ideas (intake_kind filter).
  • 2026-09-14 "Waiting on you" moved from home.embeddedera.com to the notebook front page (notebook-build waiting_section: proposals, drafted site notes, pending human checks; notebook-publish also watches those two sources). Home page API kept; approve/reject buttons retired — decide by editing the Status line or publish-note.
  • 2026-09-14 Opening stock count: intake "Stock count" (barcode → OCR → Haiku) + /stock queue confirming into the ERP; SOP-023 published, SOP-005 v1.6 cross-refs it. Sandbox token note: erp-sandbox token only prints; env.sandbox ERP_TOKEN_* must be pasted by hand (to-do below).
  • 2026-09-14 Stock queue complete: create-part-and-add-stock, New bin, direct Zebra printing (192.168.5.16:9100), label QR = ERP page URL, INVENTREE_BASE_URL fixed to the public host. Resistor row #184 ready for one press.
  • 2026-09-14 First real stock count (22 parts, 19 stock items). Faults fixed: task-verify erp: check used the public host (Access login → cannot tell) → local URL; create-part left orphans when the manufacturer step 403d → reuse same-name part, manufacturer/supplier best-effort, company POST falls back to the owner token; Verify line now follows the chosen part. Deleted duplicate parts EE-C-0156/0161/0168 (no stock). Labels tool live; camera scan in progress.