The N100 becomes the lived-in box (09 §3 decision 254): media apps installed and wired through the dashboard; films proven never off-site; the USB split NOT done (it is the whole-guest backup target)
gates / gates (push) Successful in 6m59s
gates / gates (push) Successful in 6m59s
- 09 §3 decision 254 (operator decisions 240/243 written down); target-selection: a "lived-in" tier, Tier 0 = demo-hp alone; nodes.md role + drive; 11-os-updates ring 0 wording; CLAUDE.md + docs.md: the diary. - documentation/lived-in/n100.md (new diary); audits/n100-lived-in-2026-10-15/ (state, drive read, Part C capture sets, installs, wiring, stranger probes, demo-hp clean-up, the operator's SHEET.md). - Register: R-1062 (the split, operator decides), R-1063 (decommission half-state on an agent refusal), R-1064 (path removal silent about cross-drive copies), R-1065 (a claimed Plex gets no libraries until a wiring run). - demo-hp: /mnt/sizing-bench removed through the dashboard; the hub shows demo-hp OK (14:56 UTC). Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -17,6 +17,7 @@ repo. Sibling repos point here; this is where the pointed-at thing must actually
|
||||
| host addresses, routes, node names, break-glass, what is provisioned | `operations/nodes.md` |
|
||||
| Tailscale topology, accept-dns/accept-routes | `operations/tailscale.md` |
|
||||
| which box may be broken, and what may be done to it | `runbooks/target-selection.md` |
|
||||
| what happened on the lived-in N100 (dated, each line with its register row) | `lived-in/n100.md` |
|
||||
| an operational procedure | `runbooks/RUNBOOK-*.md` |
|
||||
| logging levels and phrasing | `runbooks/logging-conventions.md` |
|
||||
| a spike or campaign result | `audits/` |
|
||||
|
||||
@@ -33,6 +33,7 @@ Four surfaces in one repo, plus the design home for the whole system:
|
||||
| UI, tokens, badges, Hungarian copy | the **`felhom-ui-design`** skill |
|
||||
| host addresses, break-glass, node facts | `documentation/operations/nodes.md` — never restate them |
|
||||
| which box may I break | `documentation/runbooks/target-selection.md` |
|
||||
| a problem seen on the N100 (the lived-in box, `09` §3 decision 254) | goes into `documentation/lived-in/n100.md` AND the register |
|
||||
| what version is live anywhere | ask the hub (`/hosts`, `/configs`) or the box — **never a doc** |
|
||||
| the authoritative design | `documentation/architecture/01..11-*.md` (00 = the capability map) |
|
||||
|
||||
|
||||
@@ -25,6 +25,13 @@
|
||||
> while a release is ahead. CC has no scoped route to the global floor (R-1051) — only the operator page with the
|
||||
> operator's password. A box on an `-rc` tag is never moved by the floor (R-1053).
|
||||
|
||||
> **2026-10-15 (evening, last) — the N100 is the lived-in box (`09` §3 decision 254).** Product paths only; no
|
||||
> deliberate failure without the operator's word; diary `documentation/lived-in/n100.md`; Tier 0 is demo-hp alone. Media
|
||||
> apps installed through the dashboard and wired by the box; films proven never off-site (the controller's classifier;
|
||||
> vzdump excludes mp8). The USB split was NOT done: `hdd_1` is the whole-guest backup target (R-1062, operator decides);
|
||||
> the decommission flow's half-state on an agent refusal is R-1063; a claimed Plex gets no libraries until a wiring run
|
||||
> (R-1065). The box-walk library has no N100 row: `audits/n100-lived-in-2026-10-15/tools/n100.py` overrides it.
|
||||
|
||||
> **2026-10-15 (evening, later) — controller v0.314.0, the first release under decision 250.** The floor 0.314.0 (MinAgent
|
||||
> 0.155.0) was raised at 13:11 UTC by CC's token (`HUB_TOKEN` in `~/.config/credentials`, not `~/.felhom-hub/cc-token`)
|
||||
> after Tester 1, demo-hp and demo-felhom ran it through per-customer floors and the box walk's checks were green; the
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# REPORT — the N100 becomes the lived-in box (2026-10-15)
|
||||
|
||||
Written in ASD-STE100 Simplified Technical English. Read first: `runbooks/target-selection.md`, `operations/nodes.md`,
|
||||
`07-backup-architecture.md`, `15-media-library.md`, `09` §3 decisions 240, 243, 250. Evidence:
|
||||
`documentation/audits/n100-lived-in-2026-10-15/`.
|
||||
|
||||
## What waits on you
|
||||
|
||||
1. **The sheet** (about 30 minutes): `documentation/audits/n100-lived-in-2026-10-15/SHEET.md`. Install and claim Plex;
|
||||
make the admins in Prowlarr, Sonarr and Radarr; add download sources in Prowlarr; add one show and one film. Then say
|
||||
„done". If you do nothing, the apps wait, safe behind their gate.
|
||||
2. **Decide (R-1062):** the USB drive is also the box's whole-box backup drive. Split it anyway? My pick: **no, keep one
|
||||
drive**. If you do nothing, it stays one drive.
|
||||
|
||||
## 1. The lived-in rule, and the files
|
||||
|
||||
`09` §3 **decision 254**:
|
||||
- The N100 changes only through the product: the dashboard, the hub, the release train, the OS update rings.
|
||||
- No deliberate failure without your word for that one act.
|
||||
- Reads and observation are free. A problem goes into the diary and the register.
|
||||
- It is not Tier 2. It is no longer „reach here first".
|
||||
|
||||
Decisions 240 and 243 point at it now.
|
||||
|
||||
Files changed:
|
||||
- `architecture/09-update-architecture.md`;
|
||||
- `runbooks/target-selection.md` (a new „lived-in" row; Tier 0 is demo-hp alone; the N100 section rewritten);
|
||||
- `operations/nodes.md` (role and drive lines);
|
||||
- `architecture/11-os-updates.md` (ring 0 no longer calls the N100 disposable);
|
||||
- `CLAUDE.md` and `.claude/rules/docs.md` (one line each: the diary);
|
||||
- `documentation/lived-in/n100.md` (new);
|
||||
- `STATUS.md`, `CONTEXT.md`, the register.
|
||||
- My own memory index: it called both demo boxes disposable.
|
||||
|
||||
## 2. What the N100 had, and what the 6 GB is
|
||||
|
||||
- Controller 0.314.0, agent 0.156.1. Guest: 12 GB of memory, 0.2 GB used. One app (opengist).
|
||||
- The five media apps need about 2 GB by the estimator's rule. They fit.
|
||||
- `/dev/dri`: the host has it, the guest does not. So Plex cannot use hardware transcoding today.
|
||||
- **The USB drive is not only app test data.** It holds:
|
||||
- 2.7 GB: the box's nightly whole-box backups (`dump/`). The host storage `felhom-backup` points at this drive.
|
||||
- 3.1 GB: app backups and an off-site restore copy.
|
||||
- 422 MB: leftovers of removed apps.
|
||||
- Empty media folders.
|
||||
|
||||
There are no family files on it.
|
||||
- **So I did not split it.** It is the box's whole-box backup target. The product refuses to retire such a drive, and the
|
||||
box has no other drive to take that role. I also did not press the retire button. Reading the code showed that a
|
||||
refused retire leaves the dashboard showing the drive as retired (R-1063).
|
||||
|
||||
## 3. Films and off-site — proven before any download
|
||||
|
||||
I ran the controller's own classifier on the deployed apps:
|
||||
- off-site takes no media folder;
|
||||
- the cross-drive tier would take only qBittorrent's downloads, and only if someone switches it on. It is off. With one
|
||||
data drive it falls back to the internal SSD, and takes state only, not downloads;
|
||||
- the whole-box backup's own log says: „excluding bind mount point mp8 ('/mnt/felhom-drives')".
|
||||
|
||||
## 4. What the box linked by itself
|
||||
|
||||
- I installed qBittorrent, Prowlarr, Sonarr and Radarr through the dashboard's own call, and sent no drive. Each was
|
||||
healthy in under 35 s. The box picked `hdd_1` by itself.
|
||||
- From the apps' own answers:
|
||||
- Sonarr: `…/media/tv`. Radarr: `…/media/movies`. Both have the tag `hdd-1`, and qBittorrent as their client.
|
||||
- qBittorrent: the categories `tv-hdd-1` and `movies-hdd-1`, saving under `…/media/torrents/` on the same drive.
|
||||
- Prowlarr: linked to Sonarr and Radarr.
|
||||
- A stranger meets the gate on Prowlarr, Sonarr and Radarr, and qBittorrent's own login.
|
||||
- **Not done by itself:** a freshly claimed Plex gets no libraries until the next linking run (R-1065, from the code).
|
||||
The sheet tells you what to press if it happens.
|
||||
|
||||
## 5. demo-hp's warning
|
||||
|
||||
Gone. I removed `/mnt/sizing-bench` through the dashboard, and the hub showed demo-hp **OK** at 14:56 UTC. The path held
|
||||
two apps' cross-drive copies, and the dashboard said nothing about them (R-1064).
|
||||
|
||||
## 6. Wrong claims in the prompt; commits; register; STATUS
|
||||
|
||||
**Claims in the prompt that turned out wrong:**
|
||||
1. „the 6.1 GB … app test data": it is mostly the box's own backups. The drive is the whole-box backup target, so the
|
||||
split cannot go through the product.
|
||||
2. „The box wires … Plex by itself": not right after the claim (R-1065).
|
||||
3. „HD710 PRO": that is the USB enclosure. The disk inside is a TOSHIBA MQ04ABF100 (931.5 GB). True, but incomplete.
|
||||
|
||||
**Commits:** felhom.eu (this commit). No product code.
|
||||
|
||||
**Register:** before **152** · opened **4** (R-1062, R-1063, R-1064, R-1065) · closed **0** · after **156**.
|
||||
|
||||
**STATUS.md:** 61 lines.
|
||||
|
||||
**Teardown:** I installed four apps on the N100 on purpose (they stay). I deleted a temporary test file in the
|
||||
controller tree; it was never committed. On demo-hp I removed one storage path. The hub was read only, through my token.
|
||||
ep0, DooPlex and Tester 1 were not touched.
|
||||
@@ -6,6 +6,7 @@
|
||||
`documentation/backlog/STATUS-HISTORY.md`. Reports: `REPORT-night-2026-10-14.md`, `REPORT-immich-rollout-2026-10-14.md`, `REPORT-seo-felho-tarhely-2026-10-14.md`, `REPORT-immich-repair-2026-10-14.md`, `REPORT-power-cut-fixes-2026-10-14.md`, `REPORT-night-power-2026-10-13.md`, `REPORT-poweroff.md`.
|
||||
|
||||
## What works
|
||||
- **The N100 is the lived-in box** (since 2026-10-15): used like a household's box, changed only through the product. qBittorrent, Prowlarr, Sonarr and Radarr are installed and linked by the box; films never go off-site (checked before any download). Its diary: `documentation/lived-in/n100.md`.
|
||||
- A restored app comes back exactly as safe as it was at the backup: closed to strangers until its first account is made (0.314.0, proven on the scratch box). A box on a test build now moves with the floor (Tester 1 did, by itself). The box claims Plex again (demo-hp's Plex claimed through the dashboard, 2026-10-15). A brand-new box from the public installer updated itself to the floor 3 minutes after it was linked (test box, since removed).
|
||||
- Scripts use the hub with a scoped token, not your password (hub 0.153.0): CC sets the floor with its own token; no token can see a secret, delete anything, or send, make or show a household's password or link. Your new hub password is yours alone (changed 2026-10-15).
|
||||
- Every public name of the three test boxes answers only over https: plain http gets a 301 to the same https address, and browsers are told to remember it for one day (29 names checked, 2026-10-14 night).
|
||||
@@ -41,8 +42,10 @@
|
||||
| D6 | R-992 | The scratch box cannot read the private drill catalog: give it a read-only login, or make that copy readable? | **A read-only login** | Readable copy: the drill catalog becomes public | every new-app test needs hand-staging | new-app tests |
|
||||
| D7 | R-990, R-989 | Rule yes / no / later on the forum ideas (`audits/forum-research-2026-10-12/FELHOM.md` §5) and the selfh.st ideas (`audits/selfhst-survey-2026-10-12/FELHOM.md` §6) | — | — | nothing changes; the research ages | — |
|
||||
| D8 | R-206 | Install DooPlex's Docker settings from git (restarts Docker), and prune the build cache weekly: yes or no? | **Yes, in a quiet window** | — | a rebuild of DooPlex still has the settings in git | — |
|
||||
| D9 | R-1062 | The N100's USB drive is also its whole-box backup drive. Split it in two anyway? | **No — keep one drive**; the lived-in box keeps its nightly whole-box backup | Split: the box loses its local whole-box backup (or add a second drive first) | it stays one drive; multi-drive tests stay on Tester 1 | — |
|
||||
|
||||
## Waiting on you — do
|
||||
- **The N100 sheet (about 30 minutes):** `documentation/audits/n100-lived-in-2026-10-15/SHEET.md` — install Plex and claim it, make the admins in Prowlarr/Sonarr/Radarr, add your download sources in Prowlarr, add one show and one film. Then say „done". If not: the media apps wait, safe behind their gate.
|
||||
- **Delete the test customer „Tester3” in the hub (browser only).** Its test box is already gone and switched off on purpose, so no alarm is coming. If not: a dead test customer stays in your list.
|
||||
- **Hub 0.153.0 (your rulings 13:20 + R-1059 „A"): no token can resend a claim code, create or edit a customer, make a passphrase or a link, or re-issue an off-site password.** Live since 13:39 (checked with CC's token: all six refused).
|
||||
- **Remove the test server „plex-k6” from your Plex account** (plex.tv → Settings → Authorized Devices). The claim test passed and the server is gone from Tester 1. If not: a dead server stays listed in your Plex apps.
|
||||
|
||||
@@ -948,6 +948,26 @@ its length, and both fixes cost something the household would notice — operato
|
||||
**Extended the same day (operator, R-1059 = A):** the off-site and PBS-DR re-issues (they mint a household
|
||||
credential for the box) are session only too; „Off-site: write" keeps the windows and freeze.
|
||||
|
||||
### 2026-10-15 (evening) — the N100 is the lived-in box (recorded by the n100-lived-in task; decisions 240 and 243)
|
||||
|
||||
254. **The N100 (`demo-felhom`) is the lived-in box.** *Operator ruling 2026-10-14 (decision 240), its timing
|
||||
decision 243 (after the Tester 1 all-drives test — done 2026-10-15), written down 2026-10-15 at the operator's
|
||||
request.* Decision 240 said the rule „is recorded by the second task of 2026-10-14" — it never was; this is it.
|
||||
1. **It changes only through the product's own paths:** the dashboard, the hub, the normal release train (the floor
|
||||
under decision 250, the weekly golden), the OS update rings. No drill catalog, no hand edits inside the guest, no
|
||||
`docker` command that changes state, no reinstall.
|
||||
2. **No deliberate failure** — power cut, drive pull, drill, restore test — **without the operator's word for that
|
||||
one act.** A failure that happens by itself is observed and recorded, and repaired by hand only where the
|
||||
household could do the same.
|
||||
3. **Reads, logs, metering and observation are free.** A problem found goes into the diary
|
||||
(`documentation/lived-in/n100.md`) and the register.
|
||||
4. **It stays a demo box:** no paying customer's data; it is not Tier 2. It is no longer „reach here first" — Tier 0
|
||||
is demo-hp (and its guests and VMs) alone (`runbooks/target-selection.md`).
|
||||
5. **The one hand change granted before the rule (operator, 2026-10-15 16:31): split the USB drive in two.** NOT
|
||||
done: the drive is the box's whole-guest backup target (`felhom-backup`) and holds its nightly backups, so the
|
||||
product refuses to decommission it and the N100 has no other drive to move that role to (R-1062,
|
||||
`audits/n100-lived-in-2026-10-15/B/`). The grant is not used; a split needs a new word.
|
||||
|
||||
### 2026-10-15 (afternoon) — a restore puts the setup gate back as it was (operator brief, R-1057 raised to P2)
|
||||
|
||||
253. **A restore puts the setup gate back exactly as it was when the backup was taken.** *Operator brief 2026-10-15
|
||||
@@ -1008,6 +1028,8 @@ its length, and both fixes cost something the household would notice — operato
|
||||
(`15-media-library.md` §2; R-1014)
|
||||
243. **The N100 lived-in setup waits until the all-drives build has been tested on the Tester 1 rig.** Until then the
|
||||
N100 stays Tier 0 and is not fenced (it may host a second test rig). This replaces decision 240's timing.
|
||||
**Fulfilled 2026-10-15** (the Tester 1 rig was tested; release 0.313.0): the rule is decision 254 — the N100 is no
|
||||
longer Tier 0.
|
||||
*Operator ruling 2026-10-14.*
|
||||
|
||||
### 2026-10-14 (afternoon) — media apps on every drive (recorded before the work; the media-all-drives brief)
|
||||
@@ -1020,7 +1042,8 @@ its length, and both fixes cost something the household would notice — operato
|
||||
239. **Each drive shows whether its apps have restarted since it was added.** If they have not, a manual restart
|
||||
button is there. *Operator ruling 2026-10-14.* (R-1023)
|
||||
240. **The N100 becomes a lived-in box.** Its rule is recorded by the second task of 2026-10-14
|
||||
(`TASK-media-folder-fix-and-n100-2026-10-14.md`). *Operator ruling 2026-10-14.*
|
||||
(`TASK-media-folder-fix-and-n100-2026-10-14.md`). *Operator ruling 2026-10-14.* **That task did not record it** (its N100 part was removed the
|
||||
same evening, decision 243); the rule is decision 254 (2026-10-15).
|
||||
241. **Tester 1 may follow the drill catalog for the media test, until the operator says „tear it down".** It is the
|
||||
one exception to §6.5's fence; the teardown is R-1022. *Operator ruling 2026-10-14.*
|
||||
|
||||
|
||||
@@ -148,8 +148,9 @@ has not ruled on it as such.
|
||||
|
||||
### 5.1 Two rings
|
||||
|
||||
- **Ring 0:** demo-felhom (N100) and demo-hp. They are disposable (`runbooks/target-selection.md`), and
|
||||
they have different hardware. They take every update first.
|
||||
- **Ring 0:** demo-felhom (N100) and demo-hp, on different hardware. They take every update first. demo-hp is
|
||||
disposable; the N100 is the lived-in box (`09` §3 decision 254) — it takes ring 0 through the product like any box,
|
||||
which is the point: a lived-in box meets an update before a customer does (`runbooks/target-selection.md`).
|
||||
- **Ring 1:** every other box. It takes only what ring 0 approved.
|
||||
|
||||
### 5.2 Two lanes
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
== host
|
||||
demo-felhom
|
||||
felhom-agent 0.156.1
|
||||
total used free shared buff/cache available
|
||||
Mem: 15772 2408 8108 66 5664 13363
|
||||
NAME SIZE TYPE FSTYPE MOUNTPOINT MODEL SERIAL
|
||||
sda 476.9G disk AirDisk 512GB SSD QDF922W009654S30EX
|
||||
|-sda1 1007K part
|
||||
|-sda2 1G part vfat /boot/efi
|
||||
`-sda3 475.9G part LVM2_member
|
||||
|-pve-swap 8G lvm swap [SWAP]
|
||||
|-pve-root 96G lvm ext4 /
|
||||
|-pve-data_tmeta 3.6G lvm
|
||||
| `-pve-data-tpool 348.8G lvm
|
||||
| |-pve-data 348.8G lvm
|
||||
| |-pve-vm--9201--disk--2 32G lvm ext4
|
||||
| `-pve-vm--9201--disk--3 250G lvm ext4
|
||||
`-pve-data_tdata 348.8G lvm
|
||||
`-pve-data-tpool 348.8G lvm
|
||||
|-pve-data 348.8G lvm
|
||||
|-pve-vm--9201--disk--2 32G lvm ext4
|
||||
`-pve-vm--9201--disk--3 250G lvm ext4
|
||||
sdb 931.5G disk ext4 /mnt/hdd_1 TOSHIBA MQ04ABF100 65NOP3HDT
|
||||
VMID Status Lock Name
|
||||
9201 running demo-felhom
|
||||
== guest
|
||||
cores: 3
|
||||
memory: 12288
|
||||
mp0: local-lvm:vm-9201-disk-3,mp=/var/lib/felhom,backup=1,size=250G
|
||||
mp8: /mnt/felhom-drives,mp=/mnt/felhom-drives
|
||||
mp9: /var/lib/felhom-agent/guests/9201/bootstrap,mp=/etc/felhom-bootstrap,ro=1
|
||||
rootfs: local-lvm:vm-9201-disk-2,size=32G
|
||||
swap: 512
|
||||
gitea.dooplex.hu/admin/felhom-controller:0.314.0
|
||||
192.168.0.149 169.254.253.2 172.16.253.1 172.17.0.1 172.18.0.1
|
||||
total used free shared buff/cache available
|
||||
Mem: 12288 222 10945 8 1128 12065
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/mapper/pve-vm--9201--disk--2 32G 1.2G 29G 4% /
|
||||
/dev/sdb 916G 6.2G 864G 1% /mnt/felhom-drives/hdd_1
|
||||
ls: cannot access '/dev/dri': No such file or directory
|
||||
cloudflared Up 41 hours (healthy)
|
||||
felhom-controller Up 2 hours (healthy)
|
||||
filebrowser Up 21 hours (healthy)
|
||||
opengist Up 12 hours (healthy)
|
||||
traefik Up 12 hours
|
||||
@@ -0,0 +1,26 @@
|
||||
NAME TRAN VENDOR MODEL SERIAL SIZE
|
||||
sdb usb ADATA TOSHIBA MQ04ABF100 65NOP3HDT 931.5G
|
||||
ID_BUS=ata
|
||||
ID_MODEL=TOSHIBA_MQ04ABF100
|
||||
ID_SERIAL=TOSHIBA_MQ04ABF100_65NOP3HDT
|
||||
ID_USB_MODEL=HD710_PRO
|
||||
ID_USB_VENDOR=ADATA
|
||||
by-path
|
||||
card0
|
||||
renderD128
|
||||
== top
|
||||
total 32
|
||||
drwxr-xr-x 5 root root 4096 Jul 28 21:25 .
|
||||
drwxr-xr-x 5 root root 4096 Aug 3 09:15 ..
|
||||
drwxr-xr-x 2 root root 4096 Oct 15 04:59 dump
|
||||
drwxr-xr-x 6 100000 100000 4096 Jul 18 22:11 felhom-data
|
||||
drwx------ 2 root root 16384 Jul 18 18:41 lost+found
|
||||
== du
|
||||
2.7G /mnt/hdd_1/dump
|
||||
3.5G /mnt/hdd_1/felhom-data
|
||||
16K /mnt/hdd_1/lost+found
|
||||
== felhom-data
|
||||
32K /mnt/hdd_1/felhom-data/shares
|
||||
528K /mnt/hdd_1/felhom-data/userdata
|
||||
422M /mnt/hdd_1/felhom-data/appdata
|
||||
3.1G /mnt/hdd_1/felhom-data/backups
|
||||
@@ -0,0 +1,47 @@
|
||||
Name Type Status Total (KiB) Used (KiB) Available (KiB) %
|
||||
felhom-backup dir active 960303848 6435888 905013448 0.67%
|
||||
felhom-pbs pbs active 0 0 0 0.00%
|
||||
local dir active 98497780 32496832 60951400 32.99%
|
||||
local-lvm lvmthin active 365760512 9290317 356470194 2.54%
|
||||
dir: felhom-backup
|
||||
|
||||
== dump
|
||||
-rw-r--r-- 1 root root 950588793 Oct 13 04:53 vzdump-lxc-9201-2026_10_13-04_52_51.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 13 04:53 vzdump-lxc-9201-2026_10_13-04_52_51.tar.zst.notes
|
||||
-rw-r--r-- 1 root root 1505 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.log
|
||||
-rw-r--r-- 1 root root 951109351 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.tar.zst.notes
|
||||
-rw-r--r-- 1 root root 1504 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.log
|
||||
-rw-r--r-- 1 root root 951089306 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.tar.zst.notes
|
||||
== backups
|
||||
4.0K /mnt/hdd_1/felhom-data/backups/offsite-proof
|
||||
1.6G /mnt/hdd_1/felhom-data/backups/offsite-restore
|
||||
1.3G /mnt/hdd_1/felhom-data/backups/primary
|
||||
274M /mnt/hdd_1/felhom-data/backups/secondary
|
||||
== appdata
|
||||
12K /mnt/hdd_1/felhom-data/appdata/romm
|
||||
24K /mnt/hdd_1/felhom-data/appdata/paperless
|
||||
63M /mnt/hdd_1/felhom-data/appdata/nextcloud
|
||||
360M /mnt/hdd_1/felhom-data/appdata/immich
|
||||
== userdata
|
||||
/mnt/hdd_1/felhom-data/userdata
|
||||
/mnt/hdd_1/felhom-data/userdata/media
|
||||
/mnt/hdd_1/felhom-data/userdata/media/nzbget
|
||||
/mnt/hdd_1/felhom-data/userdata/media/usenet
|
||||
/mnt/hdd_1/felhom-data/userdata/media/movies
|
||||
/mnt/hdd_1/felhom-data/userdata/media/music
|
||||
/mnt/hdd_1/felhom-data/userdata/media/comics
|
||||
/mnt/hdd_1/felhom-data/userdata/media/podcasts
|
||||
/mnt/hdd_1/felhom-data/userdata/media/audiobooks
|
||||
/mnt/hdd_1/felhom-data/userdata/media/transmission
|
||||
/mnt/hdd_1/felhom-data/userdata/media/transmission/watch
|
||||
/mnt/hdd_1/felhom-data/userdata/media/grimmory
|
||||
/mnt/hdd_1/felhom-data/userdata/media/torrents
|
||||
/mnt/hdd_1/felhom-data/userdata/media/tv
|
||||
/mnt/hdd_1/felhom-data/userdata/media/photos
|
||||
/mnt/hdd_1/felhom-data/userdata/media/metube
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db-shm
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db-wal
|
||||
@@ -0,0 +1,7 @@
|
||||
standing now: typical 27 MB, peak 68 MB; rule (platform 470 + peak) x 1.5 = 807 MB vs guest 12288 MB -> fits
|
||||
standing + the five: typical 636 MB, peak 841 MB; rule (platform 470 + peak) x 1.5 = 1966 MB vs guest 12288 MB -> fits
|
||||
plex: typical 232 MB, peak 234 MB (measured)
|
||||
qbittorrent: typical 163 MB, peak 318 MB (onboarding)
|
||||
prowlarr: typical 41 MB, peak 44 MB (onboarding)
|
||||
sonarr: typical 77 MB, peak 77 MB (onboarding)
|
||||
radarr: typical 96 MB, peak 100 MB (measured)
|
||||
@@ -0,0 +1,16 @@
|
||||
/api/storage/paths -> 404 {"_raw": "404 page not found\n"}
|
||||
/api/disks -> 200 {"data": {"vmid": 9201, "disks": [{"name": "felhom-backup", "type": "local-dir", "state": "attached", "backing_device": "/dev/sdb", "mount_path": "/mnt/hdd_1", "class": "slow", "role": "user-data", "data_bearing": true, "data_reason": "device is mounted", "total_bytes": 983351140352, "used_bytes": 6590349312, "used_fraction": 0.00670192878369056, "durable_id": "uuid:47a3361a-91e0-4831-a69d-27f540ed3f48", "wipe_durable_id": "byid:wwn-0x5000039ddb108568", "guest_attached": false, "backup_target": true, "guest_path": "/mnt/felhom-drives/hdd_1", "bound_under_parent": true, "smart": {"health": "PASSED", "model_name": "TOSHIBA MQ04ABF100", "temperature_c": 35, "power_on_hours": 5449, "reallocated_sectors": 0, "pending_sectors": 0, "offline_uncorrectable": 0, "udma_crc_errors": 0, "critical_warning": null, "media_errors": null, "percentage_used": null}}, {"name": "local", "type": "local", "stat
|
||||
/api/backup/status -> 200 {"ok": true, "data": {"enabled": true, "running": false}}
|
||||
/api/offbox/status -> 404 {"ok": false, "error": "endpoint not found"}
|
||||
/api/backup/offsite/status -> 404 {"ok": false, "error": "endpoint not found"}
|
||||
/api/selfupdate/status -> 200 {"ok": true, "data": {"running": false, "last_check": {"current_version": "0.314.0", "latest_version": "0.314.0", "update_available": false, "checked_at": "2026-10-15T12:56:24Z"}, "last_state": {"status": "success", "previous_version": "0.313.0", "previous_image": "gitea.dooplex.hu/admin/felhom-controller:0.313.0", "target_version": "0.314.0", "target_image": "gitea.dooplex.hu/admin/felhom-controller:0.314.0", "initiated_at": "2026-10-15T12:55:48Z", "initiated_by": "auto-floor", "completed_at": "2026-10-15T12:55:54Z"}}}
|
||||
/api/storage/backup-target -> 200 {"data": {"degraded": false, "known": true, "label": "Külső tárhely (hdd_1)", "target": "felhom-backup"}, "ok": true}
|
||||
/api/storage/media/status -> 200 {"data": {"pending": false, "drives": null, "apps": null}, "ok": true}
|
||||
/api/storage/ -> 404 {"_raw": "404 page not found\n"}
|
||||
|
||||
|
||||
{'path': '/mnt/felhom-drives/hdd_1', 'label': 'Külső tárhely (hdd_1)', 'schedulable': True}
|
||||
keys: ['password_hash', 'filebrowser_admin_state', 'filebrowser_admin_decided_at', 'claimed', 'claim_code_hash', 'claim_code_generation', 'claim_code_issued_at', 'claim_consumed_generation', 'offbox_enlarge_notice_seeded', 'app_update_events_seeded', 'unhealthy_stop_event_seeded', 'hub_escrow_identity_present', 'hub_escrow_superseded_present', 'hub_escrow_superseded_at', 'hub_escrow_key_sha256', 'hub_escrow_key_checked_at', 'app_backup', 'offsite_data_at', 'backup_window_start', 'storage_paths', 'last_guest_boot_id', 'hub_verified', 'hub_verified_at', 'hub_last_check', 'applied_config_version', 'offbox']
|
||||
offbox: {"enabled": true, "host": "u629488-sub1.your-storagebox.de", "port": 23, "user": "u629488-sub1", "repo_path": "/home/felhom-repo", "schedule": "daily", "quota_gb": 50, "transport": "rclone-pinned", "last_run": "2026-10-15T02:15:10Z", "last_status": "ok", "last_success": "2026-10-15T02:15:10Z", "last_integrity_check": "2026-10-11T04:00:00Z", "last_integrity_ok": true, "last_integrity_depth": "100%", "proved_snapshots": {"opengist": "0ef3edb5"}, "last_proof_run": "2026-10-15T03:30:00Z", "last_proof_stack": "opengist", "last_proof_snapshot": "0ef3edb5", "last_proof_result": "pass", "last_duration": "7s", "repo_size_human": "181.6 KB", "repo_size_bytes": 185936, "snapshot_count": 15, "stats_know
|
||||
app_backup: {"opengist": {"enabled": false, "cross_drive": {"enabled": true, "method": "rsync", "destination_path": "/mnt/felhom-drives/hdd_1", "schedule": "daily", "last_run": "2026-10-15T01:30:00Z", "last_status": "ok", "last_success": "2026-10-15T01:30:00Z", "success_tracked": true, "unit_package_date": "2026-10-15T00:30:00Z", "last_duration": "0s", "last_size_human": "202.8 KB"}, "offbox": true}}
|
||||
offsite_data_at: {'opengist': {'pushed_at': '2026-10-15T02:15:05Z', 'data_at': '2026-10-15T02:15:00Z'}}
|
||||
@@ -0,0 +1,10 @@
|
||||
qbittorrent 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None), ('QBT_ADMIN_PASSWORD', 'password', True, None)]
|
||||
deployed: False
|
||||
prowlarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None)]
|
||||
deployed: False
|
||||
sonarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
radarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
plex 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('PLEX_CLAIM', 'text', True, True), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
@@ -0,0 +1,18 @@
|
||||
16:36:53 qbittorrent: deploy (fields sent: ['DOMAIN', 'QBT_ADMIN_PASSWORD', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
qbittorrent: state=running after 13s; pinned={'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.4-1'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
16:37:06 prowlarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
prowlarr: state=running after 28s; pinned={'prowlarr': 'lscr.io/linuxserver/prowlarr:version-2.6.5.5623'};
|
||||
16:37:34 sonarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
sonarr: state=running after 33s; pinned={'sonarr': 'lscr.io/linuxserver/sonarr:4.0.20'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
16:38:07 radarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
radarr: state=running after 28s; pinned={'radarr': 'lscr.io/linuxserver/radarr:6.4.4'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
cloudflared Up 41 hours (healthy)
|
||||
felhom-controller Up 2 hours (healthy)
|
||||
filebrowser Up 21 hours (healthy)
|
||||
opengist Up 12 hours (healthy)
|
||||
prowlarr Up About a minute (healthy)
|
||||
qbittorrent Up About a minute (healthy)
|
||||
radarr Up 15 seconds (healthy)
|
||||
sonarr Up 56 seconds (healthy)
|
||||
traefik Up 12 hours
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
14:38:45 qbittorrent / -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v3/system/status -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v1/system/status -> HTTP/2 404
|
||||
14:38:46 qbittorrent /initialize.json -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v2/app/version -> HTTP/2 404
|
||||
14:38:46 prowlarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2F
|
||||
14:38:47 prowlarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:47 prowlarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:47 prowlarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:47 prowlarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
14:38:48 sonarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2F
|
||||
14:38:48 sonarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:48 sonarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:48 sonarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:49 sonarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
14:38:49 radarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2F
|
||||
14:38:49 radarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:49 radarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:50 radarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:50 radarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
(the qbittorrent lines above used the wrong name; its address is torrent.demo-felhom.eu)
|
||||
14:39:24 torrent / -> HTTP/2 200 body: <!DOCTYPE html><html lang="C"><head> <meta charset="UTF-8"> <meta nam
|
||||
14:39:25 torrent /api/v2/app/version -> HTTP/2 403 body: Forbidden
|
||||
@@ -0,0 +1,27 @@
|
||||
== the controller's wiring runs:
|
||||
2026/10/15 14:36:47 [INFO] [stacks] media_library qbittorrent: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:37:28 [INFO] [stacks] media_library sonarr: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:38:01 [INFO] [stacks] media_library radarr: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:39:15 [INFO] [media] wiring the drives into the media apps (a media app came up: radarr)
|
||||
2026/10/15 14:39:18 [INFO] [mediawire] 1 drive(s) wired in 3.504s: folders=done(0) qbittorrent=done(3) sonarr=done(4) radarr=done(4) prowlarr=done(2)
|
||||
|
||||
== per-drive binds (docker's own view):
|
||||
qbittorrent: /var/lib/docker/volumes/qbittorrent_qbittorrent_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media/torrents -> /downloads; /mnt/felhom-drives/hdd_1/userdata/media/torrents -> /mnt/felhom-drives/hdd_1/userdata/media/torrents;
|
||||
sonarr: /var/lib/docker/volumes/sonarr_sonarr_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media -> /mnt/felhom-drives/hdd_1/userdata/media;
|
||||
radarr: /var/lib/docker/volumes/radarr_radarr_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media -> /mnt/felhom-drives/hdd_1/userdata/media;
|
||||
prowlarr: /var/lib/docker/volumes/prowlarr_prowlarr_config/_data -> /config;
|
||||
== sonarr: root folders ['/mnt/felhom-drives/hdd_1/userdata/media/tv']
|
||||
tags ['hdd-1']
|
||||
download clients [('qBittorrent hdd-1', 'QBittorrent', ['qbittorrent', 'tv-hdd-1'], [1])]
|
||||
== radarr: root folders ['/mnt/felhom-drives/hdd_1/userdata/media/movies']
|
||||
tags ['hdd-1']
|
||||
download clients [('qBittorrent hdd-1', 'QBittorrent', ['qbittorrent', 'movies-hdd-1'], [1])]
|
||||
== prowlarr: apps [('Radarr', 'fullSync', 'http://radarr:7878'), ('Sonarr', 'fullSync', 'http://sonarr:8989')]
|
||||
== qbittorrent categories: Forbidden
|
||||
== qbittorrent (its own API, after its login):
|
||||
{"movies-hdd-1":{"download_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp","inactive_seeding_time_limit":-2,"name":"movies-hdd-1","ratio_limit":-2,"savePath":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/movies","seeding_time_limit":-2,"share_limit_action":"Default"},"tv-hdd-1":{"download_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp","inactive_seeding_time_limit":-2,"name":"tv-hdd-1","ratio_limit":-2,"savePath":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/tv","seeding_time_limit":-2,"share_limit_action":"Default"}}
|
||||
"auto_tmm_enabled":true
|
||||
"save_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents"
|
||||
"save_path_changed_tmm_enabled":false
|
||||
"temp_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp"
|
||||
"temp_path_enabled":true
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"opengist": {
|
||||
"enabled": false,
|
||||
"cross_drive": {
|
||||
"enabled": true,
|
||||
"method": "rsync",
|
||||
"destination_path": "/mnt/felhom-drives/hdd_1",
|
||||
"schedule": "daily",
|
||||
"last_run": "2026-10-15T01:30:00Z",
|
||||
"last_status": "ok",
|
||||
"last_success": "2026-10-15T01:30:00Z",
|
||||
"success_tracked": true,
|
||||
"unit_package_date": "2026-10-15T00:30:00Z",
|
||||
"last_duration": "0s",
|
||||
"last_size_human": "202.8 KB"
|
||||
},
|
||||
"offbox": true
|
||||
},
|
||||
"prowlarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"qbittorrent": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"radarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"sonarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
== qbittorrent: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media/torrents class=optional origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes [/mnt/felhom-drives/hdd_1/felhom-data/userdata/media/torrents (optional)]
|
||||
== sonarr: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media class=excluded origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
== radarr: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media class=excluded origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
== prowlarr: 0 classifiable bind(s), classified=true
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
--- PASS: TestN100CaptureSetTmp (0.00s)
|
||||
2026-10-15 04:59:17 INFO: including mount point mp0 ('/var/lib/felhom') in backup
|
||||
2026-10-15 04:59:17 INFO: excluding bind mount point mp8 ('/mnt/felhom-drives') from backup (not a volume)
|
||||
2026-10-15 04:59:17 INFO: excluding bind mount point mp9 ('/etc/felhom-bootstrap') from backup (not a volume)
|
||||
mp0: local-lvm:vm-9201-disk-3,mp=/var/lib/felhom,backup=1,size=250G
|
||||
mp8: /mnt/felhom-drives,mp=/mnt/felhom-drives
|
||||
mp9: /var/lib/felhom-agent/guests/9201/bootstrap,mp=/etc/felhom-bootstrap,ro=1
|
||||
Tier 2 with ONE data drive (backup/tier2.go selectTier2TargetFrom): no other drive -> the internal SSD, STATE-ONLY set (never the optional media/torrents), and only if the SSD has headroom; so no film or download reaches tier 2 on the N100 today.
|
||||
@@ -0,0 +1,9 @@
|
||||
{'path': '/mnt/felhom-drives/hdd_1', 'label': 'NVME 1TB', 'is_default': True, 'schedulable': True}
|
||||
{'path': '/mnt/sizing-bench', 'label': 'Tárhely (sizing-bench)', 'schedulable': True}
|
||||
total 16
|
||||
drwxr-xr-x 4 root root 4096 Oct 15 01:30 .
|
||||
drwxr-xr-x 5 root root 4096 Oct 14 20:43 ..
|
||||
drwxr-xr-x 3 root root 4096 Oct 15 01:30 backups
|
||||
drwxrwsr-x 6 root 1000 4096 Oct 14 20:43 userdata
|
||||
2026/10/15 14:41:46 info.go:13: [DEBUG] [system] GetDiskUsage: path="/mnt/sizing-bench" total=31.2 GB used=1.3 GB avail=28.3GB (4.3%)
|
||||
2026/10/15 14:42:21 info.go:13: [DEBUG] [system] GetDiskUsage: path="/mnt/sizing-bench" total=31.2 GB used=1.3 GB avail=28.3GB (4.3%)
|
||||
@@ -0,0 +1,9 @@
|
||||
16:44:24 POST /settings/storage/remove storage_path=/mnt/sizing-bench -> HTTP/2 302 | location: /storage?storage_msg=success&storage_detail=Adatt%C3%A1rol%C3%B3+elt%C3%A1vol%C3%ADtva%3A+%2Fmnt%2Fsizing-bench
|
||||
2
|
||||
2026/10/15 14:44:24 settings.go:1632: [INFO] [settings] Removed storage path: /mnt/sizing-bench
|
||||
2026/10/15 14:44:24 handlers.go:3527: [INFO] [web] Storage path removed: /mnt/sizing-bench
|
||||
2026/10/15 14:44:25 handlers.go:3805: [INFO] [web] FileBrowser mounts synced (recreated) — 1 storage path(s), config updated
|
||||
|
||||
/app_backup/calibre-web/cross_drive/destination_path = /mnt/sizing-bench
|
||||
/app_backup/paperless-ngx/cross_drive/destination_path = /mnt/sizing-bench
|
||||
storage paths now: ['/mnt/felhom-drives/hdd_1']
|
||||
@@ -0,0 +1,3 @@
|
||||
14:56:26 atus-dot-nominal"> Demo HP OK 1 1 just now 28% 26% 27%/22% 17/17 –
|
||||
|
||||
[exited with code 0]
|
||||
@@ -0,0 +1,19 @@
|
||||
# The N100 becomes the lived-in box (2026-10-15)
|
||||
|
||||
Rule: `architecture/09-update-architecture.md` §3 decision 254. Diary: `documentation/lived-in/n100.md`.
|
||||
Read first: `runbooks/target-selection.md`, `operations/nodes.md`, `07-backup-architecture.md`, `15-media-library.md`.
|
||||
|
||||
| folder | what |
|
||||
|---|---|
|
||||
| `B/01-state.txt` | the host and guest: versions, memory, disks, `/dev/dri` (host yes, guest no) |
|
||||
| `B/02-drive.txt`, `B/03-drive-detail.txt` | the USB drive (ADATA HD710 PRO / TOSHIBA MQ04ABF100 `65NOP3HDT`) and its 6.2 GB: vzdumps, app backups, leftovers — no family files; PVE storage `felhom-backup` = the whole-guest backup target |
|
||||
| `B/04-sizing.txt` | the five media apps by the estimator's rule: ~2 GB needed of 12 GB |
|
||||
| `B/05-dashboard-view.txt` | the dashboard's own view: one enrolled drive, `backup_target: true`, off-site on (182 KB) |
|
||||
| `B/06-deploy-fields.txt` | the install fields per app |
|
||||
| `D/01-install.txt` | qBittorrent, Prowlarr, Sonarr, Radarr through the deploy call — no drive sent; the box chose `hdd_1` |
|
||||
| `D/02-stranger.txt` | a stranger from the internet: the gate on Prowlarr/Sonarr/Radarr; qBittorrent's own login page and 403 API |
|
||||
| `D/03-wiring.txt` | what the box wired, from the apps' own APIs |
|
||||
| `D/04-app-backup-settings.txt`, `D/05-capture-sets.txt` | **Part C:** the controller's classifier over the deployed files — off-site takes no media; tier 2 only qBittorrent's downloads and only if switched on (not on; with one drive state-only to the SSD); vzdump excludes the drives |
|
||||
| `F/` | demo-hp: `/mnt/sizing-bench` removed through the dashboard; the hub's next report |
|
||||
| `SHEET.md` | the operator's sheet |
|
||||
| `tools/` | `n100.py` (the box-walk library pointed at the N100), `install_media.py`, `read_wiring.py` |
|
||||
@@ -0,0 +1,50 @@
|
||||
# Your sheet — the N100 becomes the lived-in box (about 30 minutes)
|
||||
|
||||
Do these when it suits you. Use one browser. Sign in to the dashboard first: then the apps let you through.
|
||||
|
||||
## 1. The addresses
|
||||
|
||||
- Dashboard: **https://felhom.demo-felhom.eu**
|
||||
- qBittorrent: **https://torrent.demo-felhom.eu**
|
||||
- Prowlarr: **https://prowlarr.demo-felhom.eu**
|
||||
- Sonarr: **https://sonarr.demo-felhom.eu**
|
||||
- Radarr: **https://radarr.demo-felhom.eu**
|
||||
- Plex (after you install it): **https://plex.demo-felhom.eu**
|
||||
|
||||
## 2. Plex
|
||||
|
||||
1. Dashboard → Alkalmazások → Plex → install. It asks no code.
|
||||
2. Wait until Plex runs. Open Plex's page in the dashboard.
|
||||
3. Open **plex.tv/claim**. Copy the code. Paste it on Plex's page within 4 minutes.
|
||||
4. The box opens Plex by itself when Plex is claimed. If it asks, press „Kész, beállítottam".
|
||||
5. Wait 2 minutes. Open Plex. **If Plex shows no library,** press „Bekötés most" on the dashboard (the card about the
|
||||
drives and the apps), and tell me that you had to. (I expect this; it is R-1065.)
|
||||
|
||||
## 3. Prowlarr, Sonarr, Radarr
|
||||
|
||||
1. Open each address. The app asks you to make its admin login. Make one for each.
|
||||
2. On each app's page in the dashboard, press „Kész, beállítottam". Until you do, only you can reach the app.
|
||||
3. Add your download sources **in Prowlarr only.** They reach Sonarr and Radarr by themselves (the box linked them).
|
||||
|
||||
## 4. One show, one film
|
||||
|
||||
1. Sonarr: add one show. Radarr: add one film.
|
||||
2. When they finish, open Plex. Check that both are there.
|
||||
|
||||
## 5. Passwords
|
||||
|
||||
- qBittorrent: user `admin`. The password is on qBittorrent's page in the dashboard (the password row, show button).
|
||||
The same value is in a private file on DooPlex: `~/.felhom-demofelhom/qbittorrent-admin`.
|
||||
- Prowlarr, Sonarr, Radarr, Plex: the logins you make. None is written here.
|
||||
|
||||
## 6. qBittorrent — the legal line
|
||||
|
||||
„Csak olyan tartalmat tölts le, amihez jogod van. A letöltés a háztartásod internetcíméről történik, és a torrent
|
||||
természetéből adódóan a többi résztvevő látja a címedet."
|
||||
|
||||
## 7. Anything odd
|
||||
|
||||
Tell any CC session. It goes into the diary (`documentation/lived-in/n100.md`) and the register.
|
||||
|
||||
When you are done, say „done". I then read back: Plex claimed, its libraries, the show and the film imported as
|
||||
hardlinks, and visible in Plex.
|
||||
@@ -0,0 +1,26 @@
|
||||
"""install_media.py — Part D1: qBittorrent, Prowlarr, Sonarr, Radarr through the dashboard's deploy call, with the fields
|
||||
the wizard sends (no HDD_PATH for a media app — the box picks its drive). Admins and indexers are the operator's."""
|
||||
import json, os, time, n100
|
||||
w = n100.w
|
||||
w.login()
|
||||
for app in ("qbittorrent", "prowlarr", "sonarr", "radarr"):
|
||||
if w.stack(app).get("deployed"):
|
||||
print(f"{app}: already installed — skipped"); continue
|
||||
c, d = w.ctl("GET", f"/api/stacks/{app}/deploy-fields")
|
||||
fields = (((d.get("data") or {}).get("metadata") or {}).get("deploy_fields")) or []
|
||||
sub = next((f.get("default") for f in fields if f.get("env_var") == "SUBDOMAIN"), None) or app
|
||||
values = {"DOMAIN": w.DOMAIN, "SUBDOMAIN": sub}
|
||||
if any(f.get("env_var") == "QBT_ADMIN_PASSWORD" for f in fields):
|
||||
values["QBT_ADMIN_PASSWORD"] = open(os.path.expanduser("~/.felhom-demofelhom/qbittorrent-admin")).read().strip()
|
||||
t0 = time.time()
|
||||
code, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": values})
|
||||
print(f"{time.strftime('%H:%M:%S')} {app}: deploy (fields sent: {sorted(values)}) -> {code} {json.dumps(d, ensure_ascii=False)[:120]}")
|
||||
for _ in range(120):
|
||||
time.sleep(5)
|
||||
st = w.stack(app)
|
||||
if st.get("deployed") and (st.get("app_config") or {}).get("pinned_images") and st.get("state") in ("running", "unhealthy"):
|
||||
break
|
||||
st = w.stack(app)
|
||||
hdd = w.guest(f"grep -E '^\\s*HDD_PATH:' /opt/docker/stacks/{app}/app.yaml | head -1").strip()
|
||||
print(f" {app}: state={st.get('state')} after {time.time()-t0:.0f}s; pinned={(st.get('app_config') or {}).get('pinned_images')}; {hdd}")
|
||||
print(w.guest("docker ps --format '{{.Names}} {{.Status}}' | sort"))
|
||||
@@ -0,0 +1,12 @@
|
||||
"""n100.py — the box-walk library pointed at the N100 (demo-felhom guest 9201). Import this, not box_walk, for the N100.
|
||||
box_walk.py has no demo-felhom row; this overrides the target AFTER import (no catalog change). Every call is the
|
||||
dashboard's own endpoint, as box_walk documents."""
|
||||
import os, sys
|
||||
os.environ.setdefault("TARGET", "9201")
|
||||
os.environ.setdefault("SC", os.path.expanduser("~/.felhom-demofelhom"))
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w # noqa: E402
|
||||
w._T = {"hp": "demo-felhom", "ssh": "felhom-pve", "jump": None, "guest": "9201",
|
||||
"base": "https://192.168.0.149", "domain": "demo-felhom.eu"}
|
||||
w.GUEST, w.BASE, w.DOMAIN, w.HP = "9201", "https://192.168.0.149", "demo-felhom.eu", "demo-felhom"
|
||||
w.HOSTHDR = "Host: felhom.demo-felhom.eu"
|
||||
@@ -0,0 +1,23 @@
|
||||
"""read_wiring.py — Part D2: what the box wired by itself, read from each app's OWN API inside its container (keys read
|
||||
from the app's config at use, never printed) and from the controller's log. Read only."""
|
||||
import json, shlex, n100
|
||||
w = n100.w
|
||||
def arr(app, port, path, ver="v3"):
|
||||
script = ("K=$(sed -n 's:.*<ApiKey>\\(.*\\)</ApiKey>.*:\\1:p' /config/config.xml); "
|
||||
f"curl -s -H \"X-Api-Key: $K\" http://127.0.0.1:{port}/api/{ver}{path}")
|
||||
out = w.guest(f"docker exec {app} sh -c {shlex.quote(script)}")
|
||||
try: return json.loads(out)
|
||||
except Exception: return out[:200]
|
||||
print("== the controller's wiring runs:")
|
||||
print(w.guest("docker logs --since 10m felhom-controller 2>&1 | grep -E '\\[media\\] wiring|\\[mediawire\\]|media_library .*binds' | cut -c1-330"))
|
||||
print("== per-drive binds (docker's own view):")
|
||||
for a in ("qbittorrent", "sonarr", "radarr", "prowlarr"):
|
||||
print(f" {a}:", w.guest(f"docker inspect {a} -f '{{{{range .Mounts}}}}{{{{.Source}}}} -> {{{{.Destination}}}}; {{{{end}}}}'").strip())
|
||||
for a, port in (("sonarr", 8989), ("radarr", 7878)):
|
||||
rf = arr(a, port, "/rootfolder"); tags = arr(a, port, "/tag"); dc = arr(a, port, "/downloadclient")
|
||||
print(f"== {a}: root folders {[r.get('path') for r in rf] if isinstance(rf, list) else rf}")
|
||||
print(f" tags {[t.get('label') for t in tags] if isinstance(tags, list) else tags}")
|
||||
print(f" download clients {[(c.get('name'), c.get('implementation'), [f.get('value') for f in c.get('fields', []) if f.get('name') in ('host', 'tvCategory', 'movieCategory')], c.get('tags')) for c in dc] if isinstance(dc, list) else dc}")
|
||||
apps = arr("prowlarr", 9696, "/applications", "v1")
|
||||
print(f"== prowlarr: apps {[(a.get('name'), a.get('syncLevel'), next((f.get('value') for f in a.get('fields', []) if f.get('name') == 'baseUrl'), None)) for a in apps] if isinstance(apps, list) else apps}")
|
||||
print("== qbittorrent categories:", w.guest("docker exec qbittorrent sh -c 'curl -s http://127.0.0.1:8080/api/v2/torrents/categories'").strip()[:600])
|
||||
@@ -124,7 +124,7 @@ stopping line that lies.
|
||||
| **R-494** | Install & onboarding | P4 | **NARROWED 2026-09-14 by operator ruling → [P3-LOW] the hub COULD create the tunnel at customer creation, for a domain already on Cloudflare. Not blocking: every customer has their own domain and the operator creates the tunnel per day-0 A.1 (`architecture/01-topology-and-trust.md`).** *Original finding, kept:* **[P1-HIGH] A new customer's dashboard has NO reachable address unless the operator hand-makes a Cloudflare tunnel — the link in the setup-code mail is dead.** MEASURED 2026-09-14 on a fresh install from the public ISO (drill intervention **I1**): the claim mail points at `https://felhom.drill0242.felhom.eu`; that name has **no A and no AAAA** record (`dig @1.1.1.1`, control `felhom.enkisfelhom.hu` resolves); the hub has **no tunnel- or DNS-creation code** (`hub/internal/cloudflare/` holds only geo-rule removal; `cf_tunnel_token` is a pasted, optional form field, `configs.go:1478`) — day-0 runbook A.1 makes it a manual Cloudflare-dashboard step that nothing on the customer-create page asks for; the box's own split-horizon resolver on the appliance LAN IP answered `google.com` but not the dashboard name at 13:27:39Z; the agent applied the record at **13:27:44Z** (`lanresolver: applied split-horizon record … ip=192.168.0.158`, 3 m 46 s after the controller started), so the box CAN answer the name — **but only to a device that uses the box as its DNS server, and no document, screen or mail tells a household to do that**; the router and the installer-offered DNS answer nothing. The page was reachable only at the guest's LAN address with the name forced (`curl --resolve …:443:192.168.0.158`). **A volunteer could not have done that.** **What it needs:** an operator ruling — the hub creates the tunnel and DNS at customer creation, or the product gives a household a LAN address that works with no DNS change. | **READY — rank P3-LOW; owner: CC** **Re-ranked 2026-10-03: P3→P4: operator-side automation; the operator creates the tunnel by hand per the day-0 runbook.** | — | — | CC |
|
||||
| **R-504** | Install & onboarding | P4 | **[P3-LOW] `iso.felhom.eu` cannot show an index page on its own — its root returns 404, and the download page lives on the website instead.** MEASURED 2026-09-14: `https://iso.felhom.eu/` and `/index.html` → 404; only named objects answer. The host is an R2 bucket behind a custom domain; whether R2 would serve an uploaded `index.html` at `/` was **not measured** (uploading anything to the public bucket is a publication). The ISO v1.27.0 task puts the Hungarian download page at `felhom.eu/letoltes` (published with the ISO, after the operator's yes). **Remaining:** a redirect from `iso.felhom.eu/` to that page needs a Cloudflare rule the session has no credential for. | **WAITING-ON-OPERATOR — rank P3-LOW; owner: operator (Cloudflare rule)** **Re-ranked 2026-10-03: P3→P4: households are sent to the website's download page; the bare address is cosmetic.** | — | — | operator |
|
||||
|
||||
## Apps & catalog — 13 rows (P2 1, P3 7, P4 5)
|
||||
## Apps & catalog — 14 rows (P2 1, P3 8, P4 5)
|
||||
|
||||
| ID | Category | Sev | What | State | Blocked on | Next action | Owner |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
@@ -136,6 +136,7 @@ stopping line that lies.
|
||||
| **R-1028** | Apps & catalog | P3 | **Plex's claim code can run out during the install, and the box cannot recover it.** plex.tv's code lives 4 minutes from the moment the household copies it; the clock covers the wizard, the image pull (`plexinc/pms-docker` is 351 MB, measured) and the first start. Plex reads `PLEX_CLAIM` only on its first run, and the field is `locked_after_deploy` — so a late code leaves an unclaimed server and the only way back is remove + install again. Reported by the operator during the 2026-10-14 test; on Tester 1's line the pull+start took 8.5 s and the claim worked (`audits/media-all-drives-2026-10-14/``G-auth/G3-plex-claim.txt`), so it bites on a slow line or a slow hand. **K6, 2026-10-14 night (`audits/media-drive-events-2026-10-14/``K6-1-unclaimed-plex.txt`):** an unclaimed Plex starts with no code at all, and `POST /myplex/claim?token=` on the RUNNING server reaches plex.tv (a wrong code → 500 after plex.tv's 401). So the box can pull + start first and ask for the code after: no race. A real claim needs the household's code — the morning step on the throwaway `plex-k6` on Tester 1. Narrowed 2026-10-14 night. **PROVEN 2026-10-15 morning (`K6-2-claim-after-start.txt`):** the operator's real code, given to the RUNNING unclaimed `plex-k6` → 200, `claimed` 0→1, `PlexOnlineToken` written, and the open door closed (no token → 401). `ADVERTISE_IP` was unset and the claim did not need it; whether clients find the server without it was not measurable (the throwaway had no published port). **BUILT 2026-10-15 (v0.313.0):** `after_start` field — not asked at install; the Plex page asks for the code once Plex runs and claims the running server; the gate opens only when Plex says claimed. Proven up to the code on 9201 (G5). | **NARROWED** — the dashboard claim with a real code is the last step | a household Plex code | Claim through the Plex page with a real code (G5c); then close | CC |
|
||||
| **R-1029** | Apps & catalog | P3 | **Plex's folder picker shows the drives as identical „media” folders.** With one bind per drive at the same path (`/mnt/felhom-drives/<drive>/userdata/media`), the leaf of every library folder is `media`; the drive's name sits two levels up, so in Plex's picker the household sees several folders all called „media” (reported by the operator during the 2026-10-14 test on Tester 1). It conflicts with `15` §2 reason 2 (the same path everywhere). | **READY** — filed 2026-10-14 | the layout decision (STATUS D9) | Decide in `15` §2: the players (`:ro`, never linked) may get a readable path per drive (e.g. `/media/<drive label>`) without breaking the hardlink rule, which binds only the download/library apps | CC |
|
||||
| **R-1036** | Apps & catalog | P3 | **The apps page lags the catalog by two apps.** `app-catalog-felhom.eu/templates/` holds **64** apps; `/alkalmazasok` and `/en/apps` render **63** cards, one of which (`filebrowser`) is built in and not a catalog template — so **62 catalog apps are listed**. Missing: **`plant-it`** and **`wger`**, both in the catalog since 2026-10-06/08. Their website assets are ALREADY present (`plant-it-logo.svg` + 3 screenshots, `wger-logo.png` + 3 screenshots, renamed to the catalog slug by `a3507761`, 2026-10-08) — only the cards were never written, so this is not a new-asset job. Found 2026-10-14 while reconciling the app count for the „felhő tárhely” page, where four places said **60** and the rest said **62**. **Done in that session:** every stated count on the site set to **62** (`index.html`, `szolgaltatasok.html`, `en/services.html` were 60), which is what the apps page actually shows — so no visitor can count the cards and find the number wrong. **62 is still not the catalog's number.** **To close:** write the two cards on both apps pages (gate 15 keeps the two pages' app sets equal, so they move together), then raise every stated count 62 → 64 in the same commit. **The operator chose this split at the 2026-10-14 STOP** over doing it inside the SEO change. **2026-10-15 (R-1048):** Prowlarr's card added on both pages and every stated count 62 → 63 (the media group 19 → 20), so the site still states what it shows; the two owed cards would make it 65. **Note before writing them:** `wger` is `lifecycle: hidden` and `plant-it` `lifecycle: abandoned` — neither is offered for a new install, so a card would advertise an app the wizard refuses. | **OPEN** | — | write the `plant-it` + `wger` cards on both apps pages, then 62 → 64 everywhere, one commit | CC |
|
||||
| **R-1065** | Apps & catalog | P3 | **After the Plex claim the box does not set Plex's libraries until the next wiring run.** The claim handler (`felhom-controller` `internal/web/media_events.go` `appPlexClaimHandler`) opens the gate when Plex says claimed and returns; the wiring runs only when a `media_library` app comes up, on a drive event, or on „Bekötés most". Plex's own install ran it while Plex was unclaimed (`plex=household(0)`), so a freshly claimed Plex has no libraries until one of those happens — the shape of R-1058. Read from code 2026-10-15; to be measured on the N100 when the operator claims Plex (the sheet asks for „Bekötés most" only if no library appears). | **OPEN** — filed 2026-10-15 | — | Run the wiring (RunMediaWiringSoon) after a successful claim; a test; measure on the N100's claim | CC |
|
||||
| **R-76** | Apps & catalog | P4 | **FileBrowser-created folders break the setgid chain, and a drop-zone's mode is not stable** **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-26, size S, roadmap state `idea (surfaced by the R-75 spike, 2026-07-26)`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **2026-10-06 night: not a catalog fix** — the setgid chain is set by the controller's FileBrowser setup; a controller row. | — | Two related findings from `audits/SPIKE-catalog-data-paths-2026-07-26.md` P3/P5, both **pre-existing** and deliberately left alone by that spike. **(a)** FileBrowser Quantum 1.3.3 creates files `0644` and folders `0755` and does **not** propagate the setgid bit — even though the entrypoint wrapper's `umask 002` really is in effect (`/proc/1/status` `Umask: 0002`). Group inheritance itself works (a file uploaded into a 2775 group-100 dir landed group 100, not the process gid 1000), so the convention's *group* half holds and only its *mode* half is lost. The consequence is proven with a control: inside a UI-created `0755` folder a gid-1000 process's file landed group **1000**, while the identical write into the 2775 parent landed group **100**. So **any folder a customer creates through FileBrowser breaks the shared-group chain one level down.** Latent today — every userdata-touching catalog app that declares an identity declares uid/gid **1000**, the same uid FileBrowser runs as, so owner permissions mask it; it bites the day a content app runs as a different non-root uid with gid 1000. The comment at `infra/infra.go:156` is right that the image ignores `-e UMASK` but does not say t | CC |
|
||||
| **R-707** | Apps & catalog | P4 | **[P2] 37 apps still start with a login a stranger can take (`09` §3 decision 45).** Audit of all 53 apps: `app-catalog-felhom.eu/FIRST-ADMIN.md` (class, fix route, status, measured or read). Open: **3 hard-coded defaults** — calibre-web (`admin / admin123`, measured working on demo-hp and 9202; its own `cps.py -s` route needs a generated password WITH a special character — our generator is letters+digits, a controller change), mealie (`changeme@example.com / MyPassword`), wger (`admin / adminadmin`); **34 open first-run screens** (the first visitor creates the admin: actualbudget, adventurelog, audiobookshelf, calcom, docmost, emby, ghost, gitea, gramps-web, home-assistant, homebox, immich, jellyfin, komga, n8n, navidrome, opengist, outline, papra, plant-it, radarr, rallly, recipe-importer, romm, seerr, sonarr, sparkyfitness, tandoor, termix, uptime-kuma, vikunja, wanderer, wishlist, zipline). **Stale notes:** romm's `default_creds` `admin / admin` answers 401 on demo-hp (like a wrong password) — the page now warns with a login that does not exist; zipline's looks stale too. **Measured on demo-hp 2026-09-28 (read-only):** bookstack's default still logs in on the INSTALLED app (the fix is for new installs; the page now warns). Each fix: route (a) env or (b) the app's own CLI/API via `after_install:`, proven on 9202 with the default failing and the generated password working; route (c) a page sentence. Several sessions (operator, 2026-09-28). **2026-09-29 (controller v0.280.0, catalog `d0e7e2e`):** every class-3 app fixed — mealie, wger, calibre-web by `after_install` (calibre-web with the new `password:24:special`), proven on 9202 fresh installs (`audits/login-gate-2026-09-29/D/`); the setup gate (decision 46, spike PASSED) built and live on immich, n8n, audiobookshelf (probes measured) and uptime-kuma (button) (`…/C/`); romm's and zipline's stale notes removed. **Left: 30 class-4 apps** — gate each (probe measured on 9202 where one exists — 11 upstream candidates listed in `…/B/B-VERDICT.md` §3; the button otherwise). **2026-09-29 afternoon (controller v0.281.0, catalog `6faf432`):** 28 more class-4 apps gated — 32 of 34 — each proven on 9202 (`audits/gate-rollout-2026-09-29/`B): stranger → gate page / 401, household reached the first-setup screen, the gate opened (9 by a measured probe, the rest by the press), the app answered after. seerr, outline, rallly: gated, their opening needs a media server / e-mail (not proven). **Left:** wanderer (R-714); plant-it is not installable. | **NARROWED** (2026-10-03 triage: the row's verdict was finished, but it names open work no other row carries — seerr, outline and rallly are gated, but the gate OPENING is not proven (needs a media server / e-mail)) — **CLOSED — 2026-09-29 (the rest → R-714)** | — | — | CC |
|
||||
| **R-905** | Apps & catalog | P4 | **wger's collected style files (283 MB) go into every wger backup, though the app rebuilds them at every start.** Since R-762's fix (`DJANGO_DEBUG=False` + `collectstatic`, catalog `cf1ed43`) the static files sit in a named volume that the backup legs copy like data (measured 283 MB, `audits/design-build-2026-10-06/`); `collectstatic` regenerates them, so they are rebuildable bytes in every Tier-1 unit, Tier-2 copy and off-site snapshot. wger is `lifecycle: hidden` and no box runs it (hub read 2026-10-08). Options to weigh: a non-backed-up volume class for regenerable data, or an anonymous volume. Found by the R-762 helpers 2026-10-08. | **OPEN — needs a design before wger is shown** | — | Design the „regenerable volume" exclusion (catalog + controller backup legs) | CC |
|
||||
@@ -187,10 +188,13 @@ stopping line that lies.
|
||||
| **R-878** | Backup & restore | P4 | **A catch-up (R-871) runs the database-dump leg in the DAY, and that leg stops an app with a volume for its copy — the household may notice the stop, and a large volume makes it longer.** MEASURED 2026-10-05 on demo-felhom: the catch-up at 08:25:02 stopped opengist, copied 182.5 KB, started it again — about 1 s, then a few seconds of `health: starting`; the night does exactly the same, unseen. Nothing measured for a large volume. Fix direction (if it matters): skip the volume copy of a running app in a DAYTIME catch-up and leave it to the next night, or warn. `audits/catchup-2026-10-05/partA/live-demo-felhom.txt` | **READY — owner: CC** **2026-10-05 (burn-down night): NEEDS A LIVE MEASUREMENT** — a timed catch-up on 9202 for an app with a multi-GB volume, then the skip-or-warn choice. | — | measure a large volume first | CC |
|
||||
| **R-32** | Backup & restore | P4 | **[P2-HIGH] RESET must purge the customer base dir; the orphan card must stay honest; unattributed bytes must be visible.** The rehearsal's S7 said in advance that an orphan card would BE a finding — and one appeared (16:58:14). Cause: RESET's `"hetzner":"ok"` leg destroys the sub-account, but **a Hetzner sub-account is an access-control object, not a data object** — its directory survives, so re-enabling offsite recreated an account over the previous lifecycle's ciphertext, encrypted under a key that same RESET had destroyed. **MIGRATED FROM `ROADMAP.md` 2026-08-22 (R-369) — originally filed 2026-07-21, size M, roadmap state `idea`.** Moved verbatim; nothing added or reinterpreted. The roadmap keeps its copy as history, marked moved. | **OPEN — migrated from ROADMAP 2026-08-22, rank unchanged** **2026-10-06 night: design written** (`audits/night-burndown-2026-10-06/design-R-32.md`) — pick A: purge the repo + set-aside copies through the sub-account's own password login BEFORE deleting it (no main-account credential); the „repo data destroyed" comment at `hub/internal/offsite/offsite.go:276-280` is false for the shared tier; part (3) waits on a read-only measurement (`du` on port 23). Operator: agree to route A. **2026-10-07 07:58: `09` §3 decision 167 — option A yes, and delete the old RESET leftovers once.** **2026-10-07 (Part D step 2, read only):** the hub shows bx11 holding 3.3 GB of data while the four live customers account for ~0.6 GB → **~2.7 GB belongs to no live customer**; no live customer shows a set-aside folder, so the leftovers are in homes whose sub-account is gone, reachable only by the pool box's MAIN account. **The one-time clean-up is STOPPED:** no main-account login for bx11 is held on DooPlex (the API token in the credentials file sees no box). Needs: the main-account login, or the operator lists and deletes in the Hetzner console (`audits/day-2026-10-07/D/D2-listing-readonly.txt`). **2026-10-07: option A DELIVERED (hub 0.142.0):** RESET purges the repo and every `.orphaned-*` through the sub-account's own login before deleting it, and keeps the sub-account if the purge fails (red-proved, `audits/day-2026-10-07/D/`). Not yet seen live (no scratch RESET today). **The one-time clean-up of the ~2.7 GB of leftovers is STOPPED:** it needs the pool box's main-account login (see above). **2026-10-07 14:43 — `09` §3 decision 173: leave the ~2.7 GB of old leftovers for now; re-ranked P2 → P4.** Option A itself is delivered (hub 0.142.0). What stays open is ONLY the leftovers: they were computed (box total minus live customers), never listed, and deleting them needs the pool box's MAIN login, which reaches every customer's data. **Blocker: a safe main-account path.** | — | **Ruling from the run (three parts, deliberately separate):** (1) because RESET destroys custody, the ciphertext it leaves behind is unrecoverable **BY DESIGN** → RESET gains a **main-account purge of the customer base dir** (the existing operator ack already covers it); (2) the **move-aside guard STAYS** for reinstall-*without*-RESET — there custody survives and the card's "history recoverable" promise is true (R-26 depends on exactly that); (3) the operator **Restic tab shows per-customer directory bytes vs attributed snapshot bytes**, so dead data cannot hide. Measured on the pool box that night: **49 M attributed** (2 snapshots, 48.717 MiB) against **1.4 G + 3.0 M unattributed** across TWO `.orphaned-*` dirs. Evidence `restic-and-pool.txt` | CC |
|
||||
|
||||
## Storage & devices — 3 rows (P3 2, P4 1)
|
||||
## Storage & devices — 6 rows (P3 3, P4 3)
|
||||
|
||||
| ID | Category | Sev | What | State | Blocked on | Next action | Owner |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| **R-1062** | Storage & devices | P4 | **The N100's USB drive cannot be split in two without losing the box's whole-guest backup target.** The operator asked (2026-10-15 16:31) for two halves for multi-drive tests. Read first (`audits/n100-lived-in-2026-10-15/B/`): no family files — 2.7 GB nightly vzdumps of guest 9201 (`dump/`, PVE storage `felhom-backup` = the whole-guest backup target), 3.1 GB app backups + an off-site restore copy, 422 MB leftover app data of removed apps, empty media folders. The agent refuses a decommission of a backup target (`refuseIfBackupTarget`) and the N100 has no other drive to move that role to. Nothing changed. | **WAITING-ON-OPERATOR** — filed 2026-10-15 | operator decision | Keep one drive (CC's pick: the lived-in box keeps its local whole-guest backup), or give a word to drop that backup leg / add a second drive first | operator |
|
||||
| **R-1063** | Storage & devices | P3 | **„Végleges leszerelés" leaves a half-state when the agent refuses: the dashboard marks the drive decommissioned first and never undoes it.** `handleStorageDecommission` → `finalizeDecommissionWith` calls `settings.SetDecommissioned` (and may move the default) BEFORE `agent.Decommission`; on the agent's 403 (protected role) or 409 (whole-guest backup target) it returns the error and keeps the mark — the dashboard would show a retired drive the agent kept serving. Read from code 2026-10-15 (`felhom-controller` `internal/web/storage_handlers.go`); NOT pressed on the lived-in N100 on purpose. | **OPEN** — filed 2026-10-15 | — | Measure on demo-hp (a backup-target drive), then: ask the agent first (or undo the mark and the default on a refusal); a test with a refusing agent seam, red first | CC |
|
||||
| **R-1064** | Storage & devices | P4 | **Removing a storage path does not mention the cross-drive backup copies it holds.** demo-hp 2026-10-15: `/mnt/sizing-bench` removed through `/settings/storage/remove` (302, „Adattároló eltávolítva") while calibre-web's and paperless-ngx's `cross_drive.destination_path` pointed at it; the copies stay on disk, the records still name the removed path. The in-use check counts HDD_PATH only (`appsUsingPath`). | **OPEN** — filed 2026-10-15 | — | Read what tonight's tier-2 run (01:30) does with the two records; then: name the copies in the removal's confirmation (or count them as in use) | CC |
|
||||
| **R-330** | Storage & devices | P3 | **Disk health Phase 2 — the three SMART attributes the wire does not carry.** The failing drive's most telling counter was **187 `Reported_Uncorrect`**, sitting at normalized **1** against threshold **0** with a raw count of **1001** — one point from failing and structurally unable to get there. Also wanted: **199 `UDMA_CRC_Error_Count`** (cabling) and **188 `Command_Timeout`**. None are on the agent→controller wire today, so v0.215.0's ladder could not use them. Phase 2 also persists periodic SMART **samples** (the right home is `metrics.MetricsStore`, NOT the Phase-1 state file, which is one record per disk and must stay that way). **This is a declared WIRE change, so under the G-1 gate the hub must model the new fields in the SAME session** — that is precisely why it was kept out of Phase 1, where it would have turned a one-word severity fix into a three-repo change | **READY** — **2026-10-12: the wire half is CLOSED in this row** — released in agent v0.150.0 (boxes run 0.154.0), controller and hub decode 187/188/199. **Only open work:** the verdict slice (use the three counters in the disk verdict and the household's words) and persisting samples. **READY (M) — NEW 2026-08-14** **2026-10-06 night: the wire half BUILT on main (unreleased):** the agent sends SMART 187 `reported_uncorrect`, 188 `command_timeout` (raw, vendor-packed on some drives — carried as reported), 199 `udma_crc_errors` (pointer + omitempty: unknown is absent, never 0); the controller decodes them and the hub's host-report mirror models them (G-1 wire gate green; it convicted the agent half alone). **Carried only** — no verdict, banner, mail or alarm reads them (`TestR330_CountersChangeNoVerdictYet`); using them changes what a household is told and is the next slice, with persisting samples. Red-proofs `audits/night-burndown-2026-10-06/r330/`. Ships with agent v0.150.0 and the next controller and hub releases. | R-328 (closed) | The verdict slice: 187/188/199 into the disk verdict with tests; then persist samples | CC |
|
||||
| **R-332** | Storage & devices | P3 | **The new Hiba-from-counters path has never fired on real hardware.** v0.215.0's whole point is a verdict the product could not previously reach, and it is proven only against the committed fixture's values in unit tests (12 scenario groups, 11 of 12 red-proofs failing as required). The live validation on demo-hp proved the **negative** — three healthy disks still read Rendben across the deploy, no false alert — and the **severity wire** end to end, but no live disk has actually reached Hiba. **This is the honest gap and it must not be closed by pointing at the fixture tests**: the drive that produced the fixture is in DooPlex, which is Tier 2 and never a drill target, and the demo boxes are all-flash and healthy | **WATCHING — NEW 2026-08-14, NARROWED same day.** One item originally in this gap is now PROVEN LIVE: the **persisted state surviving a controller restart**. The v0.215.0→v0.216.0 redeploy destroyed and rebuilt the container, and the new one read back a `changed_at` written by the PREVIOUS version (`2026-08-14T07:23:14.640216851Z`, still intact at 09:31:35Z) instead of re-baselining — Scenario L on real hardware, not just the production-path unit test. **What remains unproven is the verdict itself, plus the stronger restart half: an already-ALERTED disk not re-alerting** | a real degrading disk, or an injection harness | **Closing condition:** a live disk reaching Hiba from counters, OR a deliberate injection through the REAL pipeline (agent `/disks` → controller check → hub event), not a hand-set verdict | CC |
|
||||
| **R-331** | Storage & devices | P4 | **Disk health Phase 3 — growth-rate detection, and retiring the static 64.** The v0.215.0 count backstop (64 unreadable sectors → Hiba) is **a judgement from ONE drive**: the observed benign excursion peaked at 16 and cleared inside an hour, and the terminal run passed 64 at 13 Aug 11:28 and never came back. It is deliberately a backstop BEHIND the sustain rule, not the primary signal, but it is still a magic number tuned on a single sample and it will be wrong for some drive. With Phase 2's history the box can ask the question that actually matters — *is this count climbing, and how fast* — which distinguishes a drive with eight stable aging sectors from one adding forty a day, something no static threshold can do. Revisit 64 when that exists | **READY (M) — NEW 2026-08-14** | R-330 | Growth-rate rule over persisted samples; re-derive or delete the static 64 | CC |
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# The N100 — the lived-in box (diary)
|
||||
|
||||
**What it is.** `demo-felhom` (N100 mini-PC, guest 9201, `felhom.demo-felhom.eu`). From 2026-10-15 it is used the way a
|
||||
household uses a box, and it changes only through the product. **The rule:** `architecture/09-update-architecture.md`
|
||||
§3 decision 254 — the dashboard, the hub, the normal release train and the OS update rings only; no deliberate failure
|
||||
without the operator's word for that one act; reads and observation are free. Tiers: `runbooks/target-selection.md`.
|
||||
|
||||
**What it runs (2026-10-15):** controller 0.314.0, agent 0.156.1. Apps: opengist (standing), qBittorrent, Prowlarr,
|
||||
Sonarr, Radarr (installed 2026-10-15 through the dashboard). Plex: the operator installs it. Drives: the system SSD and the
|
||||
USB drive `hdd_1` (ADATA HD710 PRO / TOSHIBA MQ04ABF100, 931.5 GB), which is also the whole-guest backup target.
|
||||
|
||||
**How to add a line.** Anyone — the operator or a session — who notices something on the N100 adds a dated line below:
|
||||
what happened, who noticed, and the register row it became. Prose here is not a record; the row is.
|
||||
|
||||
## Diary
|
||||
|
||||
- **2026-10-15 — the rule starts.** Written as decision 254. (CC, n100-lived-in task)
|
||||
- **2026-10-15 — the USB drive stays one drive.** The operator asked for a split in two. Read first: it holds no family
|
||||
files — 2.7 GB of the box's nightly whole-guest backups (`dump/`), 3.1 GB of app backups and an off-site restore copy,
|
||||
422 MB of leftover app data from removed apps. It is the whole-guest backup target, so the product refuses to retire it,
|
||||
and the box has no other drive for that role. Nothing was changed. → R-1062 (the operator decides), R-1063 (the
|
||||
dashboard's half-state on that refusal, read from the code). (CC)
|
||||
- **2026-10-15 — media apps installed through the dashboard.** qBittorrent, Prowlarr, Sonarr, Radarr — each healthy in
|
||||
under 35 s; the box chose `hdd_1` for their own config (the wizard asks no drive). The box wired them by itself:
|
||||
Sonarr `…/media/tv` and Radarr `…/media/movies`, tag `hdd-1`, qBittorrent as their client with categories
|
||||
`tv-hdd-1` / `movies-hdd-1` saving under `…/media/torrents/` (the same drive, so imports can be hardlinks); Prowlarr
|
||||
linked to both. A stranger meets the gate on Prowlarr/Sonarr/Radarr and qBittorrent's own login. (CC)
|
||||
- **2026-10-15 — films never go off-site, proven before any download.** The controller's own classifier over the
|
||||
deployed apps: off-site takes no media path; the cross-drive tier would take only qBittorrent's downloads and is not
|
||||
on for it (with one data drive it falls back to the SSD with state only); the whole-guest backup excludes the drives
|
||||
(its log: „excluding bind mount point mp8"). (CC)
|
||||
- **2026-10-15 — demo-hp, not the N100:** the leftover `/mnt/sizing-bench` was removed through the dashboard; it held two
|
||||
apps' cross-drive copies and the dashboard said nothing about them → R-1064. The hub showed demo-hp OK at its next report (14:56 UTC). (CC)
|
||||
- **2026-10-15 — read before the operator's Plex install:** a freshly claimed Plex gets no libraries until the next
|
||||
wiring run (the claim does not start one) → R-1065; the sheet asks for „Bekötés most" only if no library appears.
|
||||
(CC, from the code)
|
||||
@@ -13,6 +13,8 @@
|
||||
| Firmware | AMI AN3PLUS-class | **AMI M42 v01.10 (11/11/2020)** |
|
||||
| PVE node name | `demo-felhom` | `felhom-host` |
|
||||
| Customer | `demo-felhom` | `demo-hp` |
|
||||
| Role | **the lived-in box** (`09` §3 decision 254, 2026-10-15): changes only through the product; no deliberate failure without the operator's word; diary `documentation/lived-in/n100.md` | **Tier 0** — the drill and build host (`runbooks/target-selection.md`) |
|
||||
| Drives (2026-10-15) | system SSD (AirDisk 512 GB); USB `hdd_1` = ADATA HD710 PRO enclosure, TOSHIBA MQ04ABF100 s/n `65NOP3HDT`, 931.5 GB ext4 — enrolled user-data drive AND the whole-guest backup target `felhom-backup` | — |
|
||||
| Agent / controller | *not recorded here* — see the note below | *not recorded here* |
|
||||
| Control plane | **island** `169.254.253.1:8443` on `vmbr9` (R-50, migrated 2026-07-25) | **island** `169.254.253.1:8443` on `vmbr9` (R-50, migrated 2026-07-25) |
|
||||
| SSH alias | `felhom-pve` | **`demo-hp`** |
|
||||
|
||||
@@ -71,7 +71,8 @@ in `documentation/backlog/OPEN-ITEMS.md`, never `--no-verify`.
|
||||
|
||||
| Tier | Meaning | Machines |
|
||||
|---|---|---|
|
||||
| **0 — disposable. Reach here first.** | Exists to be broken; reinstalling is a routine afternoon, not an incident. **A drill that needs a victim uses one of these.** | `demo-hp` (t740), `demo-felhom` (N100) |
|
||||
| **0 — disposable. Reach here first.** | Exists to be broken; reinstalling is a routine afternoon, not an incident. **A drill that needs a victim uses one of these.** | `demo-hp` (t740) and its guests and VMs — alone since 2026-10-15 |
|
||||
| **Lived-in — used, not broken** (`09` §3 decision 254, 2026-10-15) | A demo box a family-like household really uses. It changes only through the product's own paths (dashboard, hub, the normal release train, the OS update rings); **no deliberate failure without the operator's word for that one act**; reads and observation are free; what is found goes into `documentation/lived-in/n100.md` and the register. Not Tier 2 (no paying customer's data), but never „reach here first". | `demo-felhom` (N100) |
|
||||
| **1 — create and destroy freely** | Throwaway VMs, guests, scratch customers — **hosted on a Tier 0 machine** | drill VMs, scratch guests |
|
||||
| **2 — protected. Never a drill target.** | Losing it costs the recovery chain or a real relationship | **DooPlex**, **`ep0`** (operator ruling 2026-08-03) — and nothing else (Peti's cluster RETIRED 2026-09-25) |
|
||||
|
||||
@@ -112,12 +113,14 @@ felhom-pve, and **moved off DooPlex**. This page exists because that ruling sat
|
||||
- **Forbidden:** do not destroy or unblock **`drill-r50` (VM 300)** — the only drift fixture (R-93). **Measured 2026-09-13 (R-461): `qm list` is EMPTY on both demo-hp and demo-felhom — the VM does not exist anywhere, so the fence currently protects nothing and R-93's premise is gone. The fence stays as written for the day someone rebuilds it; do not read its presence here as evidence the fixture exists.**
|
||||
(Access: DooPlex's own key works — `ssh demo-hp`; G1 break-glass is the fallback. `operations/nodes.md`, R-129.)
|
||||
|
||||
### `demo-felhom` — N100 · **Tier 0**
|
||||
### `demo-felhom` — N100 · **Lived-in** (`09` §3 decision 254, since 2026-10-15; Tier 0 until then)
|
||||
|
||||
- **Freely:** create/destroy guests and scratch customers; reinstall the box.
|
||||
- **Care:** it carries the **PBS-DR / offsite tier** — but so does demo-hp now, so this is **no longer
|
||||
a reason to prefer one over the other**. Prefer demo-hp per the 2026-07-25 ruling, on the ruling's
|
||||
own grounds (it is the designated drill host), not because its backup chain is safe to disturb.
|
||||
- **Freely:** read anything — logs, `docker ps`, `df`, the mount table, the hub's view, the plug's meter.
|
||||
- **Through the product only:** installs, removals, settings, drives (the dashboard's own calls); releases by the floor;
|
||||
OS updates by the rings. No drill catalog, no hand edit in the guest, no state-changing `docker`, no reinstall.
|
||||
- **Forbidden without the operator's word for that one act:** any deliberate failure — power cut, drive pull, drill,
|
||||
restore test — and any destructive test. A failure that happens by itself is recorded in `documentation/lived-in/n100.md`.
|
||||
- **Care:** it carries the **PBS-DR / offsite tier**, and its USB drive (`hdd_1`) is its whole-guest backup target.
|
||||
|
||||
<!--
|
||||
CORRECTED 2026-08-06. This line used to read "(demo-hp has none)" and was the runbook's stated reason
|
||||
@@ -144,7 +147,7 @@ kind of belief under which a drill lands somewhere it should not.
|
||||
-->
|
||||
|
||||
|
||||
**Both Tier 0 boxes — the shared backup-target fence is DOWNGRADED to a cost, 2026-08-02 (D-d).** It
|
||||
**Both Tier 0 boxes (as of 2026-08-02; the N100 is lived-in since 2026-10-15, decision 254) — the shared backup-target fence is DOWNGRADED to a cost, 2026-08-02 (D-d).** It
|
||||
read *"do not re-point either backup target"*, because these are the only two **correctly configured**
|
||||
boxes and therefore the regression path new installer logic is measured against. D-d makes both boxes
|
||||
freely breakable and reinstallable, which loses that reference just as thoroughly — so the fence was
|
||||
|
||||
Reference in New Issue
Block a user