Website: the two download clients on the app page; the campaign's evidence; R-988 filed
gates / gates (push) Successful in 6m27s

The catalog published qBittorrent and Transmission today (app-catalog 9081a47). Here:

- two cards in the media category on both language sets, each with the project's own logo,
  each saying what a closed peer port costs (slower swarms, no incoming peers)
- the published count 58 -> 60 on every page that states it, FAQ JSON-LD with its visible twin
- documentation/audits/qbittorrent-2026-10-12/: both bench runs, both box walks and verdicts,
  verify-fixes.json, teardown-newapps.json, and the README brought to its final state
- the 2026-09-30 walk harness: a `type: path` deploy field is filled with the drive ROOT —
  the controller refuses a path inside a drive (409), so the walker could not install any app
  with a drive field at all
- R-988: the Usenet pair (SABnzbd, NZBGet), operator request, not started
- STATUS.md and REPORT-newapps-2026-10-12.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117kRTSgs3rJWUFGxyoWN6Y
This commit is contained in:
2026-10-12 21:03:11 +02:00
parent 5148fe1e11
commit c4d1b0ff98
51 changed files with 2442 additions and 97 deletions
@@ -197,6 +197,7 @@ def wait_app(sub, path="/", want=("200", "302", "303", "401", "403"), tries=60,
DRIVE = "/mnt/felhom-drives/scratch_hdd/userdata"
DRIVE_ROOT = "/mnt/felhom-drives/scratch_hdd" # what a `type: path` field wants
# What THIS run generated for a deploy, per app. Deploy secrets are ENCRYPTED AT REST in
# `app.yaml` (`ENC:…`), which is right and which means a fixture cannot read an app's admin
@@ -232,7 +233,11 @@ def deploy_values(name, sub):
if not f.get("required") and ty != "password":
continue # the controller generates the optional secrets itself
if ty == "path":
p = f"{DRIVE}/{name}"
# A `type: path` field names a DRIVE, not a folder on one. The controller refuses a
# folder with 409 "Az alkalmazas adatainak helye egy meghajto lehet, nem egy mappa a
# meghajton belul" (measured on 9202, 2026-10-12, deploying qbittorrent) - and it then
# creates the app's own folder under the drive itself.
p = DRIVE_ROOT
values[ev] = p
made.append(p)
elif ty in ("secret", "password"):
@@ -6,70 +6,83 @@ client. Radarr's own template said so in its prerequisites („Letöltő kliens
qBittorrent — külön telepítendő)") while the website promised „Automatikus film letöltő… a filmek
automatikusan a könyvtáradba kerülnek". Operator ruling, 2026-10-12: add them.
**Where this run got to.** Both templates are written and **measured twice** — on the bench (LXC 9401,
demo-hp) and on the scratch guest 9202 **through the product**. Neither is published: the onboarding
records are not complete, and `catalog_gates.py` refuses a new template without one.
**Where this run got to. Both are PUBLISHED** — `app-catalog-felhom.eu` `9081a47`, the two templates
and their two complete onboarding records in one commit, with the README and FIRST-ADMIN rows, the
fixtures for both venues and the website cards. Each was measured twice before that: on the bench
(LXC 9401 on demo-hp) and on scratch guest 9202 **through the product**.
## What is in here
| | |
|---|---|
| `bench/` | qBittorrent on LXC 9401: image, telemetry, entrypoint, first admin, storage, ownership, health, memory, a real download, the config as the app rewrote it |
| `transmission-bench/` | the same twelve questions asked of Transmission |
| `box/` | guest 9202 through the product: the two box walks, the app logs, and `verify-fixes.json` — the proof the defects below are gone |
| `bench/` | qBittorrent on LXC 9401: image, telemetry, entrypoint, first admin, storage, ownership, health, memory, a real download, the config as the app rewrote it, and `MV-qbittorrent/` — the harness verdict for the ladder step |
| `transmission-bench/` | the same twelve questions asked of Transmission, plus `MV-transmission/` |
| `box/` | guest 9202 through the product: the two box walks, the per-app box verdicts under `qbittorrent/` and `transmission/`, the app logs, `verify-fixes.json` (the proof the defects below are gone) and `teardown-newapps.json` |
| `tools/` | `boxwalk_newapps.py` (deploy + stranger + sign-in + lock-out through traefik) and `verify_fixes.py` (the re-measure). Both reuse the 2026-09-30 harness for the session, CSRF and setup gate |
## Five defects, each found by measuring and fixed
## Six defects, each found by measuring and fixed before publication
1. **qBittorrent was unreachable on its own public name.** `WebUI\ServerDomains` takes **semicolons**;
with a comma list the app answers 401 „Invalid Host header" to everything, its own name included.
Nothing upstream documents the separator — measured through the app's own API
(`box/verify-fixes.json`, and the four-way test: comma 401/401, single 200/401, semicolon 200/200,
`*` 200/200).
2. **Both clients asked the household's router to open a port.** qBittorrent logs
1. **qBittorrent was unreachable on its own public name.** `WebUI\ServerDomains` with a comma list
makes the app answer 401 „Invalid Host header" to everything, its own name included; semicolons
work **through the API** (the four-way test: comma 401/401, single 200/401, semicolon 200/200, `*`
200/200). Nothing upstream documents the separator.
2. **…and the config file's own dialect drops the extra entries anyway.** A semicolon list seeded
into `qBittorrent.conf` comes back from the app's first read-write cycle as the public name
**alone**, after which the controller's health probe — which dials by container name — is refused
(„Invalid Host header … 'qbittorrent:8080'"). The list moved into `after_install`, where the API
honours it, and the marker is printed only after both the list and the UPnP flag are read back.
3. **Both clients asked the household's router to open a port.** qBittorrent logs
`UPnP/NAT-PMP support: ON` and tries a mapping; Transmission ships `"port-forwarding-enabled": true`.
The box opens no port at home (`01-topology-and-trust.md` §7), so both are off now. qBittorrent's
seeded `Session\UseUPnP=false` **is written and then ignored at first start** — the app reported
`"upnp": true` with that very line in its config — so it goes through `after_install`, which the
app does honour: `ON` at 17:21:51, **`OFF` at 17:21:56**.
3. **Transmission could never become healthy.** It answers 401 on every path once authentication is
The box opens no port at home (`../architecture/01-topology-and-trust.md` §7), so both are off now.
qBittorrent's seeded `Session\UseUPnP=false` **is written and then ignored at first start** — the
app reported `"upnp": true` with that very line in its config — so it goes through `after_install`,
which the app does honour: `ON` at 17:21:51, **`OFF` at 17:21:56** (`box/verify-fixes.json`).
4. **Transmission could never become healthy.** It answers 401 on every path once authentication is
on, so `curl -f` always failed (`exit 22`). The probe accepts 200 or 401 now, with a negative
control that still fails.
4. **Transmission's host whitelist refused its own healthcheck** (400 to `Host: 127.0.0.1`).
5. **The first box walk looked like a lock-out and was not one.** Stranger and household ran from the
same machine, so a shared ban could not be told from a per-visitor one. Re-run from two addresses:
the stranger is banned (`401 401 401 401 401 403`, and 403 on the right password) while **the
household signs in at the same instant (204)**. qBittorrent reads the real visitor address through
the proxy headers; its log names `192.168.0.180`, not traefik. Transmission does not ban at all.
5. **Transmission's host whitelist refused its own healthcheck** (400 to `Host: 127.0.0.1`). The
local names are admitted beside the public one.
6. **Two fixtures were reading the wrong thing.** The box fixture looked for a cookie named `SID`;
qBittorrent 5.x names it `QBT_SID_<port>`. The Transmission fixture read the session id with an
`awk` that matched the header NAME on a second line and so got 400 on every RPC; it uses an
anchored `sed` now, with the payload on stdin.
**And one finding that was not a defect.** The first box walk looked like a household lock-out.
Stranger and household ran from the same machine, so a shared ban could not be told from a
per-visitor one. Re-run from two addresses: the stranger is banned (`401 401 401 401 401 403`, and
403 on the right password) while **the household signs in at the same instant (204)**. qBittorrent
reads the real visitor address through the proxy headers; its log names `192.168.0.180`, not traefik.
Transmission does not ban at all.
## Does a download work with no inbound port? Measured, yes
Operator's question. With UPnP off and the port confirmed closed (`"port-is-open": false`):
The operator's question. With port mapping off and neither peer port published, each client was given
one real torrent (Big Buck Bunny, Blender Foundation, CC BY) through its **own** interface:
| | after 30 s | peers | finished |
|---|---|---|---|
| qBittorrent | 98 % at **4.0 MB/s** | 34 seeds | yes, inside a minute |
| Transmission | 96 % | 48 connected, 43 sending | yes |
| | finished | where the files landed |
|---|---|---|
| qBittorrent | yes, inside a minute — `progress: 1`, `downloaded: 276610512` | `…/media/torrents/Big Buck Bunny/` (`bench/09-download.txt`) |
| Transmission | yes — `percentDone: 1.0`, `status: 6` (seeding) | `…/media/transmission/complete/Big Buck Bunny/` (`transmission-bench/05-download.txt`) |
The tunnel is not involved: Cloudflare carries the app's **web page** inbound, while peer traffic
goes out through the household's own router by NAT. What a closed port costs is incoming peers —
slower on sparse swarms, less upload — and the app text now says so and says the household can switch
it on themselves.
Both files are the completed-state snapshots, which is why their peer counts read 0: the swarm work
was over. The tunnel is not involved either way — Cloudflare carries the app's **web page** inbound,
while peer traffic goes out through the household's own router by NAT. What a closed port costs is
incoming peers (slower on sparse swarms, less upload), and the app text now says so.
## What is still open before these can be published
## State left behind — three layers, verified
- **2.5 / 2.8** — a backup and a restore through the product, data read back (the dawarich route:
the update's per-app backup → remove keeping backups → restore).
- **6.1–6.3** — an upgrade fixture, and a first ladder step proven on bench + 9202
(`upgrade-test.py --write-ladder`).
- **8.3–8.5** — logo, screenshots, the cards on both language pages, the app count 58 → 60, and the
three *arr descriptions that promise automatic downloading.
- **The two onboarding records**, which the gate requires complete before either template may land.
## State left behind
Guest 9202: both apps **removed** through the product (volumes gone, containers gone, the test
downloads deleted from the scratch drive), the controller **restored to the live catalog** from this
run's own saved copy, its cache rebuilt (60 templates, neither new app present). Bench LXC 9401:
deployments down with their volumes, **stopped** as it was found. The live catalog's `main` is
untouched (`3a6e930`). The two templates live in the private drill repo as work in progress.
- **Machine (guest 9202):** both apps removed **through the product** (`POST …/stop` then
`…/remove` with the drive data), `deployed: false` for both, the two config volumes gone, no
container left, and the two download folders deleted from the scratch drive by name. The guest's
standing apps (filebrowser, paperless) are untouched and running. `box/teardown-newapps.json`.
- **Catalog pointer:** the controller is back on the **live** catalog from this run's own saved copy
(`controller.yaml.pre-newapps1012`), the cache removed with it (R-615 — `repo_url` alone is inert),
and the restoration is proven from a **different channel than the controller's own verdict**
(R-286): the sha256 of `qbittorrent`, `transmission` and `grocy`'s `.felhom.yml` on the box equals
the sha256 of the same files at the published `origin/main`, with a decoy pair that must differ and
does. The config names the drill repo zero times.
- **Host (demo-hp):** bench LXC 9401 has no containers and no volumes and is **stopped**, as it was
found. The drill catalog `admin/app-catalog-drill` is reset to the live `main` (`9081a47`), so it
carries the published templates and no work in progress.
- **Hub:** nothing to undo — 9202 reports to no hub by its own configuration (the config header says
hub reporting OFF, no tunnel, no agent local API).
@@ -0,0 +1,8 @@
{
"qbittorrent": {
"status": "running",
"health": "healthy",
"restarts": 0,
"exit": 0
}
}
@@ -0,0 +1,4 @@
qbittorrent | WebUI will be started shortly after internal preparations. Please wait...
qbittorrent |
qbittorrent | ******** Information ********
qbittorrent | To control qBittorrent, access the WebUI at: http://localhost:8080
@@ -0,0 +1,7 @@
{
"/srv/felhom-gate/hdd/userdata/media/torrents": {
"Big Buck Bunny/poster.jpg": "310380:d082c4ae86f4f8d3",
"Big Buck Bunny/Big Buck Bunny.mp4": "276134947:mtime-1791827067",
"Big Buck Bunny/Big Buck Bunny.en.srt": "140:18e9b7280644d12f"
}
}
@@ -0,0 +1,3 @@
{
"/srv/felhom-gate/hdd/userdata/media/torrents": "4434017b4bf24656096e6e880f4de7e8e9e34751f594c9a57af6a95094d9a8c5"
}
@@ -0,0 +1,3 @@
{
"/srv/felhom-gate/hdd/userdata/media/torrents": {}
}
@@ -0,0 +1,3 @@
{
"/srv/felhom-gate/hdd/userdata/media/torrents": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
@@ -0,0 +1,762 @@
[
{
"t": 15.1,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802689024,
"peak": 803291136,
"anon": 332910592,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 300
},
{
"t": 30.2,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802775040,
"peak": 804659200,
"anon": 332910592,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 600
},
{
"t": 45.4,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 803000320,
"peak": 804659200,
"anon": 332910592,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 900
},
{
"t": 60.5,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 803033088,
"peak": 804937728,
"anon": 332914688,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1200
},
{
"t": 75.6,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802058240,
"peak": 804937728,
"anon": 332914688,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1496
},
{
"t": 90.7,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802254848,
"peak": 804937728,
"anon": 332853248,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1796
},
{
"t": 105.8,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 801980416,
"peak": 804937728,
"anon": 332853248,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2096
},
{
"t": 121.0,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802594816,
"peak": 805007360,
"anon": 333017088,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2396
},
{
"t": 136.1,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802635776,
"peak": 805007360,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2696
},
{
"t": 151.2,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802324480,
"peak": 805007360,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2996
},
{
"t": 166.4,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802590720,
"peak": 805007360,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3296
},
{
"t": 181.5,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802545664,
"peak": 805007360,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3593
},
{
"t": 196.6,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802553856,
"peak": 805007360,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3893
},
{
"t": 211.7,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802369536,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4192
},
{
"t": 226.8,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802500608,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4492
},
{
"t": 242.0,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802340864,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4792
},
{
"t": 257.1,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 801964032,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5092
},
{
"t": 272.2,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802725888,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5392
},
{
"t": 287.3,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802803712,
"peak": 805163008,
"anon": 332857344,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5692
},
{
"t": 302.5,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802516992,
"peak": 805163008,
"anon": 332840960,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5988
},
{
"t": 317.6,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802443264,
"peak": 805163008,
"anon": 333021184,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6288
},
{
"t": 332.7,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802164736,
"peak": 805163008,
"anon": 332996608,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6588
},
{
"t": 347.9,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802287616,
"peak": 805163008,
"anon": 332988416,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6888
},
{
"t": 363.0,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802058240,
"peak": 805163008,
"anon": 332988416,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7188
},
{
"t": 378.1,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802795520,
"peak": 805163008,
"anon": 332988416,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7488
},
{
"t": 393.3,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802807808,
"peak": 805163008,
"anon": 332984320,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7788
},
{
"t": 408.4,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 803041280,
"peak": 805163008,
"anon": 332988416,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8089
},
{
"t": 423.5,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802750464,
"peak": 805163008,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8389
},
{
"t": 438.7,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802504704,
"peak": 805163008,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8685
},
{
"t": 453.8,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802435072,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8985
},
{
"t": 468.9,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802770944,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9285
},
{
"t": 484.0,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802856960,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9585
},
{
"t": 499.2,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802213888,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9885
},
{
"t": 514.3,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 803074048,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10185
},
{
"t": 529.4,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802435072,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10485
},
{
"t": 544.6,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802865152,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10781
},
{
"t": 559.7,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802451456,
"peak": 805556224,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11081
},
{
"t": 574.8,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802271232,
"peak": 805883904,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11381
},
{
"t": 590.0,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802050048,
"peak": 805883904,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11681
},
{
"t": 605.1,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"current": 802615296,
"peak": 805883904,
"anon": 332980224,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11981
}
]
@@ -0,0 +1,60 @@
[17:43:28] scratch drive folders cleared before FROM (R-656): none existed
[17:43:28] MV-qbittorrent: deploying qbittorrent at FROM {'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.3-1'}
[17:44:07] FROM settled=True in 30.9s :: {"qbittorrent": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
[17:44:07] qbittorrent: createCategory felhom6d2253cb http=200
[17:44:07] qbittorrent: torrents/add http=200
[17:44:08] qbittorrent: category kept, torrent present=True
[17:44:08] C1 (seed reads back BEFORE): True
[17:44:08] MV-qbittorrent: swapping to TO {'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.4-1'}
[17:44:10] TO up -d rc=0
[17:44:41] TO settled=True in 30.9s :: {"qbittorrent": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
[17:44:41] migration lines observed: 0
[17:44:42] qbittorrent: category kept, torrent present=True
[17:44:42] RESULT (seed reads back AFTER): True
[17:44:42] files_may_change — the files: ['/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/Big Buck Bunny.en.srt (added)', '/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/Big Buck Bunny.mp4 (added)', '/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/poster.jpg (added)']
[17:44:42] files_may_change: the bind-mounted tree changed under ['/srv/felhom-gate/hdd/userdata/media/torrents']
[17:44:42] memory watch: 600s, 4 callers on 1 path(s) at 172.18.0.2:8080
[17:44:57] + 15s qbittorrent=765M/1024M peak=766M kills=0 rs=0 reqs=300
[17:45:12] + 30s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=600
[17:45:28] + 45s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=900
[17:45:43] + 60s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=1200
[17:45:58] + 76s qbittorrent=764M/1024M peak=767M kills=0 rs=0 reqs=1496
[17:46:13] + 91s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=1796
[17:46:28] + 106s qbittorrent=764M/1024M peak=767M kills=0 rs=0 reqs=2096
[17:46:43] + 121s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=2396
[17:46:58] + 136s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=2696
[17:47:13] + 151s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=2996
[17:47:29] + 166s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=3296
[17:47:44] + 182s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=3593
[17:47:59] + 197s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=3893
[17:48:14] + 212s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=4192
[17:48:29] + 227s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=4492
[17:48:44] + 242s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=4792
[17:48:59] + 257s qbittorrent=764M/1024M peak=767M kills=0 rs=0 reqs=5092
[17:49:14] + 272s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=5392
[17:49:29] + 287s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=5692
[17:49:45] + 302s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=5988
[17:50:00] + 318s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=6288
[17:50:15] + 333s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=6588
[17:50:30] + 348s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=6888
[17:50:45] + 363s qbittorrent=764M/1024M peak=767M kills=0 rs=0 reqs=7188
[17:51:00] + 378s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=7488
[17:51:15] + 393s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=7788
[17:51:31] + 408s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=8089
[17:51:46] + 424s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=8389
[17:52:01] + 439s qbittorrent=765M/1024M peak=767M kills=0 rs=0 reqs=8685
[17:52:16] + 454s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=8985
[17:52:31] + 469s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=9285
[17:52:46] + 484s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=9585
[17:53:01] + 499s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=9885
[17:53:16] + 514s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=10185
[17:53:32] + 529s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=10485
[17:53:47] + 545s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=10781
[17:54:02] + 560s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=11081
[17:54:17] + 575s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=11381
[17:54:32] + 590s qbittorrent=764M/1024M peak=768M kills=0 rs=0 reqs=11681
[17:54:47] + 605s qbittorrent=765M/1024M peak=768M kills=0 rs=0 reqs=11981
[17:54:47] memory watch: killed=False tight=[] requests=11981 codes={'200': 11981}
[17:54:47] MV-qbittorrent: ABORT — putting the FROM images back
[17:55:20] qbittorrent: category kept, torrent present=True
[17:55:20] ABORT: app came back in 30.9s; data present=True
@@ -0,0 +1,4 @@
qbittorrent | WebUI will be started shortly after internal preparations. Please wait...
qbittorrent |
qbittorrent | ******** Information ********
qbittorrent | To control qBittorrent, access the WebUI at: http://localhost:8080
@@ -0,0 +1,8 @@
{
"qbittorrent": {
"status": "running",
"health": "healthy",
"restarts": 0,
"exit": 0
}
}
@@ -0,0 +1,64 @@
{
"harness_version": 5,
"edge": "MV-qbittorrent",
"app": "qbittorrent",
"note": "night 2026-09-23 within-a-major move: qbittorrent=qbittorrentofficial/qbittorrent-nox:5.2.4-1",
"from": {
"qbittorrent": "qbittorrentofficial/qbittorrent-nox:5.2.3-1"
},
"to": {
"qbittorrent": "qbittorrentofficial/qbittorrent-nox:5.2.4-1"
},
"verdict": "proven",
"seed_read_before": true,
"seed_read_after": true,
"healthy_after": true,
"migration_observed": null,
"abort": "starts-and-serves",
"abort_detail": null,
"engine_state_after": null,
"memory": {
"soak_s": 605.3,
"requested_s": 600,
"requests": 11981,
"codes": {
"200": 11981
},
"first_kill": null,
"containers": {
"qbittorrent": {
"limit": 1073741824,
"peak": 805883904,
"peak_pct": 0.751,
"anon_peak_sampled": 333021184,
"anon_peak_pct": 0.31,
"swap_peak": 0,
"oom_kills": 0,
"restarts": 0,
"oomkilled_flag": false,
"measured": true
}
},
"unmeasured": [],
"venue_swap_bytes": 0,
"load": "reached"
},
"marks": [
"files_may_change"
],
"bench_overrides": null,
"duration_s": 30.9,
"measured_at": "2026-10-12T17:55:20Z",
"evidence": "evidence/MV-qbittorrent",
"scratch_cleared": [],
"files_changed": [
"/srv/felhom-gate/hdd/userdata/media/torrents"
],
"files_changed_detail": [
"/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/Big Buck Bunny.en.srt (added)",
"/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/Big Buck Bunny.mp4 (added)",
"/srv/felhom-gate/hdd/userdata/media/torrents/Big Buck Bunny/poster.jpg (added)"
],
"files_ignored": [],
"total_s": 711.8
}
@@ -0,0 +1,18 @@
{
"app": "qbittorrent",
"venue": "box 9202 (drill catalog, controller 0.283.1), the product's guarded Update",
"from": {
"qbittorrent": "qbittorrentofficial/qbittorrent-nox:5.2.3-1"
},
"to": {
"qbittorrent": "qbittorrentofficial/qbittorrent-nox:5.2.4-1"
},
"verdict": "proven",
"seed_read_before": true,
"seed_read_after": true,
"healthy_after": true,
"duration_s": 19.6,
"final_phase": "done",
"measured_at": "2026-10-12T18:32:35Z",
"evidence": "felhom.eu/documentation/audits/pg-last-six-2026-09-30/box/qbittorrent/step.txt"
}
@@ -0,0 +1,19 @@
deploy/reuse qbittorrent: False
C1 seed reads back BEFORE: False
deploy/reuse qbittorrent: True
qbittorrent: the app did not hand back a session cookie
qbittorrent: the app did not hand back a session cookie
C1 seed reads back BEFORE: False
deploy/reuse qbittorrent: True
qbittorrent: no session cookie in the response (HTTP/2 204 | content-security-policy: default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self'; frame-src 'self' blob:; frame-ancestors 'self'; | cross-origin-opener-policy: same-origin | date: Mon, 12 Oct 20)
qbittorrent: no session cookie in the response (HTTP/2 204 | content-security-policy: default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none'; form-action 'self'; frame-src 'self' blob:; frame-ancestors 'self'; | cross-origin-opener-policy: same-origin | date: Mon, 12 Oct 20)
C1 seed reads back BEFORE: False
deploy/reuse qbittorrent: True
qbittorrent: this run holds no generated password for the app
qbittorrent: this run holds no generated password for the app
C1 seed reads back BEFORE: False
deploy/reuse qbittorrent: True
qbittorrent: createCategory felhomed439f7e http=200
qbittorrent: torrents/add http=200
qbittorrent: category kept, torrent present=True
C1 seed reads back BEFORE: True
@@ -0,0 +1,30 @@
before: pinned={'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.3-1'}
drill: dbdf8e1 DRILL qbittorrent: {'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.4-1'} (box proof)
phase +0.0s backing-up | err=None
phase +2.1s safety-dump | err=None
phase +3.1s pulling | err=None
phase +7.2s copying | err=None
phase +13.4s verifying | err=None
phase +19.6s done | err=None
qbittorrent: category kept, torrent present=True
2026/10/12 18:32:37 update.go:537: [INFO] [stacks] update qbittorrent: accepted — guarded update started
2026/10/12 18:32:37 update.go:1378: [INFO] [stacks] update qbittorrent: phase checking
2026/10/12 18:32:37 update.go:795: [INFO] [stacks] update qbittorrent: ladder — the last step (1 of 1) — the catalog's current definition
2026/10/12 18:32:37 update.go:825: [INFO] [stacks] update qbittorrent: no usable copy on any tier — younger than 24h0m0s and not older than this install's deploy (2026-10-12T18:31:43Z) (found: none) — backing up first
2026/10/12 18:32:37 update.go:1378: [INFO] [stacks] update qbittorrent: phase backing-up
2026/10/12 18:32:39 update.go:840: [INFO] [stacks] update qbittorrent: precondition met after the backup — Tier 2 (second drive) copy from 2026-10-12T18:32:38Z
2026/10/12 18:32:39 update.go:1378: [INFO] [stacks] update qbittorrent: phase safety-dump
2026/10/12 18:32:39 update.go:855: [INFO] [stacks] update qbittorrent: safety dump done (0 file(s)) []
2026/10/12 18:32:39 undo.go:287: [INFO] [stacks] update qbittorrent: the undo copy will hold 1 named volume(s), 8.0 MiB
2026/10/12 18:32:39 update.go:1378: [INFO] [stacks] update qbittorrent: phase pinning
2026/10/12 18:32:39 pin.go:373: [INFO] [stacks] update qbittorrent: pin advanced to /opt/docker/felhom-controller/data/catalog-cache/templates/qbittorrent/docker-compose.yml (qbittorrent=qbittorrentofficial/qbittorrent-nox:5.2.4-1)
2026/10/12 18:32:39 update.go:1378: [INFO] [stacks] update qbittorrent: phase pulling
2026/10/12 18:32:43 update.go:1378: [INFO] [stacks] update qbittorrent: phase copying
2026/10/12 18:32:49 update.go:1378: [INFO] [stacks] update qbittorrent: phase copying
2026/10/12 18:32:49 undo.go:437: [INFO] [stacks] update qbittorrent: copied qbittorrent_qbittorrent_config → qbittorrent_qbittorrent_config.pre-update-20261012T183249Z in 710ms
2026/10/12 18:32:49 update.go:1378: [INFO] [stacks] update qbittorrent: phase starting
2026/10/12 18:32:50 update.go:1378: [INFO] [stacks] update qbittorrent: phase verifying
2026/10/12 18:32:55 update.go:1006: [INFO] [stacks] update qbittorrent: healthy after 5s (the app's health check passed)
2026/10/12 18:32:55 update.go:1043: [INFO] [stacks] update qbittorrent: DONE in 19s
RESULT final_phase=done after={'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.4-1'} seed_after=True verdict=proven (19.6 s)
@@ -0,0 +1,25 @@
{
"qbittorrent": {
"was_deployed": true,
"remove_code": "200",
"deployed_after": false
},
"transmission": {
"was_deployed": true,
"remove_code": "200",
"deployed_after": false
},
"catalog": {
"repo_url_before": "",
"repo_url_after": "",
"template_count": 0,
"qbittorrent_present": false,
"transmission_present": false
},
"drive": {
"before": "/mnt/felhom-drives/scratch_hdd/userdata/media/torrents\n/mnt/felhom-drives/scratch_hdd/userdata/media/transmission",
"after": ""
},
"containers": "felhom-controller filebrowser paperless-postgres paperless-redis paperless-webserver traefik",
"volumes_matching": ""
}
@@ -0,0 +1,18 @@
{
"app": "transmission",
"venue": "box 9202 (drill catalog, controller 0.283.1), the product's guarded Update",
"from": {
"transmission": "lscr.io/linuxserver/transmission:version-4.1.2-r0"
},
"to": {
"transmission": "lscr.io/linuxserver/transmission:version-4.1.3-r0"
},
"verdict": "proven",
"seed_read_before": true,
"seed_read_after": true,
"healthy_after": true,
"duration_s": 25.7,
"final_phase": "done",
"measured_at": "2026-10-12T18:33:51Z",
"evidence": "felhom.eu/documentation/audits/pg-last-six-2026-09-30/box/transmission/step.txt"
}
@@ -0,0 +1,5 @@
deploy/reuse transmission: True
transmission: session-set speed-limit-down=700 http=200
transmission: torrent-add http=200 ok=True
transmission: limit kept, torrent present=True
C1 seed reads back BEFORE: True
@@ -0,0 +1,29 @@
before: pinned={'transmission': 'lscr.io/linuxserver/transmission:version-4.1.2-r0'}
drill: 9a1bf36 DRILL transmission: {'transmission': 'lscr.io/linuxserver/transmission:version-4.1.3-r0'} (box proof)
phase +0.0s backing-up | err=None
phase +6.2s pulling | err=None
phase +12.3s copying | err=None
phase +19.5s verifying | err=None
phase +25.7s done | err=None
transmission: limit kept, torrent present=True
2026/10/12 18:33:52 update.go:537: [INFO] [stacks] update transmission: accepted — guarded update started
2026/10/12 18:33:52 update.go:1378: [INFO] [stacks] update transmission: phase checking
2026/10/12 18:33:52 update.go:795: [INFO] [stacks] update transmission: ladder — the last step (1 of 1) — the catalog's current definition
2026/10/12 18:33:52 update.go:825: [INFO] [stacks] update transmission: no usable copy on any tier — younger than 24h0m0s and not older than this install's deploy (2026-10-12T18:33:22Z) (found: none) — backing up first
2026/10/12 18:33:52 update.go:1378: [INFO] [stacks] update transmission: phase backing-up
2026/10/12 18:33:58 update.go:840: [INFO] [stacks] update transmission: precondition met after the backup — Tier 2 (second drive) copy from 2026-10-12T18:33:57Z
2026/10/12 18:33:58 update.go:1378: [INFO] [stacks] update transmission: phase safety-dump
2026/10/12 18:33:58 update.go:855: [INFO] [stacks] update transmission: safety dump done (0 file(s)) []
2026/10/12 18:33:58 undo.go:287: [INFO] [stacks] update transmission: the undo copy will hold 1 named volume(s), 0.0 MiB
2026/10/12 18:33:58 update.go:1378: [INFO] [stacks] update transmission: phase pinning
2026/10/12 18:33:58 pin.go:373: [INFO] [stacks] update transmission: pin advanced to /opt/docker/felhom-controller/data/catalog-cache/templates/transmission/docker-compose.yml (transmission=lscr.io/linuxserver/transmission:version-4.1.3-r0)
2026/10/12 18:33:58 update.go:1378: [INFO] [stacks] update transmission: phase pulling
2026/10/12 18:34:04 update.go:1378: [INFO] [stacks] update transmission: phase copying
2026/10/12 18:34:11 update.go:1378: [INFO] [stacks] update transmission: phase copying
2026/10/12 18:34:11 undo.go:437: [INFO] [stacks] update transmission: copied transmission_transmission_config → transmission_transmission_config.pre-update-20261012T183411Z in 507ms
2026/10/12 18:34:11 update.go:1378: [INFO] [stacks] update transmission: phase starting
2026/10/12 18:34:11 update.go:1378: [INFO] [stacks] update transmission: phase verifying
2026/10/12 18:34:17 update.go:1006: [INFO] [stacks] update transmission: healthy after 5s (the app's health check passed)
2026/10/12 18:34:17 update.go:1043: [INFO] [stacks] update transmission: DONE in 25s
RESULT final_phase=done after={'transmission': 'lscr.io/linuxserver/transmission:version-4.1.3-r0'} seed_after=True verdict=proven (25.7 s)
@@ -0,0 +1,8 @@
{
"transmission": {
"status": "running",
"health": "healthy",
"restarts": 0,
"exit": 0
}
}
@@ -0,0 +1,35 @@
transmission | [migrations] started
transmission | [migrations] no migrations found
transmission | ───────────────────────────────────────
transmission |
transmission | ██╗ ███████╗██╗ ██████╗
transmission | ██║ ██╔════╝██║██╔═══██╗
transmission | ██║ ███████╗██║██║ ██║
transmission | ██║ ╚════██║██║██║ ██║
transmission | ███████╗███████║██║╚██████╔╝
transmission | ╚══════╝╚══════╝╚═╝ ╚═════╝
transmission |
transmission | Brought to you by linuxserver.io
transmission | ───────────────────────────────────────
transmission |
transmission | To support LSIO projects visit:
transmission | https://www.linuxserver.io/donate/
transmission |
transmission | ───────────────────────────────────────
transmission | GID/UID
transmission | ───────────────────────────────────────
transmission |
transmission | User UID: 1000
transmission | User GID: 1000
transmission | ───────────────────────────────────────
transmission | Linuxserver.io version: 4.1.2-r0-ls351
transmission | Build-date: 2026-06-30T12:27:43+00:00
transmission | ───────────────────────────────────────
transmission |
transmission | stat: cannot statx '/downloads/complete': No such file or directory
transmission | find: ‘/downloads/complete’: No such file or directory
transmission | **** Permissions could not be set. This is probably because your volume mounts are remote or read-only. ****
transmission | **** The app may not work properly and we will not provide support for it. ****
transmission | [custom-init] No custom files found, skipping...
transmission | Connection to localhost (::1) 9091 port [tcp/*] succeeded!
transmission | [ls.io-init] done.
@@ -0,0 +1,4 @@
{
"/srv/felhom-gate/hdd/userdata/media/transmission": {},
"/srv/felhom-gate/hdd/userdata/media/transmission/watch": {}
}
@@ -0,0 +1,4 @@
{
"/srv/felhom-gate/hdd/userdata/media/transmission": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"/srv/felhom-gate/hdd/userdata/media/transmission/watch": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
@@ -0,0 +1,4 @@
{
"/srv/felhom-gate/hdd/userdata/media/transmission": {},
"/srv/felhom-gate/hdd/userdata/media/transmission/watch": {}
}
@@ -0,0 +1,4 @@
{
"/srv/felhom-gate/hdd/userdata/media/transmission": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"/srv/felhom-gate/hdd/userdata/media/transmission/watch": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
@@ -0,0 +1,762 @@
[
{
"t": 15.1,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29204480,
"peak": 32493568,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 300
},
{
"t": 30.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29020160,
"peak": 32493568,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 600
},
{
"t": 45.4,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29392896,
"peak": 32493568,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 900
},
{
"t": 60.5,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29216768,
"peak": 32825344,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1200
},
{
"t": 75.7,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29270016,
"peak": 32825344,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1500
},
{
"t": 90.8,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29790208,
"peak": 32825344,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 1801
},
{
"t": 105.9,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29487104,
"peak": 32825344,
"anon": 3280896,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2101
},
{
"t": 121.0,
"containers": {
"transmission": {
"limit": 536870912,
"current": 30281728,
"peak": 32825344,
"anon": 3289088,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2401
},
{
"t": 136.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29192192,
"peak": 32825344,
"anon": 3289088,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 2701
},
{
"t": 151.3,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29552640,
"peak": 32825344,
"anon": 3289088,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3001
},
{
"t": 166.4,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29335552,
"peak": 32825344,
"anon": 3293184,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3301
},
{
"t": 181.5,
"containers": {
"transmission": {
"limit": 536870912,
"current": 29507584,
"peak": 33361920,
"anon": 3293184,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3601
},
{
"t": 196.7,
"containers": {
"transmission": {
"limit": 536870912,
"current": 30363648,
"peak": 33361920,
"anon": 3796992,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 3905
},
{
"t": 211.8,
"containers": {
"transmission": {
"limit": 536870912,
"current": 31752192,
"peak": 33361920,
"anon": 5107712,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4205
},
{
"t": 227.0,
"containers": {
"transmission": {
"limit": 536870912,
"current": 46772224,
"peak": 47046656,
"anon": 16809984,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4505
},
{
"t": 242.1,
"containers": {
"transmission": {
"limit": 536870912,
"current": 63754240,
"peak": 63827968,
"anon": 20672512,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 4805
},
{
"t": 257.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 72364032,
"peak": 73076736,
"anon": 19353600,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5105
},
{
"t": 272.4,
"containers": {
"transmission": {
"limit": 536870912,
"current": 89751552,
"peak": 90591232,
"anon": 19046400,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5405
},
{
"t": 287.5,
"containers": {
"transmission": {
"limit": 536870912,
"current": 108511232,
"peak": 108666880,
"anon": 18542592,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 5706
},
{
"t": 302.7,
"containers": {
"transmission": {
"limit": 536870912,
"current": 112844800,
"peak": 114921472,
"anon": 18595840,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6006
},
{
"t": 317.8,
"containers": {
"transmission": {
"limit": 536870912,
"current": 118894592,
"peak": 119459840,
"anon": 18759680,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6306
},
{
"t": 332.9,
"containers": {
"transmission": {
"limit": 536870912,
"current": 129499136,
"peak": 129974272,
"anon": 20180992,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6606
},
{
"t": 348.1,
"containers": {
"transmission": {
"limit": 536870912,
"current": 144572416,
"peak": 145113088,
"anon": 22351872,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 6906
},
{
"t": 363.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 151588864,
"peak": 151846912,
"anon": 22626304,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7206
},
{
"t": 378.3,
"containers": {
"transmission": {
"limit": 536870912,
"current": 162766848,
"peak": 162770944,
"anon": 22740992,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7510
},
{
"t": 393.4,
"containers": {
"transmission": {
"limit": 536870912,
"current": 171028480,
"peak": 172408832,
"anon": 22790144,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 7810
},
{
"t": 408.6,
"containers": {
"transmission": {
"limit": 536870912,
"current": 177917952,
"peak": 178741248,
"anon": 22781952,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8110
},
{
"t": 423.7,
"containers": {
"transmission": {
"limit": 536870912,
"current": 186368000,
"peak": 186642432,
"anon": 22773760,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8410
},
{
"t": 438.8,
"containers": {
"transmission": {
"limit": 536870912,
"current": 194375680,
"peak": 194772992,
"anon": 22519808,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 8710
},
{
"t": 454.0,
"containers": {
"transmission": {
"limit": 536870912,
"current": 200634368,
"peak": 201076736,
"anon": 22528000,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9010
},
{
"t": 469.1,
"containers": {
"transmission": {
"limit": 536870912,
"current": 208633856,
"peak": 209502208,
"anon": 22544384,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9310
},
{
"t": 484.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 216813568,
"peak": 217448448,
"anon": 22269952,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9611
},
{
"t": 499.4,
"containers": {
"transmission": {
"limit": 536870912,
"current": 222810112,
"peak": 222810112,
"anon": 22269952,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 9911
},
{
"t": 514.5,
"containers": {
"transmission": {
"limit": 536870912,
"current": 229953536,
"peak": 231510016,
"anon": 22265856,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10211
},
{
"t": 529.6,
"containers": {
"transmission": {
"limit": 536870912,
"current": 238043136,
"peak": 238628864,
"anon": 22286336,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10511
},
{
"t": 544.7,
"containers": {
"transmission": {
"limit": 536870912,
"current": 243933184,
"peak": 244301824,
"anon": 22294528,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 10811
},
{
"t": 559.9,
"containers": {
"transmission": {
"limit": 536870912,
"current": 253083648,
"peak": 253677568,
"anon": 22294528,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11111
},
{
"t": 575.0,
"containers": {
"transmission": {
"limit": 536870912,
"current": 258396160,
"peak": 258625536,
"anon": 22286336,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11411
},
{
"t": 590.1,
"containers": {
"transmission": {
"limit": 536870912,
"current": 269279232,
"peak": 269430784,
"anon": 22286336,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 11711
},
{
"t": 605.2,
"containers": {
"transmission": {
"limit": 536870912,
"current": 276484096,
"peak": 277352448,
"anon": 22294528,
"swap": 0,
"swap_peak": 0,
"oom_kill": 0,
"restarts": 0,
"oomkilled_flag": false,
"status": "running",
"cgroup": true
}
},
"requests": 12011
}
]
@@ -0,0 +1,2 @@
transmission | [migrations] started
transmission | [migrations] no migrations found
@@ -0,0 +1,58 @@
[18:03:40] scratch drive folders cleared before FROM (R-656): ['/srv/felhom-gate/hdd/userdata/media/transmission']
[18:03:40] MV-transmission: deploying transmission at FROM {'transmission': 'lscr.io/linuxserver/transmission:version-4.1.2-r0'}
[18:04:11] FROM settled=True in 30.9s :: {"transmission": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
[18:04:11] transmission: session-set speed-limit-down=690 http=200
[18:04:11] transmission: torrent-add http=200 ok=True
[18:04:12] transmission: limit kept, torrent present=True
[18:04:12] C1 (seed reads back BEFORE): True
[18:04:12] MV-transmission: swapping to TO {'transmission': 'lscr.io/linuxserver/transmission:version-4.1.3-r0'}
[18:04:16] TO up -d rc=0
[18:04:47] TO settled=True in 30.9s :: {"transmission": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
[18:04:48] migration lines observed: 2
[18:04:48] transmission: limit kept, torrent present=True
[18:04:48] RESULT (seed reads back AFTER): True
[18:04:48] memory watch: 600s, 4 callers on 1 path(s) at 172.18.0.2:9091
[18:05:03] + 15s transmission=27M/512M peak=30M kills=0 rs=0 reqs=300
[18:05:18] + 30s transmission=27M/512M peak=30M kills=0 rs=0 reqs=600
[18:05:34] + 45s transmission=28M/512M peak=30M kills=0 rs=0 reqs=900
[18:05:49] + 60s transmission=27M/512M peak=31M kills=0 rs=0 reqs=1200
[18:06:04] + 76s transmission=27M/512M peak=31M kills=0 rs=0 reqs=1500
[18:06:19] + 91s transmission=28M/512M peak=31M kills=0 rs=0 reqs=1801
[18:06:34] + 106s transmission=28M/512M peak=31M kills=0 rs=0 reqs=2101
[18:06:49] + 121s transmission=28M/512M peak=31M kills=0 rs=0 reqs=2401
[18:07:04] + 136s transmission=27M/512M peak=31M kills=0 rs=0 reqs=2701
[18:07:19] + 151s transmission=28M/512M peak=31M kills=0 rs=0 reqs=3001
[18:07:35] + 166s transmission=27M/512M peak=31M kills=0 rs=0 reqs=3301
[18:07:50] + 182s transmission=28M/512M peak=31M kills=0 rs=0 reqs=3601
[18:08:05] + 197s transmission=28M/512M peak=31M kills=0 rs=0 reqs=3905
[18:08:20] + 212s transmission=30M/512M peak=31M kills=0 rs=0 reqs=4205
[18:08:35] + 227s transmission=44M/512M peak=44M kills=0 rs=0 reqs=4505
[18:08:50] + 242s transmission=60M/512M peak=60M kills=0 rs=0 reqs=4805
[18:09:05] + 257s transmission=69M/512M peak=69M kills=0 rs=0 reqs=5105
[18:09:21] + 272s transmission=85M/512M peak=86M kills=0 rs=0 reqs=5405
[18:09:36] + 288s transmission=103M/512M peak=103M kills=0 rs=0 reqs=5706
[18:09:51] + 303s transmission=107M/512M peak=109M kills=0 rs=0 reqs=6006
[18:10:06] + 318s transmission=113M/512M peak=113M kills=0 rs=0 reqs=6306
[18:10:21] + 333s transmission=123M/512M peak=123M kills=0 rs=0 reqs=6606
[18:10:36] + 348s transmission=137M/512M peak=138M kills=0 rs=0 reqs=6906
[18:10:51] + 363s transmission=144M/512M peak=144M kills=0 rs=0 reqs=7206
[18:11:07] + 378s transmission=155M/512M peak=155M kills=0 rs=0 reqs=7510
[18:11:22] + 393s transmission=163M/512M peak=164M kills=0 rs=0 reqs=7810
[18:11:37] + 409s transmission=169M/512M peak=170M kills=0 rs=0 reqs=8110
[18:11:52] + 424s transmission=177M/512M peak=177M kills=0 rs=0 reqs=8410
[18:12:07] + 439s transmission=185M/512M peak=185M kills=0 rs=0 reqs=8710
[18:12:22] + 454s transmission=191M/512M peak=191M kills=0 rs=0 reqs=9010
[18:12:37] + 469s transmission=198M/512M peak=199M kills=0 rs=0 reqs=9310
[18:12:52] + 484s transmission=206M/512M peak=207M kills=0 rs=0 reqs=9611
[18:13:08] + 499s transmission=212M/512M peak=212M kills=0 rs=0 reqs=9911
[18:13:23] + 514s transmission=219M/512M peak=220M kills=0 rs=0 reqs=10211
[18:13:38] + 530s transmission=227M/512M peak=227M kills=0 rs=0 reqs=10511
[18:13:53] + 545s transmission=232M/512M peak=232M kills=0 rs=0 reqs=10811
[18:14:08] + 560s transmission=241M/512M peak=241M kills=0 rs=0 reqs=11111
[18:14:23] + 575s transmission=246M/512M peak=246M kills=0 rs=0 reqs=11411
[18:14:38] + 590s transmission=256M/512M peak=256M kills=0 rs=0 reqs=11711
[18:14:53] + 605s transmission=263M/512M peak=264M kills=0 rs=0 reqs=12011
[18:14:54] memory watch: killed=False tight=[] requests=12011 codes={'401': 12011}
[18:14:54] MV-transmission: ABORT — putting the FROM images back
[18:15:30] transmission: limit kept, torrent present=True
[18:15:30] ABORT: app came back in 30.9s; data present=True
@@ -0,0 +1,39 @@
transmission | [migrations] started
transmission | [migrations] no migrations found
transmission | ───────────────────────────────────────
transmission |
transmission | ██╗ ███████╗██╗ ██████╗
transmission | ██║ ██╔════╝██║██╔═══██╗
transmission | ██║ ███████╗██║██║ ██║
transmission | ██║ ╚════██║██║██║ ██║
transmission | ███████╗███████║██║╚██████╔╝
transmission | ╚══════╝╚══════╝╚═╝ ╚═════╝
transmission |
transmission | Brought to you by linuxserver.io
transmission | ───────────────────────────────────────
transmission |
transmission | To support LSIO projects visit:
transmission | https://www.linuxserver.io/donate/
transmission |
transmission | ───────────────────────────────────────
transmission | GID/UID
transmission | ───────────────────────────────────────
transmission |
transmission | User UID: 1000
transmission | User GID: 1000
transmission | ───────────────────────────────────────
transmission | Linuxserver.io version: 4.1.3-r0-ls363
transmission | Build-date: 2026-09-29T16:34:59+00:00
transmission | ───────────────────────────────────────
transmission |
transmission | stat: cannot statx '/downloads/complete': No such file or directory
transmission | find: ‘/downloads/complete’: No such file or directory
transmission | **** Permissions could not be set. This is probably because your volume mounts are remote or read-only. ****
transmission | **** The app may not work properly and we will not provide support for it. ****
transmission | stat: cannot statx '/downloads/incomplete': No such file or directory
transmission | find: ‘/downloads/incomplete’: No such file or directory
transmission | **** Permissions could not be set. This is probably because your volume mounts are remote or read-only. ****
transmission | **** The app may not work properly and we will not provide support for it. ****
transmission | [custom-init] No custom files found, skipping...
transmission | Connection to localhost (::1) 9091 port [tcp/*] succeeded!
transmission | [ls.io-init] done.
@@ -0,0 +1,8 @@
{
"transmission": {
"status": "running",
"health": "healthy",
"restarts": 0,
"exit": 0
}
}
@@ -0,0 +1,58 @@
{
"harness_version": 5,
"edge": "MV-transmission",
"app": "transmission",
"note": "night 2026-09-23 within-a-major move: transmission=lscr.io/linuxserver/transmission:version-4.1.3-r0",
"from": {
"transmission": "lscr.io/linuxserver/transmission:version-4.1.2-r0"
},
"to": {
"transmission": "lscr.io/linuxserver/transmission:version-4.1.3-r0"
},
"verdict": "proven",
"seed_read_before": true,
"seed_read_after": true,
"healthy_after": true,
"migration_observed": "\u001b[2Ktransmission | [migrations] started",
"abort": "starts-and-serves",
"abort_detail": null,
"engine_state_after": null,
"memory": {
"soak_s": 605.4,
"requested_s": 600,
"requests": 12011,
"codes": {
"401": 12011
},
"first_kill": null,
"containers": {
"transmission": {
"limit": 536870912,
"peak": 277352448,
"peak_pct": 0.517,
"anon_peak_sampled": 22790144,
"anon_peak_pct": 0.042,
"swap_peak": 0,
"oom_kills": 0,
"restarts": 0,
"oomkilled_flag": false,
"measured": true
}
},
"unmeasured": [],
"venue_swap_bytes": 0,
"load": "reached"
},
"marks": [],
"bench_overrides": null,
"duration_s": 30.9,
"measured_at": "2026-10-12T18:15:30Z",
"evidence": "evidence/MV-transmission",
"scratch_cleared": [
"/srv/felhom-gate/hdd/userdata/media/transmission"
],
"files_changed": [],
"files_changed_detail": [],
"files_ignored": [],
"total_s": 709.8
}
+2 -1
View File
@@ -122,7 +122,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 — 6 rows (P2 1, P3 2, P4 3)
## Apps & catalog — 7 rows (P2 1, P3 2, P4 4)
| ID | Category | Sev | What | State | Blocked on | Next action | Owner |
|---|---|---|---|---|---|---|---|
@@ -132,6 +132,7 @@ stopping line that lies.
| **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 |
| **R-988** | Apps & catalog | P4 | **The Usenet pair the operator asked for on 2026-10-12: SABnzbd and NZBGet.** Same shape as the torrent pair published the same day (`app-catalog-felhom.eu` `9081a47`) and the same pipeline: a template each, a bench run on LXC 9401, a box walk on 9202 through the product, a first ladder step written by `upgrade-test.py --write-ladder`, a complete onboarding record, README + FIRST-ADMIN rows, and the app cards. Two things are known already and decide the shape: **SABnzbd publishes no image of its own** (so `lscr.io/linuxserver/sabnzbd`, the same third-party exception Transmission got, which the operator granted on 2026-10-12), while **NZBGet has the project's own `nzbgetcom/nzbget`**; and **both need a PAID Usenet provider (server, port, username, password), which the household must bring** - so the app page has to say so before the install, and a provider's credentials are deploy fields the household types, never generated. Neither can be exercised end to end without an account, so the record will say what was measured without one and what it cost. | OPEN - operator request, not started | - | Write both templates; bench then box, as for the torrent pair | CC |
## App updates — 4 rows (P3 4)