Prowlarr evidence (R-1048) + its apps-page card; the stated app count 62 -> 63; R-1057 filed
gates / gates (push) Successful in 6m34s
gates / gates (push) Successful in 6m34s
- documentation/audits/prowlarr-2026-10-15/: bench (update test proven, C3 failed as it must, soak 7.6 %, volume-persistence CLEAN, official-image check), 9202 runs 1-3 (run 1's bump emptied the drill .felhom.yml — a test-tool bug, fixed; run 3 re-proved the step and backup -> remove -> restore with the full template), tools. - website: a Prowlarr card on both apps pages; every stated count 62 -> 63, the media group 19 -> 20; sizing.json + sizing-data.json carry Prowlarr (41/44 MB, onboarding), the sizing test and SIZING.md table moved to 63 apps. - OPEN-ITEMS: R-1057 (a restore of a removed gated app returns without the gate, even from a backup made before the setup — measured on 9202); R-1036 notes the count and that wger/plant-it are hidden/abandoned. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Prowlarr into the live catalog — evidence (R-1048, 2026-10-15)
|
||||
|
||||
The record that cites this folder: `app-catalog-felhom.eu/onboarding/prowlarr.md` (61 checks). The design it follows:
|
||||
`documentation/architecture/15-media-library.md` §6 (the links) and `09-update-architecture.md` §6.4 (the ladder).
|
||||
|
||||
## The venues and what each run proves
|
||||
|
||||
| folder | venue | what it proves |
|
||||
|---|---|---|
|
||||
| `bench/` | LXC 9401 on demo-hp (`/opt/upg`) | licence, tags, the official-image check, first start from birth (memory, tools, files, analytics on by default), the update test `MV-prowlarr` (proven; abort starts-and-serves; 10-minute soak 7.6 %), C3 negative control (failed, as it must), volume-persistence CLEAN |
|
||||
| `box/walk.txt`, `walk-results.json` | 9202, drill catalog, run 1 | install window as a stranger, the setup gate, the first account, sign-in right and wrong, „Kész", the stranger after it, six wrong passwords, the address the app logs, remove with data. **Its Update ran with an EMPTY `.felhom.yml`** — see run 2 |
|
||||
| `box/run2-empty-meta/` | 9202, run 2 | **not a measurement of the template** — the test tool emptied the drill `.felhom.yml` (README there). One product fact: a restore brings the app back at the image in the backup |
|
||||
| `box/run3/` | 9202, drill catalog with the full template | the step version-2.5.2.5491 -> version-2.6.5.5623 through the guarded Update (the box verdict `box/prowlarr/box-verdict-prowlarr.json`), seed -> the Update's per-app backup -> remove keeping backups -> restore -> seed read back; probe negative control; volume size |
|
||||
| `box9201/` | demo-hp 9201, LIVE catalog, after the publish | the link read-back: Sonarr then Prowlarr, „Bekötés most", the link and its test, the sync command; remove both keeping data |
|
||||
| `tools/` | DooPlex | the scripts that ran (passwords and keys never printed) |
|
||||
|
||||
## The test-tool bug (fixed)
|
||||
|
||||
`tools/walk_prowlarr.py` bumped the drill template with `open(fy, "w").write(re.sub(…, open(fy).read(), …))`: the write
|
||||
truncates before the read, so drill commit f2b0cc1 emptied `templates/prowlarr/.felhom.yml`. The product then ran the
|
||||
app with no deploy fields (`env: {}`, traefik rule `Host(\`.enkisfelhom.hu\`)`). Found in run 2 by the gate's `not
|
||||
routed (404)` lines and the 0-byte file in the stack folder. Fixed in the tool (read first, then write); drill commit
|
||||
e917a58 restored the file; run 3 repeated the step. Run 1's checks before the bump stand.
|
||||
|
||||
## Findings and where they went
|
||||
|
||||
- Prowlarr sends anonymous usage data by default → the template seeds it off (template; no row, fixed).
|
||||
- `/initialize.json` gives the API key to anyone before the first account → the setup gate hides it; after the setup
|
||||
it redirects to the login (measured; FIRST-ADMIN row).
|
||||
- No lock-out after wrong passwords → a stranger cannot lock the household out (the property `09` §3 decisions 57–60
|
||||
protect); no row.
|
||||
- The box links Prowlarr only when Sonarr/Radarr come up, or on „Bekötés most" → the copy says so; the register row is
|
||||
in `OPEN-ITEMS.md` (filed in this session, see `box9201/`).
|
||||
@@ -0,0 +1,3 @@
|
||||
404: Not Found GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
== 2026-10-15: does the Prowlarr project publish an image of its own?
|
||||
hub.docker.com/v2/repositories/prowlarr/prowlarr/ -> 404
|
||||
hub.docker.com/v2/repositories/servarr/prowlarr/ -> 404
|
||||
hub.docker.com/v2/repositories/linuxserver/prowlarr/ -> 200
|
||||
ghcr.io anonymous pull token for prowlarr/prowlarr -> 403
|
||||
ghcr.io anonymous pull token for linuxserver/prowlarr -> 200
|
||||
== the project's README, docker lines:
|
||||
[](https://wiki.servarr.com/prowlarr/installation/docker)
|
||||
@@ -0,0 +1,9 @@
|
||||
nightly 2026-10-14T01:17:17 ['amd64', 'arm64'] sha256:5944ab837fcc
|
||||
version-2.6.5.5623 2026-10-07T10:52:59 ['amd64', 'arm64'] sha256:f9151e5bc102
|
||||
latest 2026-10-07T10:52:51 ['amd64', 'arm64'] sha256:f9151e5bc102
|
||||
develop 2026-10-07T10:52:25 ['amd64', 'arm64'] sha256:e7a05286500b
|
||||
v2.6.5.5623 2026-09-16T18:13:53Z False
|
||||
v2.6.4.5611 2026-09-06T11:41:32Z True
|
||||
v2.6.3.5592 2026-08-31T18:00:16Z True
|
||||
v2.6.2.5562 2026-08-23T08:12:32Z True
|
||||
v2.6.1.5509 2026-08-02T10:12:35Z True
|
||||
@@ -0,0 +1,3 @@
|
||||
version-2.4.0.5397 2026-07-15
|
||||
version-2.5.2.5491 2026-09-16
|
||||
version-2.6.5.5623 2026-10-07
|
||||
@@ -0,0 +1,156 @@
|
||||
== image
|
||||
lscr.io/linuxserver/prowlarr:version-2.6.5.5623
|
||||
id=sha256:cc10ec0691c72ac0282a72a61032afa138a3ee4f1c6297c66e60036b737ce4eb digest=lscr.io/linuxserver/prowlarr@sha256:f9151e5bc1025c6d0a630d503210cdcb6bb55a7cc098562609d96a408d838902 size=185390329 arch=amd64
|
||||
== tools in the image (one per run)
|
||||
curl: /usr/bin/curl
|
||||
wget: /usr/bin/wget
|
||||
sh: /bin/sh
|
||||
bash: /bin/bash
|
||||
python3:
|
||||
node:
|
||||
== the service's run script (linuxserver s6)
|
||||
#!/usr/bin/with-contenv bash
|
||||
# shellcheck shell=bash
|
||||
|
||||
if [[ -z ${LSIO_NON_ROOT_USER} ]]; then
|
||||
exec \
|
||||
s6-notifyoncheck -d -n 300 -w 1000 \
|
||||
cd /app/prowlarr/bin s6-setuidgid abc /app/prowlarr/bin/Prowlarr \
|
||||
-nobrowser -data=/config
|
||||
else
|
||||
exec \
|
||||
s6-notifyoncheck -d -n 300 -w 1000 \
|
||||
cd /app/prowlarr/bin /app/prowlarr/bin/Prowlarr \
|
||||
-nobrowser -data=/config
|
||||
fi
|
||||
init-prowlarr-config
|
||||
svc-prowlarr
|
||||
== memory from birth (cgroup /sys/fs/cgroup/system.slice/docker-cd60831859f2819d7d5312216a6815836726cb4934aeb7b89fa35f7de0bb33ec.scope), every 2 s for 150 s
|
||||
peak anon 44 MiB; oom_kill 0; restarts 0; health-like: 200
|
||||
== process list
|
||||
PID USER COMMAND
|
||||
1 root /package/admin/s6/command/s6-svscan -d4 -- /run/service
|
||||
17 root s6-supervise s6-linux-init-shutdownd
|
||||
20 root /package/admin/s6-linux-init/command/s6-linux-init-shutdownd -d3 -c /run/s6/basedir -g 3000 -C -B
|
||||
36 root s6-supervise svc-cron
|
||||
37 root s6-supervise s6rc-oneshot-runner
|
||||
38 root s6-supervise s6rc-fdholder
|
||||
39 root s6-supervise svc-prowlarr
|
||||
47 root /package/admin/s6/command/s6-ipcserverd -1 -- /package/admin/s6/command/s6-ipcserver-access -v0 -E -l0 -i data/rules -- /package/admin/s6/command/s6-sudod -t 30000 -- /package/admin/s6-rc/command/s6-rc-oneshot-run -l ../.. --
|
||||
177 root busybox crond -f -S -l 5
|
||||
270 root ps -o pid,user,args
|
||||
== config.xml after the first start (ApiKey redacted)
|
||||
<Config>
|
||||
<BindAddress>*</BindAddress>
|
||||
<Port>9696</Port>
|
||||
<SslPort>6969</SslPort>
|
||||
<EnableSsl>False</EnableSsl>
|
||||
<LaunchBrowser>True</LaunchBrowser>
|
||||
<ApiKey><redacted></ApiKey>
|
||||
<AuthenticationMethod>None</AuthenticationMethod>
|
||||
<AuthenticationRequired>Enabled</AuthenticationRequired>
|
||||
<AllowedHosts></AllowedHosts>
|
||||
<Branch>master</Branch>
|
||||
<LogLevel>debug</LogLevel>
|
||||
<SslCertPath></SslCertPath>
|
||||
<SslCertPassword></SslCertPassword>
|
||||
<UrlBase></UrlBase>
|
||||
<TrustedNetworks></TrustedNetworks>
|
||||
<InstanceName>Prowlarr</InstanceName>
|
||||
<UpdateMechanism>Docker</UpdateMechanism>
|
||||
</Config>== host config through the app's own API (analytics, update, auth)
|
||||
{'analyticsEnabled': True, 'updateAutomatically': False, 'updateMechanism': 'docker', 'authenticationMethod': 'none', 'authenticationRequired': 'enabled', 'bindAddress': '*', 'port': 9696, 'proxyEnabled': False, 'logLevel': 'debug'}
|
||||
== open TCP connections from the container (after 150 s)
|
||||
== first-start log (60 lines)
|
||||
[migrations] started
|
||||
[migrations] no migrations found
|
||||
───────────────────────────────────────
|
||||
|
||||
██╗ ███████╗██╗ ██████╗
|
||||
██║ ██╔════╝██║██╔═══██╗
|
||||
██║ ███████╗██║██║ ██║
|
||||
██║ ╚════██║██║██║ ██║
|
||||
███████╗███████║██║╚██████╔╝
|
||||
╚══════╝╚══════╝╚═╝ ╚═════╝
|
||||
|
||||
Brought to you by linuxserver.io
|
||||
───────────────────────────────────────
|
||||
|
||||
To support the app dev(s) visit:
|
||||
Prowlarr: https://opencollective.com/prowlarr
|
||||
|
||||
To support LSIO projects visit:
|
||||
https://www.linuxserver.io/donate/
|
||||
|
||||
───────────────────────────────────────
|
||||
GID/UID
|
||||
───────────────────────────────────────
|
||||
|
||||
User UID: 1000
|
||||
User GID: 1000
|
||||
───────────────────────────────────────
|
||||
Linuxserver.io version: 2.6.5.5623-ls163
|
||||
Build-date: 2026-10-07T10:41:33+00:00
|
||||
───────────────────────────────────────
|
||||
|
||||
[custom-init] No custom files found, skipping...
|
||||
[Info] Bootstrap: Starting Prowlarr - /app/prowlarr/bin/Prowlarr - Version 2.6.5.5623
|
||||
[Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[Debug] Bootstrap: Starting in Interactive mode
|
||||
[Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[Warn] Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager: No XML encryptor configured. Key {47654387-96ce-48e3-975d-a24d2f52e390} may be persisted to storage in unencrypted form.
|
||||
[Trace] EventAggregator: Publishing ConfigFileSavedEvent
|
||||
[Info] MigrationController: *** Migrating data source=/config/prowlarr.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
[Info] DatabaseEngineVersionCheck: SQLite 3.53.4
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: => 0.0873453s
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrated
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: => 0.0924168s
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: VersionMigration migrating
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Beginning Transaction
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: CreateTable VersionInfo
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: CREATE TABLE "VersionInfo" ("Version" INTEGER NOT NULL)
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: => 0.0269859s
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Committing Transaction
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: VersionMigration migrated
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: => 0.0354473s
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: VersionUniqueMigration migrating
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Beginning Transaction
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: CreateIndex VersionInfo (Version)
|
||||
[Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: CREATE UNIQUE INDEX "UC_Version" ON "VersionInfo" ("Version" ASC)
|
||||
[Info] FluentMigrator.Runner.MigrationRunner: => 0.0022584s
|
||||
== files the app wrote under /config
|
||||
/config
|
||||
/config/config.xml
|
||||
/config/prowlarr.db-wal
|
||||
/config/logs
|
||||
/config/logs/prowlarr.debug.txt
|
||||
/config/logs/prowlarr.txt
|
||||
/config/prowlarr.pid
|
||||
/config/asp
|
||||
/config/asp/key-47654387-96ce-48e3-975d-a24d2f52e390.xml
|
||||
/config/prowlarr.db
|
||||
/config/prowlarr.db-shm
|
||||
/config/Sentry
|
||||
/config/Sentry/FDD003821460B16D4E0D4235129BD6BFAF29B751
|
||||
/config/logs.db
|
||||
/config/Definitions
|
||||
/config/Definitions/hdonly-api.yml
|
||||
/config/Definitions/snowpt.yml
|
||||
/config/Definitions/tribalmixes.yml
|
||||
/config/Definitions/huntorrent.yml
|
||||
/config/Definitions/eztvl.yml
|
||||
/config/Definitions/fappaizuri.yml
|
||||
/config/Definitions/racing4everyone-api.yml
|
||||
/config/Definitions/crazyspirits-api.yml
|
||||
/config/Definitions/animetorrentsro.yml
|
||||
/config/Definitions/leech24.yml
|
||||
/config/Definitions/fenyarnyek-tracker.yml
|
||||
/config/Definitions/kinorun.yml
|
||||
/config/Definitions/zenith.yml
|
||||
/config/Definitions/dimeadozen.yml
|
||||
/config/Definitions/pussytorrents.yml
|
||||
== removed: 0 containers, 0 volumes
|
||||
@@ -0,0 +1,47 @@
|
||||
"verdict": "proven",
|
||||
"seed_read_before": true,
|
||||
"seed_read_after": true,
|
||||
"healthy_after": true,
|
||||
"migration_observed": "\u001b[2Kprowlarr | [migrations] started",
|
||||
"abort": "starts-and-serves",
|
||||
"abort_detail": null,
|
||||
"engine_state_after": null,
|
||||
"memory": {
|
||||
"soak_s": 605.5,
|
||||
"requested_s": 600,
|
||||
"requests": 11961,
|
||||
"codes": {
|
||||
"200": 11961
|
||||
},
|
||||
"first_kill": null,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"peak": 113446912,
|
||||
"peak_pct": 0.211,
|
||||
"anon_peak_sampled": 41000960,
|
||||
"anon_peak_pct": 0.076,
|
||||
"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-15T10:10:50Z",
|
||||
"evidence": "evidence/MV-prowlarr",
|
||||
"scratch_cleared": [],
|
||||
"files_changed": [],
|
||||
"files_changed_detail": [],
|
||||
"files_ignored": [],
|
||||
"total_s": 724.3
|
||||
}
|
||||
|
||||
[exited with code 0]
|
||||
@@ -0,0 +1,5 @@
|
||||
/opt/upg/evidence/C3
|
||||
/opt/upg/evidence/C3/verdict.json failed NEGATIVE control: the TO image starts and exits immediately
|
||||
removed 3 volumes of this run
|
||||
1
|
||||
status: stopped
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"harness_version": 5,
|
||||
"edge": "C3",
|
||||
"app": "privatebin",
|
||||
"note": "NEGATIVE control: the TO image starts and exits immediately",
|
||||
"from": {
|
||||
"privatebin": "privatebin/pdo:2.0.5"
|
||||
},
|
||||
"to": {
|
||||
"privatebin": "alpine:3.20"
|
||||
},
|
||||
"verdict": "failed",
|
||||
"seed_read_before": true,
|
||||
"seed_read_after": false,
|
||||
"healthy_after": false,
|
||||
"migration_observed": null,
|
||||
"abort": "starts-and-serves",
|
||||
"abort_detail": null,
|
||||
"engine_state_after": null,
|
||||
"memory": null,
|
||||
"marks": [],
|
||||
"bench_overrides": null,
|
||||
"duration_s": 420.8,
|
||||
"measured_at": "2026-10-15T09:58:46Z",
|
||||
"evidence": "evidence/C3",
|
||||
"scratch_cleared": [],
|
||||
"files_changed": [],
|
||||
"files_changed_detail": [],
|
||||
"files_ignored": [],
|
||||
"total_s": 485.2
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"prowlarr": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
[2Kprowlarr | [migrations] started
|
||||
[2Kprowlarr | [migrations] no migrations found
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | ██╗ ███████╗██╗ ██████╗
|
||||
[2Kprowlarr | ██║ ██╔════╝██║██╔═══██╗
|
||||
[2Kprowlarr | ██║ ███████╗██║██║ ██║
|
||||
[2Kprowlarr | ██║ ╚════██║██║██║ ██║
|
||||
[2Kprowlarr | ███████╗███████║██║╚██████╔╝
|
||||
[2Kprowlarr | ╚══════╝╚══════╝╚═╝ ╚═════╝
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | Brought to you by linuxserver.io
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | To support the app dev(s) visit:
|
||||
[2Kprowlarr | Prowlarr: https://opencollective.com/prowlarr
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | To support LSIO projects visit:
|
||||
[2Kprowlarr | https://www.linuxserver.io/donate/
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr | GID/UID
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | User UID: 1000
|
||||
[2Kprowlarr | User GID: 1000
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr | Linuxserver.io version: 2.5.2.5491-ls160
|
||||
[2Kprowlarr | Build-date: 2026-09-16T08:53:07+00:00
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | [custom-init] No custom files found, skipping...
|
||||
[2Kprowlarr | [Info] Bootstrap: Starting Prowlarr - /app/prowlarr/bin/Prowlarr - Version 2.5.2.5491
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Debug] Bootstrap: Console selected
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Info] MigrationController: *** Migrating data source=/config/prowlarr.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[2Kprowlarr | [Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
[2Kprowlarr | [Info] DatabaseEngineVersionCheck: SQLite 3.50.4
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0542648s
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrated
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0584528s
|
||||
[2Kprowlarr | [Info] MigrationController: *** Migrating data source=/config/logs.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[2Kprowlarr | [Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
[2Kprowlarr | [Info] DatabaseEngineVersionCheck: SQLite 3.50.4
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.005874s
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrated
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0061016s
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Now listening on: http://[::]:9696
|
||||
[2Kprowlarr | [Info] CommandExecutor: Starting 3 threads for tasks.
|
||||
[2Kprowlarr | [ls.io-init] done.
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Application started. Press Ctrl+C to shut down.
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Hosting environment: Production
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Content root path: /app/prowlarr/bin
|
||||
@@ -0,0 +1 @@
|
||||
null
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,762 @@
|
||||
[
|
||||
{
|
||||
"t": 15.1,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100339712,
|
||||
"peak": 113446912,
|
||||
"anon": 41000960,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 300
|
||||
},
|
||||
{
|
||||
"t": 30.2,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99377152,
|
||||
"peak": 113446912,
|
||||
"anon": 39952384,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 596
|
||||
},
|
||||
{
|
||||
"t": 45.4,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97824768,
|
||||
"peak": 113446912,
|
||||
"anon": 38797312,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 896
|
||||
},
|
||||
{
|
||||
"t": 60.5,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 96886784,
|
||||
"peak": 113446912,
|
||||
"anon": 36749312,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 1196
|
||||
},
|
||||
{
|
||||
"t": 75.7,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 95993856,
|
||||
"peak": 113446912,
|
||||
"anon": 36790272,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 1493
|
||||
},
|
||||
{
|
||||
"t": 90.8,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97419264,
|
||||
"peak": 113446912,
|
||||
"anon": 38031360,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 1793
|
||||
},
|
||||
{
|
||||
"t": 105.9,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97075200,
|
||||
"peak": 113446912,
|
||||
"anon": 36839424,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 2093
|
||||
},
|
||||
{
|
||||
"t": 121.0,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 96071680,
|
||||
"peak": 113446912,
|
||||
"anon": 36798464,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 2389
|
||||
},
|
||||
{
|
||||
"t": 136.2,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 96092160,
|
||||
"peak": 113446912,
|
||||
"anon": 36769792,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 2689
|
||||
},
|
||||
{
|
||||
"t": 151.3,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97271808,
|
||||
"peak": 113446912,
|
||||
"anon": 36802560,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 2989
|
||||
},
|
||||
{
|
||||
"t": 166.5,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 96870400,
|
||||
"peak": 113446912,
|
||||
"anon": 36802560,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 3287
|
||||
},
|
||||
{
|
||||
"t": 181.6,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97411072,
|
||||
"peak": 113446912,
|
||||
"anon": 36765696,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 3586
|
||||
},
|
||||
{
|
||||
"t": 196.7,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 96997376,
|
||||
"peak": 113446912,
|
||||
"anon": 36737024,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 3886
|
||||
},
|
||||
{
|
||||
"t": 211.9,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97185792,
|
||||
"peak": 113446912,
|
||||
"anon": 36786176,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 4186
|
||||
},
|
||||
{
|
||||
"t": 227.0,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 97894400,
|
||||
"peak": 113446912,
|
||||
"anon": 36818944,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 4486
|
||||
},
|
||||
{
|
||||
"t": 242.1,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101642240,
|
||||
"peak": 113446912,
|
||||
"anon": 39890944,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 4783
|
||||
},
|
||||
{
|
||||
"t": 257.3,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 98832384,
|
||||
"peak": 113446912,
|
||||
"anon": 37060608,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 5083
|
||||
},
|
||||
{
|
||||
"t": 272.4,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99069952,
|
||||
"peak": 113446912,
|
||||
"anon": 37146624,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 5383
|
||||
},
|
||||
{
|
||||
"t": 287.5,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 98840576,
|
||||
"peak": 113446912,
|
||||
"anon": 37117952,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 5679
|
||||
},
|
||||
{
|
||||
"t": 302.7,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 98979840,
|
||||
"peak": 113446912,
|
||||
"anon": 37146624,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 5979
|
||||
},
|
||||
{
|
||||
"t": 317.8,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99758080,
|
||||
"peak": 113446912,
|
||||
"anon": 37097472,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 6279
|
||||
},
|
||||
{
|
||||
"t": 332.9,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99631104,
|
||||
"peak": 113446912,
|
||||
"anon": 37072896,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 6579
|
||||
},
|
||||
{
|
||||
"t": 348.1,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99631104,
|
||||
"peak": 113446912,
|
||||
"anon": 37072896,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 6876
|
||||
},
|
||||
{
|
||||
"t": 363.2,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100147200,
|
||||
"peak": 113446912,
|
||||
"anon": 37019648,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 7176
|
||||
},
|
||||
{
|
||||
"t": 378.3,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 99917824,
|
||||
"peak": 113446912,
|
||||
"anon": 36990976,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 7475
|
||||
},
|
||||
{
|
||||
"t": 393.5,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100225024,
|
||||
"peak": 113446912,
|
||||
"anon": 36990976,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 7775
|
||||
},
|
||||
{
|
||||
"t": 408.6,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100548608,
|
||||
"peak": 113446912,
|
||||
"anon": 36990976,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 8073
|
||||
},
|
||||
{
|
||||
"t": 423.7,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100618240,
|
||||
"peak": 113446912,
|
||||
"anon": 37019648,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 8373
|
||||
},
|
||||
{
|
||||
"t": 438.8,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100392960,
|
||||
"peak": 113446912,
|
||||
"anon": 36990976,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 8672
|
||||
},
|
||||
{
|
||||
"t": 454.0,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101130240,
|
||||
"peak": 113446912,
|
||||
"anon": 36626432,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 8972
|
||||
},
|
||||
{
|
||||
"t": 469.1,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100212736,
|
||||
"peak": 113446912,
|
||||
"anon": 36691968,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 9269
|
||||
},
|
||||
{
|
||||
"t": 484.3,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 100794368,
|
||||
"peak": 113446912,
|
||||
"anon": 36712448,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 9569
|
||||
},
|
||||
{
|
||||
"t": 499.4,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101376000,
|
||||
"peak": 113446912,
|
||||
"anon": 36872192,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 9869
|
||||
},
|
||||
{
|
||||
"t": 514.5,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101093376,
|
||||
"peak": 113446912,
|
||||
"anon": 36835328,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 10169
|
||||
},
|
||||
{
|
||||
"t": 529.6,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 102236160,
|
||||
"peak": 113446912,
|
||||
"anon": 36786176,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 10467
|
||||
},
|
||||
{
|
||||
"t": 544.8,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101814272,
|
||||
"peak": 113446912,
|
||||
"anon": 36835328,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 10765
|
||||
},
|
||||
{
|
||||
"t": 559.9,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 101646336,
|
||||
"peak": 113446912,
|
||||
"anon": 36814848,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 11065
|
||||
},
|
||||
{
|
||||
"t": 575.0,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 102891520,
|
||||
"peak": 113446912,
|
||||
"anon": 37228544,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 11365
|
||||
},
|
||||
{
|
||||
"t": 590.2,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 102367232,
|
||||
"peak": 113446912,
|
||||
"anon": 36925440,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 11665
|
||||
},
|
||||
{
|
||||
"t": 605.3,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"current": 102789120,
|
||||
"peak": 113446912,
|
||||
"anon": 36958208,
|
||||
"swap": 0,
|
||||
"swap_peak": 0,
|
||||
"oom_kill": 0,
|
||||
"restarts": 0,
|
||||
"oomkilled_flag": false,
|
||||
"status": "running",
|
||||
"cgroup": true
|
||||
}
|
||||
},
|
||||
"requests": 11961
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,6 @@
|
||||
[2Kprowlarr | [migrations] started
|
||||
[2Kprowlarr | [migrations] no migrations found
|
||||
[2Kprowlarr | [Info] MigrationController: *** Migrating data source=/config/prowlarr.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[2Kprowlarr | [Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
@@ -0,0 +1,59 @@
|
||||
[09:58:46] scratch drive folders cleared before FROM (R-656): none existed
|
||||
[09:58:46] MV-prowlarr: deploying prowlarr at FROM {'prowlarr': 'lscr.io/linuxserver/prowlarr:version-2.5.2.5491'}
|
||||
[09:59:33] FROM settled=True in 30.9s :: {"prowlarr": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
|
||||
[09:59:33] fixture: the BOX walk's own (ProwlarrBox), through upgrade_boxport
|
||||
[09:59:33] prowlarr: POST /tag felhom68458ecd http=201
|
||||
[09:59:33] prowlarr: POST /appprofile felhom-profile-3a9231 http=201
|
||||
[09:59:34] prowlarr: tag kept, app profile present=True
|
||||
[09:59:34] C1 (seed reads back BEFORE): True
|
||||
[09:59:34] MV-prowlarr: swapping to TO {'prowlarr': 'lscr.io/linuxserver/prowlarr:version-2.6.5.5623'}
|
||||
[09:59:38] TO up -d rc=0
|
||||
[10:00:09] TO settled=True in 30.9s :: {"prowlarr": {"status": "running", "health": "healthy", "restarts": 0, "exit": 0}}
|
||||
[10:00:09] migration lines observed: 6
|
||||
[10:00:09] prowlarr: tag kept, app profile present=True
|
||||
[10:00:09] RESULT (seed reads back AFTER): True
|
||||
[10:00:10] memory watch: 600s, 4 callers on 1 path(s) at 172.18.0.2:9696
|
||||
[10:00:25] + 15s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=300
|
||||
[10:00:40] + 30s prowlarr=94M/512M peak=108M kills=0 rs=0 reqs=596
|
||||
[10:00:55] + 45s prowlarr=93M/512M peak=108M kills=0 rs=0 reqs=896
|
||||
[10:01:10] + 60s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=1196
|
||||
[10:01:25] + 76s prowlarr=91M/512M peak=108M kills=0 rs=0 reqs=1493
|
||||
[10:01:41] + 91s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=1793
|
||||
[10:01:56] + 106s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=2093
|
||||
[10:02:11] + 121s prowlarr=91M/512M peak=108M kills=0 rs=0 reqs=2389
|
||||
[10:02:26] + 136s prowlarr=91M/512M peak=108M kills=0 rs=0 reqs=2689
|
||||
[10:02:41] + 151s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=2989
|
||||
[10:02:56] + 166s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=3287
|
||||
[10:03:11] + 182s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=3586
|
||||
[10:03:26] + 197s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=3886
|
||||
[10:03:42] + 212s prowlarr=92M/512M peak=108M kills=0 rs=0 reqs=4186
|
||||
[10:03:57] + 227s prowlarr=93M/512M peak=108M kills=0 rs=0 reqs=4486
|
||||
[10:04:12] + 242s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=4783
|
||||
[10:04:27] + 257s prowlarr=94M/512M peak=108M kills=0 rs=0 reqs=5083
|
||||
[10:04:42] + 272s prowlarr=94M/512M peak=108M kills=0 rs=0 reqs=5383
|
||||
[10:04:57] + 288s prowlarr=94M/512M peak=108M kills=0 rs=0 reqs=5679
|
||||
[10:05:12] + 303s prowlarr=94M/512M peak=108M kills=0 rs=0 reqs=5979
|
||||
[10:05:28] + 318s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=6279
|
||||
[10:05:43] + 333s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=6579
|
||||
[10:05:58] + 348s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=6876
|
||||
[10:06:13] + 363s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=7176
|
||||
[10:06:28] + 378s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=7475
|
||||
[10:06:43] + 394s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=7775
|
||||
[10:06:58] + 409s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=8073
|
||||
[10:07:13] + 424s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=8373
|
||||
[10:07:29] + 439s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=8672
|
||||
[10:07:44] + 454s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=8972
|
||||
[10:07:59] + 469s prowlarr=95M/512M peak=108M kills=0 rs=0 reqs=9269
|
||||
[10:08:14] + 484s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=9569
|
||||
[10:08:29] + 499s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=9869
|
||||
[10:08:44] + 514s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=10169
|
||||
[10:08:59] + 530s prowlarr=97M/512M peak=108M kills=0 rs=0 reqs=10467
|
||||
[10:09:15] + 545s prowlarr=97M/512M peak=108M kills=0 rs=0 reqs=10765
|
||||
[10:09:30] + 560s prowlarr=96M/512M peak=108M kills=0 rs=0 reqs=11065
|
||||
[10:09:45] + 575s prowlarr=98M/512M peak=108M kills=0 rs=0 reqs=11365
|
||||
[10:10:00] + 590s prowlarr=97M/512M peak=108M kills=0 rs=0 reqs=11665
|
||||
[10:10:15] + 605s prowlarr=98M/512M peak=108M kills=0 rs=0 reqs=11961
|
||||
[10:10:15] memory watch: killed=False tight=[] requests=11961 codes={'200': 11961}
|
||||
[10:10:15] MV-prowlarr: ABORT — putting the FROM images back
|
||||
[10:10:50] prowlarr: tag kept, app profile present=True
|
||||
[10:10:50] ABORT: app came back in 30.9s; data present=True
|
||||
@@ -0,0 +1,60 @@
|
||||
[2Kprowlarr | [migrations] started
|
||||
[2Kprowlarr | [migrations] no migrations found
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | ██╗ ███████╗██╗ ██████╗
|
||||
[2Kprowlarr | ██║ ██╔════╝██║██╔═══██╗
|
||||
[2Kprowlarr | ██║ ███████╗██║██║ ██║
|
||||
[2Kprowlarr | ██║ ╚════██║██║██║ ██║
|
||||
[2Kprowlarr | ███████╗███████║██║╚██████╔╝
|
||||
[2Kprowlarr | ╚══════╝╚══════╝╚═╝ ╚═════╝
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | Brought to you by linuxserver.io
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | To support the app dev(s) visit:
|
||||
[2Kprowlarr | Prowlarr: https://opencollective.com/prowlarr
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | To support LSIO projects visit:
|
||||
[2Kprowlarr | https://www.linuxserver.io/donate/
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr | GID/UID
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | User UID: 1000
|
||||
[2Kprowlarr | User GID: 1000
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr | Linuxserver.io version: 2.6.5.5623-ls163
|
||||
[2Kprowlarr | Build-date: 2026-10-07T10:41:33+00:00
|
||||
[2Kprowlarr | ───────────────────────────────────────
|
||||
[2Kprowlarr |
|
||||
[2Kprowlarr | [custom-init] No custom files found, skipping...
|
||||
[2Kprowlarr | [Info] Bootstrap: Starting Prowlarr - /app/prowlarr/bin/Prowlarr - Version 2.6.5.5623
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Debug] Bootstrap: Starting in Interactive mode
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Info] AppFolderInfo: Data directory is being overridden to [/config]
|
||||
[2Kprowlarr | [Info] MigrationController: *** Migrating data source=/config/prowlarr.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[2Kprowlarr | [Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
[2Kprowlarr | [Info] DatabaseEngineVersionCheck: SQLite 3.53.4
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0508233s
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrated
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0550323s
|
||||
[2Kprowlarr | [Info] MigrationController: *** Migrating data source=/config/logs.db;cache size=-20000;datetimekind=Utc;journal mode=Wal;pooling=True;version=3;busytimeout=1000 ***
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrating
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: PerformDBOperation
|
||||
[2Kprowlarr | [Info] NzbDrone.Core.Datastore.Migration.Framework.NzbDroneSQLiteProcessor: Performing DB Operation
|
||||
[2Kprowlarr | [Info] DatabaseEngineVersionCheck: SQLite 3.53.4
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0062184s
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: DatabaseEngineVersionCheck migrated
|
||||
[2Kprowlarr | [Info] FluentMigrator.Runner.MigrationRunner: => 0.0064463s
|
||||
[2Kprowlarr | [Info] ConfigureHostFilteringOptions: Allowed Hosts is not configured, accepting requests for any host
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Now listening on: http://[::]:9696
|
||||
[2Kprowlarr | [Info] CommandExecutor: Starting 3 threads for tasks.
|
||||
[2Kprowlarr | [ls.io-init] done.
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Application started. Press Ctrl+C to shut down.
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Hosting environment: Production
|
||||
[2Kprowlarr | [Info] Microsoft.Hosting.Lifetime: Content root path: /app/prowlarr/bin
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"prowlarr": {
|
||||
"status": "running",
|
||||
"health": "healthy",
|
||||
"restarts": 0,
|
||||
"exit": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"harness_version": 5,
|
||||
"edge": "MV-prowlarr",
|
||||
"app": "prowlarr",
|
||||
"note": "night 2026-09-23 within-a-major move: prowlarr=lscr.io/linuxserver/prowlarr:version-2.6.5.5623",
|
||||
"from": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.5.2.5491"
|
||||
},
|
||||
"to": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
},
|
||||
"verdict": "proven",
|
||||
"seed_read_before": true,
|
||||
"seed_read_after": true,
|
||||
"healthy_after": true,
|
||||
"migration_observed": "\u001b[2Kprowlarr | [migrations] started",
|
||||
"abort": "starts-and-serves",
|
||||
"abort_detail": null,
|
||||
"engine_state_after": null,
|
||||
"memory": {
|
||||
"soak_s": 605.5,
|
||||
"requested_s": 600,
|
||||
"requests": 11961,
|
||||
"codes": {
|
||||
"200": 11961
|
||||
},
|
||||
"first_kill": null,
|
||||
"containers": {
|
||||
"prowlarr": {
|
||||
"limit": 536870912,
|
||||
"peak": 113446912,
|
||||
"peak_pct": 0.211,
|
||||
"anon_peak_sampled": 41000960,
|
||||
"anon_peak_pct": 0.076,
|
||||
"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-15T10:10:50Z",
|
||||
"evidence": "evidence/MV-prowlarr",
|
||||
"scratch_cleared": [],
|
||||
"files_changed": [],
|
||||
"files_changed_detail": [],
|
||||
"files_ignored": [],
|
||||
"total_s": 724.3
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
{
|
||||
"probe": {
|
||||
"app": "prowlarr",
|
||||
"containers": [
|
||||
{
|
||||
"diff_added": 205,
|
||||
"diff_benign_db_touches": [],
|
||||
"diff_data_dirs": [],
|
||||
"diff_other_dirs": [
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 4,
|
||||
"db_signature": false,
|
||||
"dir": "/",
|
||||
"files": [
|
||||
"etc",
|
||||
"defaults",
|
||||
"run",
|
||||
"app"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 4,
|
||||
"db_signature": false,
|
||||
"dir": "/etc",
|
||||
"files": [
|
||||
"crontabs",
|
||||
"passwd-",
|
||||
"s6-overlay",
|
||||
"group-"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 1,
|
||||
"db_signature": false,
|
||||
"dir": "/etc/crontabs",
|
||||
"files": [
|
||||
"root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 1,
|
||||
"db_signature": false,
|
||||
"dir": "/etc/s6-overlay",
|
||||
"files": [
|
||||
"s6-rc.d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 1,
|
||||
"db_signature": false,
|
||||
"dir": "/etc/s6-overlay/s6-rc.d",
|
||||
"files": [
|
||||
"init-adduser"
|
||||
]
|
||||
},
|
||||
{
|
||||
"added": [],
|
||||
"changed_count": 1,
|
||||
"db_signature": false,
|
||||
"dir": "/etc/s6-overlay/s6-rc.d/init-adduser",
|
||||
"files": [
|
||||
"branding"
|
||||
]
|
||||
}
|
||||
],
|
||||
"diff_token_dirs": [],
|
||||
"diff_total": 219,
|
||||
"diff_unresolved": [],
|
||||
"exit": 0,
|
||||
"gid": 0,
|
||||
"health": "healthy",
|
||||
"image": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623",
|
||||
"mounts": [
|
||||
{
|
||||
"class": "named-declared",
|
||||
"files": 591,
|
||||
"name": "volgate-prowlarr_prowlarr_config",
|
||||
"sample": [
|
||||
"config.xml",
|
||||
"prowlarr.db-wal",
|
||||
"prowlarr.pid",
|
||||
"prowlarr.db",
|
||||
"prowlarr.db-shm",
|
||||
"logs.db",
|
||||
"logs/prowlarr.debug.txt",
|
||||
"logs/prowlarr.txt",
|
||||
"asp/key-676faa09-8e2e-44e6-b101-6bb715cf2305.xml",
|
||||
"Definitions/hdonly-api.yml",
|
||||
"Definitions/snowpt.yml",
|
||||
"Definitions/tribalmixes.yml",
|
||||
"Definitions/huntorrent.yml",
|
||||
"Definitions/eztvl.yml",
|
||||
"Definitions/fappaizuri.yml",
|
||||
"Definitions/racing4everyone-api.yml",
|
||||
"Definitions/crazyspirits-api.yml",
|
||||
"Definitions/animetorrentsro.yml",
|
||||
"Definitions/leech24.yml",
|
||||
"Definitions/fenyarnyek-tracker.yml",
|
||||
"Definitions/kinorun.yml",
|
||||
"Definitions/zenith.yml",
|
||||
"Definitions/dimeadozen.yml",
|
||||
"Definitions/pussytorrents.yml",
|
||||
"Definitions/whiteangel.yml",
|
||||
"Definitions/hdbao.yml",
|
||||
"Definitions/borgzelle.yml",
|
||||
"Definitions/bitagent.yml",
|
||||
"Definitions/midnightscene.yml",
|
||||
"Definitions/asiancinema.yml",
|
||||
"Definitions/thorhub-api.yml",
|
||||
"Definitions/hdolimpo-api.yml",
|
||||
"Definitions/yuscene-api.yml",
|
||||
"Definitions/ultrahd.yml",
|
||||
"Definitions/blueroms.yml",
|
||||
"Definitions/bwtorrents.yml",
|
||||
"Definitions/torrentdownload.yml",
|
||||
"Definitions/hddolby.yml",
|
||||
"Definitions/totheglory2fa.yml",
|
||||
"Definitions/selezen.yml"
|
||||
],
|
||||
"source": "/var/lib/docker/volumes/volgate-prowlarr_prowlarr_config/_data",
|
||||
"target": "/config",
|
||||
"writable_by_app": "yes"
|
||||
}
|
||||
],
|
||||
"name": "prowlarr",
|
||||
"restarts": null,
|
||||
"status": "running",
|
||||
"uid": 0
|
||||
}
|
||||
],
|
||||
"declared_volumes": [
|
||||
"prowlarr_config"
|
||||
],
|
||||
"env_keys": [
|
||||
"DOMAIN",
|
||||
"HDD_PATH",
|
||||
"IMPORT_PATH",
|
||||
"SUBDOMAIN",
|
||||
"TZ",
|
||||
"USERDATA_PATH"
|
||||
],
|
||||
"exercise": [
|
||||
"http://172.18.0.2:9696/ -> 200"
|
||||
],
|
||||
"fixture": null,
|
||||
"ports": [
|
||||
9696
|
||||
]
|
||||
},
|
||||
"reasons": [],
|
||||
"verdict": "CLEAN"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/opt/upg/scripts/upgrade_fixtures.py:643: SyntaxWarning: invalid escape sequence '\$'
|
||||
'| awk "/Session-Id/ {print \$2}"); '
|
||||
self-testing the prober (both directions)…
|
||||
prober flags the R-156 signature and clears a correct template — trustworthy
|
||||
prowlarr CLEAN
|
||||
|
||||
1 clean · 0 broken · 0 undetermined (of 1 in scope)
|
||||
volume-persistence gate OK
|
||||
rc=0
|
||||
@@ -0,0 +1,6 @@
|
||||
11:54:45 attempt 1 (aborted by the walk script's own bug, after the deploy press): running
|
||||
11:54:48 [X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
11:55:20 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
11:55:28 [X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
containers=0 volumes=0 stackdir=0
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
mirror main b5bb89c DRILL prowlarr: the live candidate (R-1048) at the PREVIOUS image version-2.5.2.5491 — the box walk's starting point on 9202
|
||||
|
||||
drill repo main: b5bb89c
|
||||
2026/10/15 09:53:53 sync.go:498: [INFO] [sync] Updated prowlarr/.felhom.yml
|
||||
2026/10/15 09:53:53 sync.go:245: [INFO] [sync] catalog moved 0f1e78b73101 -> b5bb89c2616e (1 new, 1 stack dir(s) changed)
|
||||
2026/10/15 09:53:53 sync.go:283: [INFO] [sync] Catalog sync complete
|
||||
2026/10/15 09:53:53 sync.go:126: [INFO] [sync] Initial sync: Sablonok frissítve — új: prowlarr; frissítve: immich
|
||||
|
||||
26: repo_url: file:///opt/docker/felhom-controller/drill-catalog.git
|
||||
27: sync_interval: 15m
|
||||
-rw------- 1 root root 1944 Oct 12 20:52 /var/lib/docker/volumes/felhom-controller-data/_data/controller.yaml.pre-prowlarr1015
|
||||
mirror main b5bb89c DRILL prowlarr: the live candidate (R-1048) at the PREVIOUS image version-2.5.2.5491 — the box walk's starting point on 9202
|
||||
cache HEAD b5bb89c DRILL prowlarr: the live candidate (R-1048) at the PREVIOUS image version-2.5.2.5491 — the box walk's starting point on 9202
|
||||
file:///opt/docker/felhom-controller/drill-catalog.git
|
||||
|
||||
16: image: lscr.io/linuxserver/prowlarr:version-2.5.2.5491
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
2026/10/15 09:59:58 sync.go:283: [INFO] [sync] Catalog sync complete
|
||||
2026/10/15 09:59:58 sync.go:126: [INFO] [sync] Initial sync: Sablonok frissítve — frissítve: immich
|
||||
|
||||
26: repo_url: https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
|
||||
27: sync_interval: 15m
|
||||
-rw------- 1 root root 1944 Oct 12 20:52 /var/lib/docker/volumes/felhom-controller-data/_data/controller.yaml.pre-prowlarr1015
|
||||
mirror main f2b0cc1 DRILL prowlarr: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (R-1048 box proof)
|
||||
cache HEAD 3ff0cf3 Rule file: a release needs no golden; the floor carries it after the three test boxes; golden weekly (09 §3 decision 250, operator 2026-10-15)
|
||||
https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
|
||||
|
||||
immich: box .felhom.yml == live origin/main: True
|
||||
paperless-ngx: box .felhom.yml == live origin/main: True
|
||||
sonarr: box .felhom.yml == live origin/main: True
|
||||
decoy (prowlarr exists only in the drill): box has prowlarr template: 1
|
||||
ls: cannot access '/opt/docker/felhom-controller/drill-catalog.git': No such file or directory
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"app": "prowlarr",
|
||||
"venue": "box 9202 (drill catalog, controller 0.304.0), the product's guarded Update",
|
||||
"from": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.5.2.5491"
|
||||
},
|
||||
"to": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
},
|
||||
"verdict": "proven",
|
||||
"seed_read_before": true,
|
||||
"seed_read_after": true,
|
||||
"healthy_after": true,
|
||||
"duration_s": 84.1,
|
||||
"final_phase": "done",
|
||||
"measured_at": "2026-10-15T09:58:47Z",
|
||||
"evidence": "felhom.eu/documentation/audits/prowlarr-2026-10-15/box/walk.txt"
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"app": "prowlarr",
|
||||
"venue": "box 9202 (drill catalog), the product's guarded Update \u2014 run 3, the full .felhom.yml",
|
||||
"from": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.5.2.5491"
|
||||
},
|
||||
"to": {
|
||||
"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
},
|
||||
"verdict": "proven",
|
||||
"seed_read_before": true,
|
||||
"seed_read_after": true,
|
||||
"healthy_after": true,
|
||||
"duration_s": 26.7,
|
||||
"final_phase": "done",
|
||||
"measured_at": "2026-10-15T10:39:09Z",
|
||||
"evidence": "felhom.eu/documentation/audits/prowlarr-2026-10-15/box/run3/restore.txt"
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
mirror main e985077 DRILL prowlarr: back to version-2.5.2.5491 for the restore walk (R-1048, checklist 2.5)
|
||||
|
||||
drill repo main: e985077
|
||||
27: sync_interval: 15m
|
||||
-rw------- 1 root root 1944 Oct 12 20:52 /var/lib/docker/volumes/felhom-controller-data/_data/controller.yaml.pre-prowlarr1015
|
||||
mirror main e985077 DRILL prowlarr: back to version-2.5.2.5491 for the restore walk (R-1048, checklist 2.5)
|
||||
cache HEAD e985077 DRILL prowlarr: back to version-2.5.2.5491 for the restore walk (R-1048, checklist 2.5)
|
||||
file:///opt/docker/felhom-controller/drill-catalog.git
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# Run 2 — NOT a measurement of the template (kept as a record)
|
||||
|
||||
Run 1's drill bump (`walk_prowlarr.py`, drill commit f2b0cc1) opened the drill's `.felhom.yml` for writing BEFORE it read
|
||||
it, so the file became EMPTY. Run 1's install, gate, first-admin, stranger and lock-out checks happened before that
|
||||
commit and stand. Run 1's Update and run 2 as a whole ran with an EMPTY `.felhom.yml` on the box: no deploy fields, so
|
||||
`app.yaml` `env: {}`, the traefik rule `Host(\`.enkisfelhom.hu\`)` and the app unreachable from outside (every
|
||||
`gate: … not routed (404)` line). The seed still read back because the fixture talks to the app inside its container.
|
||||
|
||||
The defect was in the test tool, not in the product. Drill commit e917a58 put the full file back; run 3 (`../run3/`)
|
||||
re-proves the step and the restore with it, and writes `../prowlarr/box-verdict-prowlarr.json`. Run 1's verdict is kept
|
||||
as `../prowlarr/box-verdict-prowlarr-run1-empty-meta.json`.
|
||||
|
||||
One true fact from run 2, product behaviour: a restore after „remove, keep backups" brings the app back at the image
|
||||
recorded in the backup (version-2.5.2.5491 here, the image before the Update), not at the catalog's newest.
|
||||
@@ -0,0 +1,123 @@
|
||||
mirror main e985077 DRILL prowlarr: back to version-2.5.2.5491 for the restore walk (R-1048, checklist 2.5)
|
||||
|
||||
drill repo main: e985077
|
||||
12:23:13 [sync] the badge NEVER caught up to lscr.io/linuxserver/prowlarr:version-2.5.2.5491 in 78.3s — catalog_images = None
|
||||
12:23:14 [1] deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
12:23:38 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:23:43 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:23:48 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:23:53 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:23:58 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:03 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:08 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:13 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:18 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:23 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:28 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:33 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:38 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:43 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:49 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:54 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:24:59 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:04 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:09 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:14 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:19 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:24 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:29 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:34 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:39 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:44 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:49 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:54 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:25:59 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:04 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:09 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:14 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:19 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:24 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:29 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:34 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:40 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:45 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:50 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:26:55 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:27:00 app never answered on prowlarr/ping (last rc=0 code=404)
|
||||
12:27:03 [1] running: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
12:27:13 prowlarr: POST /tag felhom6a4ef5fa http=201
|
||||
12:27:16 prowlarr: POST /appprofile felhom-profile-16d260 http=201
|
||||
12:27:29 prowlarr: tag kept, app profile present=True
|
||||
12:27:29 [2] seed {'tag': 'felhom6a4ef5fa', 'profile': 'felhom-profile-16d260'} read back: True
|
||||
12:27:30 drill commit 03b0c0d343d8: -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
mirror main 03b0c0d DRILL prowlarr: the step -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (R-1048, checklist 2.5)
|
||||
|
||||
drill repo main: 03b0c0d
|
||||
12:27:40 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
12:27:40 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
12:27:45 + 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
12:27:46 + 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
12:27:56 + 16.4s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
12:28:02 + 22.6s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
12:29:09 + 89.2s phase=done label=Frissítve err=None hold=None
|
||||
12:29:09 [3] guarded Update (its backing-up phase is the per-app backup): final=done phases=['backing-up', 'safety-dump', 'pulling', 'copying', 'verifying', 'done']
|
||||
12:29:22 prowlarr: tag kept, app profile present=True
|
||||
12:29:22 [3] seed read back after the Update: True
|
||||
12:29:22 [4] restore points offered BEFORE the remove: [{"time": "2026-10-15T10:27:44Z", "short_id": "helyi", "tier": 1, "drive_label": "Belső SSD (rendszer)"}]
|
||||
12:29:26 [4] stop -> 200
|
||||
12:29:57 [4] remove KEEPING the backups -> 200 {"ok": true, "data": {"removed": "prowlarr", "volumes_removed": ["prowlarr_prowlarr_config"], "hdd_paths_removed": [], "hdd_paths_preserved": [], "userdata_kept": [], "verified": true}, "message": "Stack prowlarr removed"}
|
||||
12:30:06 [4] left after remove: containers=0 volumes=0
|
||||
12:30:06 [R] restoring prowlarr from snapshot 'helyi' (of 1 offered)
|
||||
12:30:06 [R] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
|
||||
12:30:06 + 0.0s restore (True, None, None)
|
||||
12:30:28 + 22.3s restore (False, None, None)
|
||||
12:30:28 [R] after restore: state=running hold=None phase=None
|
||||
12:30:32 [5] restore: {"ok": true, "snapshot_id": "helyi", "http": "HTTP/2 302", "seconds": 22.3, "state_after": "running", "hold_after": null, "why": null}
|
||||
12:30:32 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:30:37 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:30:42 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:30:47 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:30:52 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:30:57 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:02 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:07 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:12 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:17 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:22 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:28 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:33 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:38 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:43 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:48 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:53 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:31:58 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:03 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:08 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:13 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:18 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:23 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:28 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:33 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:38 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:43 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:48 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:53 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:32:58 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:03 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:08 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:13 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:19 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:24 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:29 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:34 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:39 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:44 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:49 gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
12:33:54 app never answered on prowlarr/ping (last rc=0 code=404)
|
||||
12:34:07 prowlarr: tag kept, app profile present=True
|
||||
12:34:07 [5] 2.5 the seed reads back after remove + restore: True
|
||||
12:34:10 [5] image after restore: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
12:34:14 [X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
12:34:46 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
12:34:54 [X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
12:34:58 [9] after remove: containers=0 volumes=0
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"seed": {
|
||||
"tag": "felhom6a4ef5fa",
|
||||
"profile": "felhom-profile-16d260"
|
||||
},
|
||||
"seed_before": true,
|
||||
"after_update": true,
|
||||
"after_restore": true,
|
||||
"update_final": "done",
|
||||
"restore": {
|
||||
"ok": true,
|
||||
"snapshot_id": "helyi",
|
||||
"http": "HTTP/2 302",
|
||||
"seconds": 22.3,
|
||||
"state_after": "running"
|
||||
},
|
||||
"measured_at": "2026-10-15T10:34:58Z"
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
[sync] the badge NEVER caught up to lscr.io/linuxserver/prowlarr:version-2.5.2.5491 in 78.3s — catalog_images = None
|
||||
[1] deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
app never answered on prowlarr/ping (last rc=0 code=404)
|
||||
[1] running: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
prowlarr: POST /tag felhom6a4ef5fa http=201
|
||||
prowlarr: POST /appprofile felhom-profile-16d260 http=201
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[2] seed {'tag': 'felhom6a4ef5fa', 'profile': 'felhom-profile-16d260'} read back: True
|
||||
drill commit 03b0c0d343d8: -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
[6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
+ 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
+ 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
+ 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
+ 16.4s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
+ 22.6s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
+ 89.2s phase=done label=Frissítve err=None hold=None
|
||||
[3] guarded Update (its backing-up phase is the per-app backup): final=done phases=['backing-up', 'safety-dump', 'pulling', 'copying', 'verifying', 'done']
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[3] seed read back after the Update: True
|
||||
[4] restore points offered BEFORE the remove: [{"time": "2026-10-15T10:27:44Z", "short_id": "helyi", "tier": 1, "drive_label": "Belső SSD (rendszer)"}]
|
||||
[4] stop -> 200
|
||||
[4] remove KEEPING the backups -> 200 {"ok": true, "data": {"removed": "prowlarr", "volumes_removed": ["prowlarr_prowlarr_config"], "hdd_paths_removed": [], "hdd_paths_preserved": [], "userdata_kept": [], "verified": true}, "message": "Stack prowlarr removed"}
|
||||
[4] left after remove: containers=0 volumes=0
|
||||
[R] restoring prowlarr from snapshot 'helyi' (of 1 offered)
|
||||
[R] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
|
||||
+ 0.0s restore (True, None, None)
|
||||
+ 22.3s restore (False, None, None)
|
||||
[R] after restore: state=running hold=None phase=None
|
||||
[5] restore: {"ok": true, "snapshot_id": "helyi", "http": "HTTP/2 302", "seconds": 22.3, "state_after": "running", "hold_after": null, "why": null}
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
gate: prowlarr not routed right now (404) — not cached, asked again next call
|
||||
app never answered on prowlarr/ping (last rc=0 code=404)
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[5] 2.5 the seed reads back after remove + restore: True
|
||||
[5] image after restore: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
[X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
[X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
[X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
[9] after remove: containers=0 volumes=0
|
||||
@@ -0,0 +1,52 @@
|
||||
mirror main e917a58 DRILL prowlarr: restore the .felhom.yml an earlier walk emptied (open-for-write before read), compose at version-2.5.2.5491 (R-1048 run 3)
|
||||
|
||||
drill repo main: e917a58
|
||||
12:36:56 [sync] the badge NEVER caught up to lscr.io/linuxserver/prowlarr:version-2.5.2.5491 in 78.4s — catalog_images = None
|
||||
12:36:56 [1] deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
12:37:27 gate: prowlarr is gated — passed as the household (cookie set)
|
||||
12:37:30 [1] through traefik: 401 (gated: 302 to the gate is the healthy answer for a stranger)
|
||||
12:37:33 [1] stack .felhom.yml bytes: 3948
|
||||
12:37:37 [1] running: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
12:37:47 prowlarr: POST /tag felhom794ac402 http=201
|
||||
12:37:50 prowlarr: POST /appprofile felhom-profile-0eee01 http=201
|
||||
12:38:02 prowlarr: tag kept, app profile present=True
|
||||
12:38:02 [2] seed {'tag': 'felhom794ac402', 'profile': 'felhom-profile-0eee01'} read back: True
|
||||
12:38:06 [2] 2.7 config volume size after the seed: 5.5M
|
||||
12:38:12 [2] 4.4 negative control, the same probe on a port nothing serves: rc=7 ; the real probe: rc=0
|
||||
12:38:15 [2] 1.8 the app's own start lines: [Info] Microsoft.Hosting.Lifetime: Application started. Press Ctrl+C to shut down. | [Info] Microsoft.Hosting.Lifetime: Hosting environment: Production
|
||||
12:38:16 drill commit ebf3668f589c: -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
mirror main ebf3668f DRILL prowlarr: the step -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (R-1048, checklist 2.5)
|
||||
|
||||
drill repo main: ebf3668
|
||||
12:38:26 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
12:38:26 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
12:38:31 + 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
12:38:32 + 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
12:38:39 + 12.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
12:38:47 + 20.5s phase=starting label=Indítás az új verzióval… err=None hold=None
|
||||
12:38:48 + 21.5s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
12:38:53 + 26.6s phase=done label=Frissítve err=None hold=None
|
||||
12:38:53 [3] guarded Update (its backing-up phase is the per-app backup): final=done phases=['backing-up', 'safety-dump', 'pulling', 'copying', 'starting', 'verifying', 'done']
|
||||
12:39:06 prowlarr: tag kept, app profile present=True
|
||||
12:39:06 [3] seed read back after the Update: True
|
||||
12:39:09 [3] after: {"pinned_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "installed_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "catalog_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "live_compose_image_lines": ["image: lscr.io/linuxserver/prowlarr:version-2.6.5.5623"], "docker_inspect": ["prowlarr lscr.io/linuxserver/prowlarr:ve
|
||||
12:39:09 [3] box verdict proven
|
||||
12:39:09 [4] restore points offered BEFORE the remove: [{"time": "2026-10-15T10:38:30Z", "short_id": "helyi", "tier": 1, "drive_label": "Belső SSD (rendszer)"}]
|
||||
12:39:13 [4] stop -> 200
|
||||
12:39:45 [4] remove KEEPING the backups -> 200 {"ok": true, "data": {"removed": "prowlarr", "volumes_removed": ["prowlarr_prowlarr_config"], "hdd_paths_removed": [], "hdd_paths_preserved": [], "userdata_kept": [], "verified": true}, "message": "Stack prowlarr removed"}
|
||||
12:39:53 [4] left after remove: containers=0 volumes=0
|
||||
12:39:53 [R] restoring prowlarr from snapshot 'helyi' (of 1 offered)
|
||||
12:39:53 [R] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
|
||||
12:39:53 + 0.0s restore (True, None, None)
|
||||
12:40:20 + 26.3s restore (False, None, None)
|
||||
12:40:20 [R] after restore: state=running hold=None phase=None
|
||||
12:40:23 [5] restore: {"ok": true, "snapshot_id": "helyi", "http": "HTTP/2 302", "seconds": 26.4, "state_after": "running", "hold_after": null, "why": null}
|
||||
12:40:37 prowlarr: tag kept, app profile present=True
|
||||
12:40:37 [5] 2.5 the seed reads back after remove + restore: True
|
||||
12:40:40 [5] through traefik after restore: 200
|
||||
12:40:43 [5] app.yaml env keys after restore: DOMAIN SUBDOMAIN
|
||||
12:40:46 [5] image after restore: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
12:40:50 [X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
12:41:21 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
12:41:30 [X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
12:41:33 [9] after remove: containers=0 volumes=0
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"seed": {
|
||||
"tag": "felhom794ac402",
|
||||
"profile": "felhom-profile-0eee01"
|
||||
},
|
||||
"seed_before": true,
|
||||
"after_update": true,
|
||||
"after_restore": true,
|
||||
"update_final": "done",
|
||||
"restore": {
|
||||
"ok": true,
|
||||
"snapshot_id": "helyi",
|
||||
"http": "HTTP/2 302",
|
||||
"seconds": 26.4,
|
||||
"state_after": "running"
|
||||
},
|
||||
"measured_at": "2026-10-15T10:41:33Z"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
[sync] the badge NEVER caught up to lscr.io/linuxserver/prowlarr:version-2.5.2.5491 in 78.4s — catalog_images = None
|
||||
[1] deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
gate: prowlarr is gated — passed as the household (cookie set)
|
||||
[1] through traefik: 401 (gated: 302 to the gate is the healthy answer for a stranger)
|
||||
[1] stack .felhom.yml bytes: 3948
|
||||
[1] running: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
prowlarr: POST /tag felhom794ac402 http=201
|
||||
prowlarr: POST /appprofile felhom-profile-0eee01 http=201
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[2] seed {'tag': 'felhom794ac402', 'profile': 'felhom-profile-0eee01'} read back: True
|
||||
[2] 2.7 config volume size after the seed: 5.5M
|
||||
[2] 4.4 negative control, the same probe on a port nothing serves: rc=7 ; the real probe: rc=0
|
||||
[2] 1.8 the app's own start lines: [Info] Microsoft.Hosting.Lifetime: Application started. Press Ctrl+C to shut down. | [Info] Microsoft.Hosting.Lifetime: Hosting environment: Production
|
||||
drill commit ebf3668f589c: -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
[6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
+ 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
+ 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
+ 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
+ 12.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
+ 20.5s phase=starting label=Indítás az új verzióval… err=None hold=None
|
||||
+ 21.5s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
+ 26.6s phase=done label=Frissítve err=None hold=None
|
||||
[3] guarded Update (its backing-up phase is the per-app backup): final=done phases=['backing-up', 'safety-dump', 'pulling', 'copying', 'starting', 'verifying', 'done']
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[3] seed read back after the Update: True
|
||||
[3] after: {"pinned_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "installed_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "catalog_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "live_compose_image_lines": ["image: lscr.io/linuxserver/prowlarr:version-2.6.5.5623"], "docker_inspect": ["prowlarr lscr.io/linuxserver/prowlarr:ve
|
||||
[3] box verdict proven
|
||||
[4] restore points offered BEFORE the remove: [{"time": "2026-10-15T10:38:30Z", "short_id": "helyi", "tier": 1, "drive_label": "Belső SSD (rendszer)"}]
|
||||
[4] stop -> 200
|
||||
[4] remove KEEPING the backups -> 200 {"ok": true, "data": {"removed": "prowlarr", "volumes_removed": ["prowlarr_prowlarr_config"], "hdd_paths_removed": [], "hdd_paths_preserved": [], "userdata_kept": [], "verified": true}, "message": "Stack prowlarr removed"}
|
||||
[4] left after remove: containers=0 volumes=0
|
||||
[R] restoring prowlarr from snapshot 'helyi' (of 1 offered)
|
||||
[R] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
|
||||
+ 0.0s restore (True, None, None)
|
||||
+ 26.3s restore (False, None, None)
|
||||
[R] after restore: state=running hold=None phase=None
|
||||
[5] restore: {"ok": true, "snapshot_id": "helyi", "http": "HTTP/2 302", "seconds": 26.4, "state_after": "running", "hold_after": null, "why": null}
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[5] 2.5 the seed reads back after remove + restore: True
|
||||
[5] through traefik after restore: 200
|
||||
[5] app.yaml env keys after restore: DOMAIN SUBDOMAIN
|
||||
[5] image after restore: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 health=healthy
|
||||
[X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
[X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
[X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
[9] after remove: containers=0 volumes=0
|
||||
@@ -0,0 +1,57 @@
|
||||
11:55:37 [1] POST /api/stacks/prowlarr/deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
11:56:00 [1] install window, a stranger on the public name (23 s, distinct answers):
|
||||
11:56:00 8x / -> 302 loc=https://felhom.enkisfelhom.hu/__gate/start?rd=https%3A%2F%2F
|
||||
11:56:00 14x / -> 404
|
||||
11:56:00 8x /api/v1/system/status -> 401
|
||||
11:56:00 14x /api/v1/system/status -> 404
|
||||
11:56:00 8x /initialize.json -> 401
|
||||
11:56:00 14x /initialize.json -> 404
|
||||
11:56:03 [1] state=running health=None restarts: 0 started=2026-10-15T09:55:47.047772324Z health=healthy
|
||||
11:56:07 [1] the first-start seed line: [felhom] first start - AuthenticationRequired=Enabled, AnalyticsEnabled=False seeded
|
||||
11:56:10 [1] config.xml (key redacted): <Config> <AuthenticationRequired>Enabled</AuthenticationRequired> <AnalyticsEnabled>False</AnalyticsEnabled> <LogLevel>debug</LogLevel> <UrlBase></UrlBase> <BindAddress>*</BindAddress> <Port>9696</Port> <SslPort>6969</SslPort> <EnableSsl>False</EnableSsl> <LaunchBrowser>True</LaunchBrowser> <ApiKey><redacted></ApiKey> <AuthenticationMethod>None</AuthenticationMethod> <Branch>master</Branch> <SslCertPath></SslCertPath> <SslCertPassword></SslCertPassword> <InstanceName>Prowlarr</InstanceName> <UpdateMechanism>Docker</UpdateMechanism> </Config>
|
||||
11:56:10 gate: prowlarr is gated — passed as the household (cookie set)
|
||||
11:56:10 [2] household GET /initialize.json through the gate -> 200, carries the API key: True
|
||||
11:56:10 [2] GET /api/v1/config/host -> 200: authenticationMethod=none authenticationRequired=enabled analyticsEnabled=False
|
||||
11:56:10 [2] the household makes its first account (PUT /api/v1/config/host, forms) -> 202
|
||||
11:56:18 [3] sign in (right password) POST /login -> 302 loc=/ auth-cookie=ProwlarrAuth
|
||||
11:56:18 [3] sign in (wrong password) POST /login -> 302 loc=/login?returnUrl=/&loginFailed=true auth-cookie=none
|
||||
11:56:29 prowlarr: POST /tag felhom7b8df208 http=201
|
||||
11:56:32 prowlarr: POST /appprofile felhom-profile-11b5ec http=201
|
||||
11:56:45 prowlarr: tag kept, app profile present=True
|
||||
11:56:45 [4] seed {'tag': 'felhom7b8df208', 'profile': 'felhom-profile-11b5ec'} read back before the update: True
|
||||
11:56:45 [4] backup press SKIPPED for prowlarr (R-648: whole-box only; the update's backing-up phase backs up prowlarr alone)
|
||||
11:56:45 [4] „Mentés most” -> null
|
||||
11:56:45 [5] the household's „Kész, beállítottam” -> 200 {"data": {"opened": true}, "error": "", "ok": true}
|
||||
11:56:50 [5] stranger after the gate opened: GET / -> 302 loc=https://prowlarr.enkisfelhom.hu/login?returnUrl=%2F apiKey-in-body=False
|
||||
11:56:50 [5] stranger after the gate opened: GET /initialize.json -> 302 loc=https://prowlarr.enkisfelhom.hu/login?returnUrl=%2Finitialize.json apiKey-in-body=False
|
||||
11:56:50 [5] stranger after the gate opened: GET /api/v1/system/status -> 401 apiKey-in-body=False
|
||||
11:56:50 [5] stranger after the gate opened: GET /api/v1/indexer -> 401 apiKey-in-body=False
|
||||
11:56:50 [6] stranger wrong password #1 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] stranger wrong password #2 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] stranger wrong password #3 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] stranger wrong password #4 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] stranger wrong password #5 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] stranger wrong password #6 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
11:56:50 [6] the household's right password right after (same address) -> 302 loc=/ auth-cookie=yes
|
||||
11:56:53 [6] what the app logged for the failures (address): 2026-10-15 11:56:50.4|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test' | 2026-10-15 11:56:50.5|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test' | 2026-10-15 11:56:50.5|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test'
|
||||
11:56:57 [7] drill commit f2b0cc15090d: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
mirror main f2b0cc1 DRILL prowlarr: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (R-1048 box proof)
|
||||
|
||||
drill repo main: f2b0cc1
|
||||
11:57:07 [7] badges: {"hu": [{"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.", "text": "Frissítés elérhető"}], "en": [{"title": "A newer version of this app is available. Select the Update button to start it.", "text": "Update available"}]}
|
||||
11:57:07 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
11:57:07 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
11:57:12 + 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
11:57:13 + 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
11:57:18 + 11.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
11:57:24 + 17.4s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
11:58:31 + 84.1s phase=done label=Frissítve err=None hold=None
|
||||
11:58:31 [7] guarded Update: {"accepted": true, "http": "202", "phases": [{"t": 0.0, "phase": "backing-up", "label": "Biztonsági mentés készül a frissítés előtt…", "updating": true, "error": null, "hold": null}, {"t": 5.1, "phase": "safety-dump", "label": "Adatbázis pillanatkép…", "updating": true, "error": null, "hold": null}, {"t": 6.2, "phase": "pulling", "label": "Új verzió letöltése…", "updating": true, "error": null, "h
|
||||
11:58:44 prowlarr: tag kept, app profile present=True
|
||||
11:58:47 [7] after: {"pinned_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "installed_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "catalog_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "live_compose_image_lines": ["image: lscr.io/linuxserver/prowlarr:version-2.6.5.5623"], "docker_inspect": ["prowlarr lscr.io/linuxserver/prowlarr:ve
|
||||
11:58:47 [8] box verdict proven
|
||||
11:58:51 [X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
11:59:23 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
11:59:31 [X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
11:59:34 [9] after remove: containers=0 volumes=0 stackdir=1
|
||||
exit 0
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"install_window": {
|
||||
"/ -> 404": 14,
|
||||
"/initialize.json -> 404": 14,
|
||||
"/api/v1/system/status -> 404": 14,
|
||||
"/ -> 302 loc=https://felhom.enkisfelhom.hu/__gate/start?rd=https%3A%2F%2F": 8,
|
||||
"/initialize.json -> 401": 8,
|
||||
"/api/v1/system/status -> 401": 8
|
||||
},
|
||||
"first_admin": "202",
|
||||
"signin_right": [
|
||||
"302",
|
||||
"/",
|
||||
true
|
||||
],
|
||||
"signin_wrong": [
|
||||
"302",
|
||||
"/login?returnUrl=/&loginFailed=true",
|
||||
false
|
||||
],
|
||||
"stranger_open_/": [
|
||||
"302",
|
||||
"https://prowlarr.enkisfelhom.hu/login?returnUrl=%2F",
|
||||
false
|
||||
],
|
||||
"stranger_open_/initialize.json": [
|
||||
"302",
|
||||
"https://prowlarr.enkisfelhom.hu/login?returnUrl=%2Finitialize.json",
|
||||
false
|
||||
],
|
||||
"stranger_open_/api/v1/system/status": [
|
||||
"401",
|
||||
"",
|
||||
false
|
||||
],
|
||||
"stranger_open_/api/v1/indexer": [
|
||||
"401",
|
||||
"",
|
||||
false
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
[1] POST /api/stacks/prowlarr/deploy -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
[1] install window, a stranger on the public name (23 s, distinct answers):
|
||||
8x / -> 302 loc=https://felhom.enkisfelhom.hu/__gate/start?rd=https%3A%2F%2F
|
||||
14x / -> 404
|
||||
8x /api/v1/system/status -> 401
|
||||
14x /api/v1/system/status -> 404
|
||||
8x /initialize.json -> 401
|
||||
14x /initialize.json -> 404
|
||||
[1] state=running health=None restarts: 0 started=2026-10-15T09:55:47.047772324Z health=healthy
|
||||
[1] the first-start seed line: [felhom] first start - AuthenticationRequired=Enabled, AnalyticsEnabled=False seeded
|
||||
[1] config.xml (key redacted): <Config> <AuthenticationRequired>Enabled</AuthenticationRequired> <AnalyticsEnabled>False</AnalyticsEnabled> <LogLevel>debug</LogLevel> <UrlBase></UrlBase> <BindAddress>*</BindAddress> <Port>9696</Port> <SslPort>6969</SslPort> <EnableSsl>False</EnableSsl> <LaunchBrowser>True</LaunchBrowser> <ApiKey><redacted></ApiKey> <AuthenticationMethod>None</AuthenticationMethod> <Branch>master</Branch> <SslCertPath></SslCertPath> <SslCertPassword></SslCertPassword> <InstanceName>Prowlarr</InstanceName> <UpdateMechanism>Docker</UpdateMechanism> </Config>
|
||||
gate: prowlarr is gated — passed as the household (cookie set)
|
||||
[2] household GET /initialize.json through the gate -> 200, carries the API key: True
|
||||
[2] GET /api/v1/config/host -> 200: authenticationMethod=none authenticationRequired=enabled analyticsEnabled=False
|
||||
[2] the household makes its first account (PUT /api/v1/config/host, forms) -> 202
|
||||
[3] sign in (right password) POST /login -> 302 loc=/ auth-cookie=ProwlarrAuth
|
||||
[3] sign in (wrong password) POST /login -> 302 loc=/login?returnUrl=/&loginFailed=true auth-cookie=none
|
||||
prowlarr: POST /tag felhom7b8df208 http=201
|
||||
prowlarr: POST /appprofile felhom-profile-11b5ec http=201
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[4] seed {'tag': 'felhom7b8df208', 'profile': 'felhom-profile-11b5ec'} read back before the update: True
|
||||
[4] backup press SKIPPED for prowlarr (R-648: whole-box only; the update's backing-up phase backs up prowlarr alone)
|
||||
[4] „Mentés most” -> null
|
||||
[5] the household's „Kész, beállítottam” -> 200 {"data": {"opened": true}, "error": "", "ok": true}
|
||||
[5] stranger after the gate opened: GET / -> 302 loc=https://prowlarr.enkisfelhom.hu/login?returnUrl=%2F apiKey-in-body=False
|
||||
[5] stranger after the gate opened: GET /initialize.json -> 302 loc=https://prowlarr.enkisfelhom.hu/login?returnUrl=%2Finitialize.json apiKey-in-body=False
|
||||
[5] stranger after the gate opened: GET /api/v1/system/status -> 401 apiKey-in-body=False
|
||||
[5] stranger after the gate opened: GET /api/v1/indexer -> 401 apiKey-in-body=False
|
||||
[6] stranger wrong password #1 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] stranger wrong password #2 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] stranger wrong password #3 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] stranger wrong password #4 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] stranger wrong password #5 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] stranger wrong password #6 -> 302 loc=/login?returnUrl=/&loginFailed=true
|
||||
[6] the household's right password right after (same address) -> 302 loc=/ auth-cookie=yes
|
||||
[6] what the app logged for the failures (address): 2026-10-15 11:56:50.4|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test' | 2026-10-15 11:56:50.5|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test' | 2026-10-15 11:56:50.5|Warn|Auth|Auth-Failure ip 192.168.0.180 username 'felhom-test'
|
||||
[7] drill commit f2b0cc15090d: lscr.io/linuxserver/prowlarr:version-2.5.2.5491 -> lscr.io/linuxserver/prowlarr:version-2.6.5.5623 (push rc=0)
|
||||
[7] badges: {"hu": [{"title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.", "text": "Frissítés elérhető"}], "en": [{"title": "A newer version of this app is available. Select the Update button to start it.", "text": "Update available"}]}
|
||||
[6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}
|
||||
+ 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None
|
||||
+ 5.1s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None
|
||||
+ 6.2s phase=pulling label=Új verzió letöltése… err=None hold=None
|
||||
+ 11.3s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None
|
||||
+ 17.4s phase=verifying label=Működés ellenőrzése… err=None hold=None
|
||||
+ 84.1s phase=done label=Frissítve err=None hold=None
|
||||
[7] guarded Update: {"accepted": true, "http": "202", "phases": [{"t": 0.0, "phase": "backing-up", "label": "Biztonsági mentés készül a frissítés előtt…", "updating": true, "error": null, "hold": null}, {"t": 5.1, "phase": "safety-dump", "label": "Adatbázis pillanatkép…", "updating": true, "error": null, "hold": null}, {"t": 6.2, "phase": "pulling", "label": "Új verzió letöltése…", "updating": true, "error": null, "h
|
||||
prowlarr: tag kept, app profile present=True
|
||||
[7] after: {"pinned_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "installed_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "catalog_images": {"prowlarr": "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"}, "live_compose_image_lines": ["image: lscr.io/linuxserver/prowlarr:version-2.6.5.5623"], "docker_inspect": ["prowlarr lscr.io/linuxserver/prowlarr:ve
|
||||
[8] box verdict proven
|
||||
[X] stop -> 200 {'ok': True, 'message': 'Stack prowlarr stop completed'}
|
||||
[X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'prowlarr', 'volumes_removed': ['prowlarr_prowlarr_config'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'A
|
||||
[X] after remove: deployed=False leftovers='/opt/docker/stacks/prowlarr'
|
||||
[9] after remove: containers=0 volumes=0 stackdir=1
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# bench_first_start.sh <image> — Prowlarr's first start on the bench (LXC 9401), measured. A throwaway container
|
||||
# `prowlarr-probe` with a throwaway volume `prowlarr-probe-config`; both removed at the end. Swap is off on the bench.
|
||||
set -u
|
||||
IMG=$1; C=prowlarr-probe; V=prowlarr-probe-config
|
||||
docker rm -f $C >/dev/null 2>&1; docker volume rm $V >/dev/null 2>&1
|
||||
echo "== image"; docker pull -q $IMG; docker image inspect $IMG -f 'id={{.Id}} digest={{index .RepoDigests 0}} size={{.Size}} arch={{.Architecture}}'
|
||||
echo "== tools in the image (one per run)"
|
||||
for t in curl wget sh bash python3 node; do echo "$t: $(docker run --rm --entrypoint sh $IMG -c "command -v $t" 2>/dev/null)"; done
|
||||
echo "== the service's run script (linuxserver s6)"; docker run --rm --entrypoint sh $IMG -c 'cat /etc/s6-overlay/s6-rc.d/svc-prowlarr/run 2>/dev/null; ls /etc/s6-overlay/s6-rc.d/ | grep -i prowlarr'
|
||||
docker volume create $V >/dev/null
|
||||
CID=$(docker create --name $C -e TZ=Europe/Budapest -e PUID=1000 -e PGID=1000 -e UMASK=002 --memory 512m -v $V:/config $IMG)
|
||||
docker start $C >/dev/null; T0=$(date +%s)
|
||||
CG=$(find /sys/fs/cgroup -type d -name "*$CID*" 2>/dev/null | head -1)
|
||||
echo "== memory from birth (cgroup $CG), every 2 s for 150 s"
|
||||
peak=0; for i in $(seq 1 75); do a=$(awk '$1=="anon"{print $2}' $CG/memory.stat 2>/dev/null); [ -n "$a" ] && [ "$a" -gt "$peak" ] && peak=$a; sleep 2; done
|
||||
echo "peak anon $((peak/1048576)) MiB; oom_kill $(awk '$1=="oom_kill"{print $2}' $CG/memory.events); restarts $(docker inspect $C -f '{{.RestartCount}}'); health-like: $(docker exec $C curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:9696/ping)"
|
||||
echo "== process list"; docker exec $C ps -o pid,user,args | head -12
|
||||
echo "== config.xml after the first start (ApiKey redacted)"; docker exec $C cat /config/config.xml | sed -E 's#<ApiKey>[^<]+#<ApiKey><redacted>#'
|
||||
K=$(docker exec $C sed -n 's#.*<ApiKey>\([^<]*\)</ApiKey>.*#\1#p' /config/config.xml)
|
||||
echo "== host config through the app's own API (analytics, update, auth)"; docker exec $C curl -s -H "X-Api-Key: $K" http://127.0.0.1:9696/api/v1/config/host | python3 -c "import json,sys; d=json.load(sys.stdin); print({k:d.get(k) for k in ('analyticsEnabled','updateAutomatically','updateMechanism','authenticationMethod','authenticationRequired','bindAddress','port','proxyEnabled','logLevel')})" 2>/dev/null || echo "(no python3 in the bench shell? raw:)"
|
||||
echo "== open TCP connections from the container (after 150 s)"; docker exec $C sh -c 'cat /proc/net/tcp /proc/net/tcp6 2>/dev/null | awk "NR>1 && \$4==\"01\" {print \$3}" | sort -u'
|
||||
echo "== first-start log (60 lines)"; docker logs $C 2>&1 | head -60 | sed -E 's#[A-Fa-f0-9]{32}#<hex32>#g'
|
||||
echo "== files the app wrote under /config"; docker exec $C sh -c 'find /config -maxdepth 2 | head -30'
|
||||
docker rm -f $C >/dev/null; docker volume rm $V >/dev/null; echo "== removed: $(docker ps -aq -f name=$C | wc -l) containers, $(docker volume ls -q -f name=$V | wc -l) volumes"
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
"""repoint.py mirror|drill|restore|status — point the Tester 1 box at the drill catalog WITHOUT a credential (R-992).
|
||||
|
||||
WHY A LOCAL MIRROR. `09` §6.5's route needs a catalog credential on the box: the drill repo is private (R-992). This
|
||||
session could not mint a READ-ONLY one — the Gitea credential on DooPlex is itself a token, and Gitea answers 403 to a
|
||||
token asking to list or create tokens (measured 2026-10-14) — and the night of 2026-10-06 put the admin WRITE token
|
||||
into the box's controller.yaml, which this task forbids. The cache-staging workaround of 2026-10-12 does not hold for a
|
||||
test that lasts days: every sync (and every controller start) re-applies the live catalog over the staged templates
|
||||
and over the installed apps' compose files (Syncer.copyTemplates, no deployed check).
|
||||
|
||||
So the drill catalog is MIRRORED onto the box: a bare git repository inside the controller's own data volume, and
|
||||
`git.repo_url: file:///opt/docker/felhom-controller/drill-catalog.git`. The controller's sync runs exactly as for a
|
||||
remote (clone/fetch/reset, the R-615 re-clone on a changed URL); no secret is on the box. DooPlex updates the mirror
|
||||
from the drill repo with a git bundle (`mirror`). The drill repo on Gitea stays the record.
|
||||
|
||||
SC=~/.felhom-tester1 TARGET=tester-1 python3 repoint.py mirror # (re)load the mirror from the drill repo main
|
||||
... repoint.py drill # save controller.yaml (once), set repo_url to the mirror, restart, sync, rescan
|
||||
... repoint.py restore # put the saved controller.yaml back (byte-identical), restart, sync, rescan
|
||||
... repoint.py status
|
||||
"""
|
||||
import os, subprocess, sys, time
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w
|
||||
|
||||
DRILL = "/mnt/5_hdd/felhom.eu/drill/app-catalog-drill"
|
||||
VOL = "/var/lib/docker/volumes/felhom-controller-data/_data" # guest path of the controller's data volume
|
||||
CVOL = "/opt/docker/felhom-controller" # the same, inside the controller container
|
||||
SAVE = f"{VOL}/controller.yaml.pre-prowlarr1015"
|
||||
MIRROR_URL = f"file://{CVOL}/drill-catalog.git"
|
||||
|
||||
|
||||
def status():
|
||||
print(w.guest(f"""grep -nE 'repo_url|sync_interval' {VOL}/controller.yaml; ls -l {SAVE} 2>&1 | tail -1
|
||||
docker exec felhom-controller sh -c 'git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h %s" main 2>&1;
|
||||
git -C {CVOL}/data/catalog-cache log -1 --format="cache HEAD %h %s" 2>&1; git -C {CVOL}/data/catalog-cache remote get-url origin'"""))
|
||||
|
||||
|
||||
def mirror():
|
||||
b = "/tmp/drill-prowlarr.bundle"
|
||||
subprocess.run(["git", "-C", DRILL, "bundle", "create", b, "main"], check=True, capture_output=True)
|
||||
head = subprocess.run(["git", "-C", DRILL, "rev-parse", "--short", "main"], capture_output=True, text=True).stdout.strip()
|
||||
ssh = w.ssh_args()
|
||||
# bundle -> PVE host -> guest -> controller volume; the bare repo is made and fetched BY the controller's own user
|
||||
subprocess.run(["scp", "-q", "-o", "StrictHostKeyChecking=accept-new"] + (["-J", w._T["jump"]] if w._T["jump"] else [])
|
||||
+ [b, f"{w._T['ssh']}:{b}"], check=True)
|
||||
subprocess.run(ssh + [f"pct push {w.GUEST} {b} {VOL}/drill-prowlarr.bundle && rm -f {b}"], check=True)
|
||||
print(w.guest(f"""set -e
|
||||
docker exec felhom-controller sh -c 'test -d {CVOL}/drill-catalog.git || git init -q --bare -b main {CVOL}/drill-catalog.git
|
||||
git -C {CVOL}/drill-catalog.git fetch -q {CVOL}/drill-prowlarr.bundle +main:main && rm -f {CVOL}/drill-prowlarr.bundle
|
||||
git -C {CVOL}/drill-catalog.git log -1 --format="mirror main %h %s" main'"""))
|
||||
print("drill repo main:", head)
|
||||
os.remove(b)
|
||||
|
||||
|
||||
def restart_sync():
|
||||
w.guest("docker restart felhom-controller >/dev/null")
|
||||
for _ in range(60):
|
||||
time.sleep(3)
|
||||
try:
|
||||
w.login()
|
||||
break
|
||||
except SystemExit:
|
||||
continue
|
||||
w.sync_rescan()
|
||||
time.sleep(3)
|
||||
print(w.guest("docker logs --since 3m felhom-controller 2>&1 | grep -E '\\[sync\\]' | grep -v DEBUG | tail -8"))
|
||||
|
||||
|
||||
def drill():
|
||||
print(w.guest(f"""set -e
|
||||
test -f {SAVE} || cp -p {VOL}/controller.yaml {SAVE}
|
||||
sed -i -E 's#^(\\s+repo_url: ).*$#\\1{MIRROR_URL}#' {VOL}/controller.yaml
|
||||
grep -n 'repo_url' {VOL}/controller.yaml; diff {SAVE} {VOL}/controller.yaml || true"""))
|
||||
restart_sync()
|
||||
status()
|
||||
|
||||
|
||||
def restore():
|
||||
print(w.guest(f"""set -e
|
||||
cp -p {SAVE} {VOL}/controller.yaml
|
||||
cmp {SAVE} {VOL}/controller.yaml && echo RESTORED-IDENTICAL; grep -n repo_url {VOL}/controller.yaml"""))
|
||||
restart_sync()
|
||||
status()
|
||||
|
||||
|
||||
{"mirror": mirror, "drill": drill, "restore": restore, "status": status}[sys.argv[1]]()
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
"""walk_9201_link.py — the read-back on demo-hp 9201 from the LIVE catalog after the publish (R-1048, brief Part D3).
|
||||
|
||||
Runs ON DOOPLEX with TARGET=9201, SC=<0600 dir holding .ctlpw>, EV=<evidence dir>. Presses only what a person presses:
|
||||
POST /api/sync, the deploy wizard's POST /api/stacks/<n>/deploy, the dashboard's „Bekötés most" (POST
|
||||
/api/storage/media/wire), stop + remove KEEPING data. Reads Prowlarr's own API inside its container with the key from
|
||||
its own config.xml (never printed), exactly as the box's wiring does.
|
||||
|
||||
The two orders the controller's code implies (mediawire runs when a media_library app comes up; Prowlarr has no marker):
|
||||
B Sonarr first, Prowlarr after -> expected NO link by itself; „Bekötés most" makes it
|
||||
A Radarr after Prowlarr -> expected the link by itself, ~60 s after Radarr comes up
|
||||
Then: Prowlarr's own connection test for each link, and its sync command to completion.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w # noqa: E402
|
||||
|
||||
EV = os.environ["EV"]
|
||||
os.makedirs(EV, exist_ok=True)
|
||||
LOG = open(os.path.join(EV, "link.txt"), "a", buffering=1)
|
||||
TO = "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
HDD = "/mnt/felhom-drives/hdd_1"
|
||||
RES = {}
|
||||
_lib_say = w.say
|
||||
|
||||
|
||||
def say(*a):
|
||||
_lib_say(*a)
|
||||
LOG.write(" ".join(str(x) for x in a) + "\n")
|
||||
|
||||
|
||||
w.say = say
|
||||
|
||||
|
||||
def papi(path, body=None, method=None):
|
||||
"""Prowlarr's own API from inside its container (the key read from its config.xml at use, never printed)."""
|
||||
m = method or ("POST" if body is not None else "GET")
|
||||
data = json.dumps(body) if body is not None else ""
|
||||
script = ("K=$(sed -n 's:.*<ApiKey>\\(.*\\)</ApiKey>.*:\\1:p' /config/config.xml); "
|
||||
f"curl -s -o /tmp/pb.json -w '%{{http_code}}' -X {m} -H \"X-Api-Key: $K\" -H 'Content-Type: application/json' "
|
||||
f"--data-binary @- http://127.0.0.1:9696/api/v1{path}; echo; cat /tmp/pb.json")
|
||||
out = w.guest(f"docker exec -i prowlarr sh -c {json.dumps(script)} <<'EOF'\n{data}\nEOF")
|
||||
code, _, body_ = out.partition("\n")
|
||||
try:
|
||||
return code.strip(), json.loads(body_) if body_.strip() else None
|
||||
except Exception:
|
||||
return code.strip(), body_[:300]
|
||||
|
||||
|
||||
def apps():
|
||||
c, d = papi("/applications")
|
||||
return [(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 (d or [])] if c == "200" else c
|
||||
|
||||
|
||||
def wiring_lines(since):
|
||||
return w.guest(f"docker logs --since {since} felhom-controller 2>&1 | grep -E '\\[media\\] wiring|\\[mediawire\\]' | cut -c1-400").strip()
|
||||
|
||||
|
||||
def install(name, values):
|
||||
if w.stack(name).get("deployed"):
|
||||
sys.exit(say(f"{name} is already installed on 9201 — STOP, a household's app is never reused") or 1)
|
||||
code, d = w.ctl("POST", f"/api/stacks/{name}/deploy", {"values": values})
|
||||
say(f" deploy {name} {json.dumps(values)} -> {code} {json.dumps(d, ensure_ascii=False)[:120]}")
|
||||
w.DEPLOYED_THIS_RUN.add(name)
|
||||
for _ in range(90):
|
||||
time.sleep(5)
|
||||
st = w.stack(name)
|
||||
if st.get("deployed") and (st.get("app_config") or {}).get("pinned_images") and st.get("state") == "running":
|
||||
say(f" {name}: deployed, running, pinned={(st.get('app_config') or {}).get('pinned_images')}")
|
||||
return True
|
||||
sys.exit(say(f" {name} never became running — STOP") or 1)
|
||||
|
||||
|
||||
def wait_healthy(c, tries=60):
|
||||
for _ in range(tries):
|
||||
if w.guest(f"docker inspect {c} -f '{{{{.State.Health.Status}}}}'").strip() == "healthy":
|
||||
return True
|
||||
time.sleep(5)
|
||||
return False
|
||||
|
||||
|
||||
def main():
|
||||
w.login()
|
||||
t0 = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
for a in ("prowlarr", "sonarr", "radarr"):
|
||||
if w.stack(a).get("deployed"):
|
||||
sys.exit(say(f"{a} is installed on 9201 — STOP") or 1)
|
||||
say("[0] controller: " + w.guest("cat /etc/felhom-controller-image").strip())
|
||||
w.sync_rescan(expect_app="prowlarr", expect_ref=TO)
|
||||
say("[0] live catalog on the box: " + w.guest("docker exec felhom-controller sh -c 'git -C /opt/docker/felhom-controller/data/catalog-cache log -1 --format=\"%h %s\"; git -C /opt/docker/felhom-controller/data/catalog-cache remote get-url origin'").strip().replace("\n", " | "))
|
||||
say("[0] prowlarr template on the box: " + w.guest("wc -c /opt/docker/stacks/prowlarr/.felhom.yml; grep -E 'image:' /opt/docker/stacks/prowlarr/docker-compose.yml; grep -E '^setup_gate' /opt/docker/stacks/prowlarr/.felhom.yml").strip().replace("\n", " | "))
|
||||
|
||||
# ── order B: Sonarr first ──
|
||||
install("sonarr", {"DOMAIN": w.DOMAIN, "SUBDOMAIN": "sonarr", "HDD_PATH": HDD})
|
||||
wait_healthy("sonarr")
|
||||
time.sleep(75) # the wiring runs 60 s after the last media app came up
|
||||
say("[B1] wiring after Sonarr came up:\n" + wiring_lines(t0))
|
||||
tP = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
install("prowlarr", {"DOMAIN": w.DOMAIN, "SUBDOMAIN": "prowlarr"})
|
||||
wait_healthy("prowlarr")
|
||||
say("[B2] prowlarr first-start line: " + w.guest("docker logs prowlarr 2>&1 | grep -m1 felhom").strip())
|
||||
time.sleep(150)
|
||||
b_apps = apps()
|
||||
b_wire = wiring_lines(tP)
|
||||
say(f"[B3] 150 s after Prowlarr came up (Sonarr was there first): Prowlarr's Apps = {b_apps}")
|
||||
say(f"[B3] wiring runs since Prowlarr's install: {b_wire or '(none)'}")
|
||||
RES["order_B_apps_without_press"] = b_apps
|
||||
RES["order_B_wiring_runs"] = b_wire
|
||||
|
||||
# ── the household's „Bekötés most" ──
|
||||
code, d = w.ctl("POST", "/api/storage/media/wire", {})
|
||||
pr = [r for r in ((d or {}).get("data") or []) if isinstance(r, dict) and r.get("app") == "prowlarr"]
|
||||
say(f"[C1] „Bekötés most” (POST /api/storage/media/wire) -> {code}; prowlarr result: {json.dumps(pr, ensure_ascii=False)}")
|
||||
c_apps = apps()
|
||||
say(f"[C2] Prowlarr's Apps after the press: {c_apps}")
|
||||
RES["after_press_apps"] = c_apps
|
||||
|
||||
# ── order A: Radarr after Prowlarr ──
|
||||
tR = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
install("radarr", {"DOMAIN": w.DOMAIN, "SUBDOMAIN": "radarr", "HDD_PATH": HDD})
|
||||
wait_healthy("radarr")
|
||||
a_apps = None
|
||||
for i in range(30):
|
||||
time.sleep(10)
|
||||
a_apps = apps()
|
||||
if isinstance(a_apps, list) and any(n == "Radarr" for n, _, _ in a_apps):
|
||||
say(f"[A1] Radarr appeared in Prowlarr's Apps by itself, ~{(i + 1) * 10} s after Radarr ran")
|
||||
break
|
||||
say(f"[A2] Prowlarr's Apps: {a_apps}")
|
||||
say("[A2] wiring runs since Radarr's install:\n" + wiring_lines(tR))
|
||||
RES["order_A_apps"] = a_apps
|
||||
|
||||
# ── the links work: Prowlarr's own test per app, then its sync command to completion ──
|
||||
c, full = papi("/applications")
|
||||
for a in (full or []):
|
||||
tc, td = papi("/applications/test", a)
|
||||
say(f"[D1] Prowlarr's connection test for {a.get('name')} ({a.get('implementation')}, syncLevel {a.get('syncLevel')}) -> {tc} {str(td)[:160] if td else ''}")
|
||||
RES[f"test_{a.get('name')}"] = tc
|
||||
c, cmd = papi("/command", {"name": "ApplicationIndexerSync"})
|
||||
cid = (cmd or {}).get("id") if isinstance(cmd, dict) else None
|
||||
say(f"[D2] sync command ApplicationIndexerSync -> {c} id={cid}")
|
||||
st = None
|
||||
for _ in range(30):
|
||||
time.sleep(2)
|
||||
c, cd = papi(f"/command/{cid}")
|
||||
st = (cd or {}).get("status") if isinstance(cd, dict) else cd
|
||||
if st in ("completed", "failed", "aborted"):
|
||||
break
|
||||
say(f"[D2] sync command status: {st}")
|
||||
RES["sync_status"] = st
|
||||
say("[D3] Prowlarr's own log of the sync: " + w.guest(
|
||||
"docker exec prowlarr sh -c \"grep -h -iE 'ApplicationIndexerSync|Syncing|sonarr:8989|radarr:7878' /config/logs/prowlarr.txt | tail -6\"").strip().replace("\n", " | ")[:900])
|
||||
say("[D4] Sonarr's and Radarr's indexer lists (Prowlarr has no indexer yet, so both empty is the expected answer): "
|
||||
+ w.guest("for a in sonarr:8989:v3 radarr:7878:v3; do n=${a%%:*}; r=${a#*:}; p=${r%%:*}; v=${r#*:}; "
|
||||
"docker exec $n sh -c \"K=\\$(sed -n 's:.*<ApiKey>\\(.*\\)</ApiKey>.*:\\1:p' /config/config.xml); "
|
||||
"curl -s -H \\\"X-Api-Key: \\$K\\\" http://127.0.0.1:$p/api/$v/indexer\" | head -c 200; echo \" <- $n\"; done").strip().replace("\n", " | "))
|
||||
|
||||
# ── remove all three, KEEPING data (the brief: without „delete data") ──
|
||||
for a in ("radarr", "prowlarr", "sonarr"):
|
||||
c1, _ = w.ctl("POST", f"/api/stacks/{a}/stop")
|
||||
for _ in range(24):
|
||||
time.sleep(5)
|
||||
if w.stack(a).get("state") != "running":
|
||||
break
|
||||
code, d = w.ctl("POST", f"/api/stacks/{a}/remove", {"remove_hdd_data": False, "remove_backups": False})
|
||||
say(f"[X] {a}: stop {c1}, remove keeping data -> {code} {json.dumps(d, ensure_ascii=False)[:260]}")
|
||||
time.sleep(5)
|
||||
say("[X] left: " + w.guest("echo containers=$(docker ps -aq -f name='^(prowlarr|sonarr|radarr)$' | wc -l) "
|
||||
"volumes=$(docker volume ls -q | grep -cE '^(prowlarr|sonarr|radarr)_')").strip())
|
||||
json.dump(RES, open(os.path.join(EV, "link-results.json"), "w"), indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env python3
|
||||
"""walk_prowlarr.py — Prowlarr on scratch guest 9202 THROUGH THE PRODUCT, from the drill catalog (R-1048, 2026-10-15).
|
||||
|
||||
Runs ON DOOPLEX with TARGET=9202 and SC=<0600 dir holding .ctlpw>. 9202 must already be pointed at the drill mirror,
|
||||
whose prowlarr template is the live candidate at the PREVIOUS image (version-2.5.2.5491). Presses only what a person
|
||||
presses (box_walk.py): deploy, the setup gate as household and stranger, Prowlarr's own first-admin and sign-in routes
|
||||
through traefik over https, „Kész", „Mentés most", the drill bump + the guarded Update, remove.
|
||||
|
||||
Closes NEW-APP-CHECKLIST 3.1 3.3 3.5 3.6 3.9 3.10 2.5 2.6 4.3 6.2(box) 6.3 9.2. Writes the evidence to EV and the box
|
||||
verdict to EV/prowlarr/box-verdict-prowlarr.json (the ladder writer's input). The household password it creates is kept
|
||||
only in SC (0600) for the life of the run; the app's API key is never printed.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w # noqa: E402
|
||||
import upgrade_fixtures_box as fx # noqa: E402
|
||||
|
||||
EV = os.environ["EV"]
|
||||
APP, SUB = "prowlarr", "prowlarr"
|
||||
FROM = "lscr.io/linuxserver/prowlarr:version-2.5.2.5491"
|
||||
TO = "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
os.makedirs(os.path.join(EV, APP), exist_ok=True)
|
||||
LOG = open(os.path.join(EV, "walk.txt"), "a", buffering=1)
|
||||
RES = {}
|
||||
|
||||
|
||||
_lib_say = w.say
|
||||
|
||||
|
||||
def say(*a):
|
||||
_lib_say(*a)
|
||||
LOG.write(" ".join(str(x) for x in a) + "\n")
|
||||
|
||||
|
||||
w.say = say # the library's own lines land in the same record (the original is kept above — no recursion)
|
||||
|
||||
|
||||
def stranger(path, method="GET", data=None, accept="application/json", extra=()):
|
||||
"""A visitor with NO dashboard session and NO gate cookie, on the app's public name over https."""
|
||||
args = ["curl", "-sSk", "--max-time", "20", "-o", "/tmp/pw-body.txt", "-D", "-", "-H", f"Host: {SUB}.{w.DOMAIN}",
|
||||
"-H", f"Accept: {accept}"] + list(extra)
|
||||
if method != "GET":
|
||||
args += ["-X", method]
|
||||
if data is not None:
|
||||
args += ["--data-binary", "@-"]
|
||||
r = w.sh(args + [f"{w.BASE}{path}"], inp=data)
|
||||
head = r.stdout or ""
|
||||
st = re.match(r"HTTP/\S+ (\d+)", head)
|
||||
loc = re.search(r"(?im)^location:\s*(\S+)", head)
|
||||
body = w.sh(["head", "-c", "200", "/tmp/pw-body.txt"]).stdout.replace("\n", " ")
|
||||
return (st.group(1) if st else "000"), (loc.group(1) if loc else ""), body, head
|
||||
|
||||
|
||||
def household(path, method="GET", body=None, headers=()):
|
||||
ext = []
|
||||
for h in headers:
|
||||
ext += ["-H", h]
|
||||
if body is not None:
|
||||
ext += ["-H", "Content-Type: application/json"]
|
||||
rc, code, out = w.app_curl(SUB, path, *ext, method=method, data=json.dumps(body) if body is not None else None)
|
||||
return code, out
|
||||
|
||||
|
||||
def main():
|
||||
w.login()
|
||||
st = w.stack(APP)
|
||||
if st.get("deployed"):
|
||||
sys.exit(say("prowlarr is installed on 9202 — STOP, not a fresh install") or 1)
|
||||
|
||||
# ── 3.5 + 4.3: install, and a stranger polls the public name once a second through the install window ──
|
||||
t0 = time.time()
|
||||
code, d = w.ctl("POST", f"/api/stacks/{APP}/deploy", {"values": {"DOMAIN": w.DOMAIN, "SUBDOMAIN": SUB}})
|
||||
say(f"[1] POST /api/stacks/{APP}/deploy -> {code} {json.dumps(d, ensure_ascii=False)[:160]}")
|
||||
w.DEPLOYED_THIS_RUN.add(APP)
|
||||
seen = {}
|
||||
for i in range(90):
|
||||
for p in ("/", "/initialize.json", "/api/v1/system/status"):
|
||||
c, loc, body, _ = stranger(p, accept="text/html" if p == "/" else "application/json")
|
||||
key = f"{p} -> {c} {('loc=' + loc[:60]) if loc else ''} {'API-KEY-IN-BODY' if 'apiKey' in body else ''}".strip()
|
||||
seen[key] = seen.get(key, 0) + 1
|
||||
s = w.stack(APP)
|
||||
if s.get("deployed") and s.get("state") == "running" and i > 20:
|
||||
break
|
||||
time.sleep(1)
|
||||
say(f"[1] install window, a stranger on the public name ({round(time.time() - t0)} s, distinct answers):")
|
||||
for k, n in sorted(seen.items()):
|
||||
say(f" {n:3d}x {k}")
|
||||
RES["install_window"] = seen
|
||||
s = w.stack(APP)
|
||||
say(f"[1] state={s.get('state')} health={s.get('health')} restarts: "
|
||||
+ w.guest("docker inspect prowlarr -f '{{.RestartCount}} started={{.State.StartedAt}} health={{.State.Health.Status}}'").strip())
|
||||
say("[1] the first-start seed line: " + w.guest("docker logs prowlarr 2>&1 | grep -m1 felhom").strip())
|
||||
say("[1] config.xml (key redacted): " + w.guest("docker exec prowlarr cat /config/config.xml | sed -E 's#<ApiKey>[^<]+#<ApiKey><redacted>#' | tr '\\n' ' '").strip())
|
||||
|
||||
# ── 3.1: the household reaches the first-run screen through the gate; its key comes from the app's own page ──
|
||||
code, out = household("/initialize.json")
|
||||
m = re.search(r'"?apiKey"?\s*:\s*"([0-9a-fA-F]{20,})"', out)
|
||||
say(f"[2] household GET /initialize.json through the gate -> {code}, carries the API key: {bool(m)}")
|
||||
key = m.group(1) if m else ""
|
||||
code, out = household("/api/v1/config/host", headers=(f"X-Api-Key: {key}",))
|
||||
hc = json.loads(out) if code == "200" else {}
|
||||
say(f"[2] GET /api/v1/config/host -> {code}: authenticationMethod={hc.get('authenticationMethod')} "
|
||||
f"authenticationRequired={hc.get('authenticationRequired')} analyticsEnabled={hc.get('analyticsEnabled')}")
|
||||
user, pw = "felhom-test", "Pw-" + secrets.token_urlsafe(14)
|
||||
open(os.path.join(w.SC, "prowlarr-household.json"), "w").write(json.dumps({"user": user, "password": pw}))
|
||||
os.chmod(os.path.join(w.SC, "prowlarr-household.json"), 0o600)
|
||||
hc.update({"authenticationMethod": "forms", "username": user, "password": pw, "passwordConfirmation": pw})
|
||||
code, out = household("/api/v1/config/host", method="PUT", body=hc, headers=(f"X-Api-Key: {key}",))
|
||||
say(f"[2] the household makes its first account (PUT /api/v1/config/host, forms) -> {code}")
|
||||
RES["first_admin"] = code
|
||||
time.sleep(8)
|
||||
w.wait_app(SUB, "/ping", want=("200",), tries=24)
|
||||
|
||||
# ── 3.9: sign in the way the browser does, through traefik over https (still behind the gate) ──
|
||||
for label, p in (("right", pw), ("wrong", "nope-" + secrets.token_hex(4))):
|
||||
rc, code, out = w.app_curl(SUB, "/login?returnUrl=%2F", "-H", "Content-Type: application/x-www-form-urlencoded",
|
||||
"-D", "-", method="POST", data=f"username={user}&password={p}&rememberMe=on")
|
||||
loc = re.search(r"(?im)^location:\s*(\S+)", out)
|
||||
ck = re.search(r"(?im)^set-cookie:\s*([A-Za-z]+Auth)=", out)
|
||||
say(f"[3] sign in ({label} password) POST /login -> {code} loc={loc.group(1) if loc else '-'} auth-cookie={ck.group(1) if ck else 'none'}")
|
||||
RES[f"signin_{label}"] = [code, loc.group(1) if loc else "", bool(ck)]
|
||||
|
||||
# ── 6.1 C1 + 2.5: seed through the app's own API, read back, back it up through the product ──
|
||||
fxp = fx.FIXTURES[APP]
|
||||
tok = fxp.seed(w, SUB, say)
|
||||
ok1 = bool(tok) and fxp.verify(w, SUB, tok, say)
|
||||
say(f"[4] seed {tok} read back before the update: {ok1}")
|
||||
bk = w.backup_now(APP)
|
||||
say(f"[4] „Mentés most” -> {json.dumps(bk, ensure_ascii=False)[:200]}")
|
||||
|
||||
# ── 3.3: „Kész" opens the gate; then a stranger meets the APP's own sign-in, never the app ──
|
||||
code, d = w.ctl("POST", f"/apps/{APP}/setup-gate/open")
|
||||
say(f"[5] the household's „Kész, beállítottam” -> {code} {json.dumps(d, ensure_ascii=False)[:120]}")
|
||||
time.sleep(5)
|
||||
for p, acc in (("/", "text/html"), ("/initialize.json", "application/json"), ("/api/v1/system/status", "application/json"),
|
||||
("/api/v1/indexer", "application/json")):
|
||||
c, loc, body, _ = stranger(p, accept=acc)
|
||||
say(f"[5] stranger after the gate opened: GET {p} -> {c} {('loc=' + loc[:70]) if loc else ''} apiKey-in-body={'apiKey' in body}")
|
||||
RES[f"stranger_open_{p}"] = [c, loc, "apiKey" in body]
|
||||
|
||||
# ── 3.6 + 3.10: six wrong passwords from a stranger; then the household; and what address the app logged ──
|
||||
for i in range(6):
|
||||
c, loc, _b, _ = stranger("/login?returnUrl=%2F", method="POST", data=f"username={user}&password=wrong{i}",
|
||||
accept="text/html", extra=("-H", "Content-Type: application/x-www-form-urlencoded"))
|
||||
say(f"[6] stranger wrong password #{i + 1} -> {c} loc={loc[:60]}")
|
||||
c, loc, _b, head = stranger("/login?returnUrl=%2F", method="POST", data=f"username={user}&password={pw}",
|
||||
accept="text/html", extra=("-H", "Content-Type: application/x-www-form-urlencoded"))
|
||||
say(f"[6] the household's right password right after (same address) -> {c} loc={loc[:60]} "
|
||||
f"auth-cookie={'yes' if re.search(r'(?im)^set-cookie:.*Auth=', head) else 'no'}")
|
||||
say("[6] what the app logged for the failures (address): "
|
||||
+ w.guest("docker exec prowlarr sh -c \"grep -h -i 'auth-failure\\|Auth-' /config/logs/prowlarr*.txt | tail -3\"").strip().replace("\n", " | ")[:600])
|
||||
|
||||
# ── 6.2/6.3 box: the drill bump and the product's guarded Update; the seed read back after ──
|
||||
# the drill bump, staged by explicit path (box_walk.drill_bump runs `git add -A`, which this task forbids)
|
||||
D = w.DRILL
|
||||
comp, fy = f"{D}/templates/{APP}/docker-compose.yml", f"{D}/templates/{APP}/.felhom.yml"
|
||||
w.sh(["git", "-C", D, "pull", "-q", "--rebase", "origin", "main"], timeout=120)
|
||||
c_ = open(comp).read()
|
||||
if f"image: {FROM}" not in c_:
|
||||
sys.exit(say(f"[7] FROM {FROM} not in the drill compose — STOP") or 1)
|
||||
open(comp, "w").write(c_.replace(f"image: {FROM}", f"image: {TO}"))
|
||||
# FIXED after run 1: this line used to be `open(fy, "w").write(re.sub(..., open(fy).read(), ...))`, which truncates the
|
||||
# file BEFORE it is read — run 1's bump commit (drill f2b0cc1) emptied the drill's .felhom.yml, so run 1's Update ran
|
||||
# without the app's metadata. Run 3 (walk_restore.py, box/run3/) re-proves the step with the full file.
|
||||
fy_text = open(fy).read()
|
||||
open(fy, "w").write(re.sub(r'^catalog_since:.*$', 'catalog_since: "' + time.strftime("%Y-%m-%d") + '"', fy_text, count=1, flags=re.M))
|
||||
w.sh(["git", "-C", D, "add", f"templates/{APP}/docker-compose.yml", f"templates/{APP}/.felhom.yml"])
|
||||
w.sh(["git", "-C", D, "commit", "-q", "-m", f"DRILL {APP}: {FROM} -> {TO} (R-1048 box proof)"])
|
||||
r_ = w.sh(["git", "-C", D, "push", "-q", "origin", "main"], timeout=120)
|
||||
say(f"[7] drill commit {w.sh(['git', '-C', D, 'rev-parse', '--short=12', 'HEAD']).stdout.strip()}: {FROM} -> {TO} (push rc={r_.returncode})")
|
||||
# the mirror on 9202 is what the box reads: reload it from the drill repo
|
||||
import subprocess
|
||||
subprocess.run([sys.executable, os.path.join(os.path.dirname(os.path.abspath(__file__)), "repoint9202.py"), "mirror"], check=True,
|
||||
env=dict(os.environ))
|
||||
w.sync_rescan(expect_app=APP, expect_ref=TO)
|
||||
say(f"[7] badges: {json.dumps(w.badges(APP), ensure_ascii=False)[:300]}")
|
||||
up = w.press_update(APP)
|
||||
say(f"[7] guarded Update: {json.dumps(up, ensure_ascii=False)[:400]}")
|
||||
ok2 = bool(tok) and fxp.verify(w, SUB, tok, say)
|
||||
obs = w.observables(APP)
|
||||
say(f"[7] after: {json.dumps(obs, ensure_ascii=False)[:400]}")
|
||||
s = w.stack(APP)
|
||||
healthy = s.get("state") == "running"
|
||||
verdict = {"app": APP, "venue": "box 9202 (drill catalog, controller 0.304.0), the product's guarded Update",
|
||||
"from": {APP: FROM}, "to": {APP: TO},
|
||||
"verdict": "proven" if (ok1 and ok2 and up.get("final_phase") == "done" and healthy) else "failed",
|
||||
"seed_read_before": ok1, "seed_read_after": ok2, "healthy_after": healthy,
|
||||
"duration_s": up.get("duration_s"), "final_phase": up.get("final_phase"),
|
||||
"measured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
"evidence": "felhom.eu/documentation/audits/prowlarr-2026-10-15/box/walk.txt"}
|
||||
json.dump(verdict, open(os.path.join(EV, APP, "box-verdict-prowlarr.json"), "w"), indent=2)
|
||||
say(f"[8] box verdict {verdict['verdict']}")
|
||||
|
||||
# ── 2.6: remove through the product; nothing left ──
|
||||
if os.environ.get("KEEP") != "1":
|
||||
w.remove(APP)
|
||||
say("[9] after remove: " + w.guest("echo containers=$(docker ps -aq -f name=^prowlarr$ | wc -l) volumes=$(docker volume ls -q | grep -c prowlarr) stackdir=$(ls -d /opt/docker/stacks/prowlarr 2>/dev/null | wc -l)").strip())
|
||||
json.dump(RES, open(os.path.join(EV, "walk-results.json"), "w"), indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
"""walk_restore.py — NEW-APP-CHECKLIST 2.5 for Prowlarr on scratch guest 9202: seed -> backup -> remove -> restore ->
|
||||
read back, THROUGH THE PRODUCT (R-1048, 2026-10-15, second 9202 run).
|
||||
|
||||
The box has no per-app „Mentés most" (R-648: the only backup press is whole-box and is never pressed from a drill), so
|
||||
the per-app backup is the one the guarded Update takes in its `backing-up` phase — the same route as grocy's and
|
||||
lubelogger's restore records. Runs ON DOOPLEX with TARGET=9202, SC=<0600 dir holding .ctlpw>, EV=<evidence dir>; 9202
|
||||
must already read the drill mirror, whose prowlarr template is at FROM. Presses: deploy, the drill bump + Update,
|
||||
remove KEEPING the backups, the household's restore button (POST /backup/restore), remove with the backups.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w # noqa: E402
|
||||
import upgrade_fixtures_box as fx # noqa: E402
|
||||
|
||||
EV = os.environ["EV"]
|
||||
APP, SUB = "prowlarr", "prowlarr"
|
||||
FROM = "lscr.io/linuxserver/prowlarr:version-2.5.2.5491"
|
||||
TO = "lscr.io/linuxserver/prowlarr:version-2.6.5.5623"
|
||||
TOOLS = os.path.dirname(os.path.abspath(__file__))
|
||||
LOG = open(os.path.join(EV, "restore.txt"), "a", buffering=1)
|
||||
_lib_say = w.say
|
||||
|
||||
|
||||
def say(*a):
|
||||
_lib_say(*a)
|
||||
LOG.write(" ".join(str(x) for x in a) + "\n")
|
||||
|
||||
|
||||
w.say = say
|
||||
|
||||
|
||||
def drill_set(ref, why):
|
||||
"""Point the drill template at `ref`, staged by explicit path, then reload the 9202 mirror."""
|
||||
D = w.DRILL
|
||||
comp, fy = f"{D}/templates/{APP}/docker-compose.yml", f"{D}/templates/{APP}/.felhom.yml"
|
||||
w.sh(["git", "-C", D, "pull", "-q", "--rebase", "origin", "main"], timeout=120)
|
||||
c_ = open(comp).read()
|
||||
other = TO if ref == FROM else FROM
|
||||
if f"image: {ref}" not in c_:
|
||||
open(comp, "w").write(c_.replace(f"image: {other}", f"image: {ref}"))
|
||||
w.sh(["git", "-C", D, "add", f"templates/{APP}/docker-compose.yml", f"templates/{APP}/.felhom.yml"])
|
||||
w.sh(["git", "-C", D, "commit", "-q", "-m", f"DRILL {APP}: {why} -> {ref} (R-1048, checklist 2.5)"])
|
||||
r_ = w.sh(["git", "-C", D, "push", "-q", "origin", "main"], timeout=120)
|
||||
say(f"drill commit {w.sh(['git', '-C', D, 'rev-parse', '--short=12', 'HEAD']).stdout.strip()}: -> {ref} (push rc={r_.returncode})")
|
||||
subprocess.run([sys.executable, os.path.join(TOOLS, "repoint9202.py"), "mirror"], check=True, env=dict(os.environ))
|
||||
|
||||
|
||||
def main():
|
||||
w.login()
|
||||
if w.stack(APP).get("deployed"):
|
||||
sys.exit(say("prowlarr is installed on 9202 — STOP, not a fresh install") or 1)
|
||||
drill_set(FROM, "back to the previous image for a step")
|
||||
w.sync_rescan(expect_app=APP, expect_ref=FROM)
|
||||
code, d = w.ctl("POST", f"/api/stacks/{APP}/deploy", {"values": {"DOMAIN": w.DOMAIN, "SUBDOMAIN": SUB}})
|
||||
say(f"[1] deploy -> {code} {json.dumps(d, ensure_ascii=False)[:120]}")
|
||||
w.DEPLOYED_THIS_RUN.add(APP)
|
||||
for _ in range(60):
|
||||
s = w.stack(APP)
|
||||
if s.get("deployed") and s.get("state") == "running":
|
||||
break
|
||||
time.sleep(3)
|
||||
w.wait_app(SUB, "/ping", want=("200",), tries=40)
|
||||
say("[1] through traefik: " + w.guest(f"curl -sk -o /dev/null -w '%{{http_code}}' -H 'Host: {SUB}.{w.DOMAIN}' https://127.0.0.1/ping").strip()
|
||||
+ " (gated: 302 to the gate is the healthy answer for a stranger)")
|
||||
say("[1] stack .felhom.yml bytes: " + w.guest(f"wc -c < /opt/docker/stacks/{APP}/.felhom.yml").strip())
|
||||
say("[1] running: " + w.guest("docker inspect prowlarr -f '{{.Config.Image}} health={{.State.Health.Status}}'").strip())
|
||||
|
||||
fxp = fx.FIXTURES[APP]
|
||||
tok = fxp.seed(w, SUB, say)
|
||||
ok1 = bool(tok) and fxp.verify(w, SUB, tok, say)
|
||||
say(f"[2] seed {tok} read back: {ok1}")
|
||||
say("[2] 2.7 config volume size after the seed: " + w.guest("du -sh /var/lib/docker/volumes/prowlarr_prowlarr_config/_data | cut -f1").strip())
|
||||
say("[2] 4.4 negative control, the same probe on a port nothing serves: rc=" + w.guest("docker exec prowlarr curl -sf -o /dev/null http://127.0.0.1:9697/ping; echo $?").strip()
|
||||
+ " ; the real probe: rc=" + w.guest("docker exec prowlarr curl -sf -o /dev/null http://127.0.0.1:9696/ping; echo $?").strip())
|
||||
say("[2] 1.8 the app's own start lines: " + w.guest("docker logs prowlarr 2>&1 | grep -m2 -E 'Hosting environment|Application started'").strip().replace("\n", " | "))
|
||||
|
||||
drill_set(TO, "the step")
|
||||
w.sync_rescan(expect_app=APP, expect_ref=TO)
|
||||
up = w.press_update(APP)
|
||||
say(f"[3] guarded Update (its backing-up phase is the per-app backup): final={up.get('final_phase')} "
|
||||
f"phases={[p.get('phase') for p in up.get('phases', [])]}")
|
||||
ok2 = bool(tok) and fxp.verify(w, SUB, tok, say)
|
||||
say(f"[3] seed read back after the Update: {ok2}")
|
||||
obs = w.observables(APP)
|
||||
say(f"[3] after: {json.dumps(obs, ensure_ascii=False)[:400]}")
|
||||
s = w.stack(APP)
|
||||
if os.environ.get("VERDICT") == "1":
|
||||
verdict = {"app": APP, "venue": "box 9202 (drill catalog), the product's guarded Update — run 3, the full .felhom.yml",
|
||||
"from": {APP: FROM}, "to": {APP: TO},
|
||||
"verdict": "proven" if (ok1 and ok2 and up.get("final_phase") == "done" and s.get("state") == "running") else "failed",
|
||||
"seed_read_before": ok1, "seed_read_after": ok2, "healthy_after": s.get("state") == "running",
|
||||
"duration_s": up.get("duration_s"), "final_phase": up.get("final_phase"),
|
||||
"measured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
||||
"evidence": "felhom.eu/documentation/audits/prowlarr-2026-10-15/box/run3/restore.txt"}
|
||||
os.makedirs(os.path.join(EV, "..", APP), exist_ok=True)
|
||||
json.dump(verdict, open(os.path.join(EV, "..", APP, "box-verdict-prowlarr.json"), "w"), indent=2)
|
||||
say(f"[3] box verdict {verdict['verdict']}")
|
||||
|
||||
snaps = w.snapshots(APP)
|
||||
say(f"[4] restore points offered BEFORE the remove: {json.dumps(snaps, ensure_ascii=False)[:400]}")
|
||||
c1, d1 = w.ctl("POST", f"/api/stacks/{APP}/stop")
|
||||
say(f"[4] stop -> {c1}")
|
||||
for _ in range(24):
|
||||
time.sleep(5)
|
||||
if w.stack(APP).get("state") != "running":
|
||||
break
|
||||
code, d = w.ctl("POST", f"/api/stacks/{APP}/remove", {"remove_hdd_data": False, "remove_backups": False})
|
||||
say(f"[4] remove KEEPING the backups -> {code} {json.dumps(d, ensure_ascii=False)[:300]}")
|
||||
time.sleep(5)
|
||||
say("[4] left after remove: " + w.guest("echo containers=$(docker ps -aq -f name=^prowlarr$ | wc -l) volumes=$(docker volume ls -q | grep -c prowlarr)").strip())
|
||||
|
||||
rr = w.restore(APP)
|
||||
say(f"[5] restore: {json.dumps({k: rr.get(k) for k in ('ok', 'snapshot_id', 'http', 'seconds', 'state_after', 'hold_after', 'why')}, ensure_ascii=False)}")
|
||||
w.wait_app(SUB, "/ping", want=("200",), tries=40)
|
||||
ok3 = bool(tok) and fxp.verify(w, SUB, tok, say)
|
||||
say(f"[5] 2.5 the seed reads back after remove + restore: {ok3}")
|
||||
say("[5] through traefik after restore: " + w.guest(f"curl -sk -o /dev/null -w '%{{http_code}}' -H 'Host: {SUB}.{w.DOMAIN}' https://127.0.0.1/ping").strip())
|
||||
say("[5] app.yaml env keys after restore: " + w.guest(f"sed -n '/^env:/,/^[a-z]/p' /opt/docker/stacks/{APP}/app.yaml | grep -oE '^ +[A-Z_]+' | paste -sd' '").strip())
|
||||
say("[5] image after restore: " + w.guest("docker inspect prowlarr -f '{{.Config.Image}} health={{.State.Health.Status}}'").strip())
|
||||
|
||||
# teardown through the product, backups too (this is a scratch install)
|
||||
w.remove(APP)
|
||||
say("[9] after remove: " + w.guest("echo containers=$(docker ps -aq -f name=^prowlarr$ | wc -l) volumes=$(docker volume ls -q | grep -c prowlarr)").strip())
|
||||
json.dump({"seed": tok, "seed_before": ok1, "after_update": ok2, "after_restore": ok3,
|
||||
"update_final": up.get("final_phase"), "restore": {k: rr.get(k) for k in ("ok", "snapshot_id", "http", "seconds", "state_after")},
|
||||
"measured_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())},
|
||||
open(os.path.join(EV, "restore-results.json"), "w"), indent=2, ensure_ascii=False)
|
||||
|
||||
|
||||
main()
|
||||
@@ -187,11 +187,11 @@ a backup at the same time can slow it down · **does not fit:** guest < peak. Pe
|
||||
| Household set | 5.9 GB | does not fit | fits well | fits well | fits well |
|
||||
| Household set without Immich | 2.7 GB | fits, but tight | fits well | fits well | fits well |
|
||||
| Immich alone | 3.7 GB | fits, but tight | fits well | fits well | fits well |
|
||||
| All 62 apps | 21.8 GB | does not fit | does not fit | does not fit | fits, but tight |
|
||||
| All 63 apps | 21.9 GB | does not fit | does not fit | does not fit | fits, but tight |
|
||||
<!-- /sizing-verdicts -->
|
||||
|
||||
- **8 GB:** the household set without Immich fits, but tight; Immich alone fits, but tight; the whole household set does not fit.
|
||||
- **16 GB:** the whole household set fits well.
|
||||
- **32 GB:** the household set fits well; all 62 apps at once fit, but tight.
|
||||
- **32 GB:** the household set fits well; all 63 apps at once fit, but tight.
|
||||
|
||||
2026-10-14: raised with the HP check (operator ruling A); one verdict became stricter — household set without Immich on 8 GB, by 0.5 MB.
|
||||
|
||||
@@ -682,6 +682,17 @@
|
||||
"measured_on": "demo-felhom (N100)",
|
||||
"date": "2026-10-13"
|
||||
},
|
||||
{
|
||||
"slug": "prowlarr",
|
||||
"display_name": "Prowlarr",
|
||||
"mem_typical_mb": 41,
|
||||
"mem_peak_mb": 44,
|
||||
"cpu_class": "light",
|
||||
"cpu_note": "",
|
||||
"source": "onboarding",
|
||||
"measured_on": null,
|
||||
"date": "2026-10-15"
|
||||
},
|
||||
{
|
||||
"slug": "radicale",
|
||||
"display_name": "Radicale",
|
||||
|
||||
@@ -135,7 +135,7 @@ stopping line that lies.
|
||||
| **R-1018** | Apps & catalog | P3 | **The OnlyOffice links (FileBrowser, Nextcloud) have no recorded live proof since the move to Proxmox.** `controller/internal/integrations/` holds two handlers; no audit after the Proxmox move shows a document opened from FileBrowser or Nextcloud in OnlyOffice (searched 2026-10-14). The media-app links of `15` §6 will copy this code, including its revoke-on-stop rule (`lifecycle.go:10-13`). | **OPEN** — filed 2026-10-14 | — | One live walk on a Tier-0 box: install OnlyOffice + FileBrowser, open a document, save, read it back; then stop one app and record what the link does | CC |
|
||||
| **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. | **OPEN** | — | write the `plant-it` + `wger` cards on both apps pages, then 62 → 64 everywhere, one commit | 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-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 |
|
||||
@@ -197,7 +197,7 @@ stopping line that lies.
|
||||
| **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 |
|
||||
|
||||
## Security & access — 22 rows (P1 2, P2 3, P3 11, P4 6)
|
||||
## Security & access — 23 rows (P1 2, P2 3, P3 12, P4 6)
|
||||
|
||||
| ID | Category | Sev | What | State | Blocked on | Next action | Owner |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
@@ -223,6 +223,7 @@ stopping line that lies.
|
||||
| **R-1050** | Security & access | P4 | **Raise HSTS to one year on or after 2026-11-15, if no https trouble was reported.** `09` §3 decision 249 (D2 = A, operator 2026-10-15): HSTS stays `max-age=86400` now; after a month with no https trouble it becomes one year (`31536000`); never preload, never `includeSubDomains`. The value is `HSTSMaxAgeSeconds` in `felhom-controller/controller/internal/infra/infra.go`, pinned by `TestRenderForwardedHeaders_HTTPSOnly`. „Trouble” = any report of a name that will not open, or a box answering http after the floor. | **WATCHING** — filed 2026-10-15 | the date | On or after 2026-11-15: read the register and the operator's mail for https trouble since 2026-10-15; none → a controller release with one year (test updated), bake → vouch → floor | CC |
|
||||
| **R-1054** | Security & access | P3 | **The hub's operator/global API key is still one bearer that can do everything on `/api/v1`, including reading every box's break-glass root password (`GET /admin/hosts/{id}/recovery-credential`).** Hub v0.152.0 gave the web surface scoped tokens (`05` §17) but tokens are refused on `/api/v1` by design. Who uses the global key today is not listed in one place. Fix: list its consumers; move each operator use to a scoped token on the web side (or a token class on the API), and keep the global key only where a box path needs it — or retire it. | OPEN — filed 2026-10-15 by the token build | — | List the global key's consumers (pod env, scripts, runbooks) | CC |
|
||||
| **R-1055** | Security & access | P3 | **A stolen `customers:write` token can take over a household's dashboard: edit the household's e-mail, then „resend claim" — the claim code goes to the new address.** The operator table (`09` §3 decision 251) put „resend claim" in Customers write; the self-bind link, which mints a capability, was made session only. Nobody holds a `customers:write` token today. Fix (operator decision): keep it, or make `/configs/{id}/claim-resend` session only (one line in `hub/internal/web/routes.go`). | WAITING-ON-OPERATOR — filed 2026-10-15 by the token build | operator decision | Decide: claim resend stays in Customers write, or session only | operator |
|
||||
| **R-1057** | Security & access | P3 | **A restore of a REMOVED gated app comes back without its setup gate, even when the backup was taken before the household's setup — so the app returns open, with no account.** Measured 2026-10-15 on 9202 with Prowlarr (`audits/prowlarr-2026-10-15/box/run3/restore.txt`): installed (gated, no account made), the guarded Update's per-app backup, remove keeping the backups, the household's restore button — afterwards a stranger's `/ping` through traefik answered 200, where before the remove it answered 401 (the gate). This follows the documented rule (`felhom-controller` `internal/stacks/life_records.go` `carryLifeRecords`: no prior record = no gate, „the data comes back with its admin"); the rule's assumption fails for a backup made before the setup. For a first-visitor app (Prowlarr, n8n, …) the first stranger sets the sign-in; for Prowlarr `/initialize.json` also hands out the API key (seen before the setup in the install window — NOT measured after this restore). Needs: the household to install, let a backup run before finishing the setup, remove, restore. | **OPEN** — filed 2026-10-15 by the Prowlarr walk | — | Record the gate's state in the per-app backup and re-close it on restore when it was closed then; red-proof with this walk (`tools/walk_restore.py`) | CC |
|
||||
|
||||
## Box system & updates — 13 rows (P2 1, P3 9, P4 3)
|
||||
|
||||
|
||||
@@ -92,8 +92,8 @@ class SizingWeb(unittest.TestCase):
|
||||
self.assertEqual(io.open(DATA, encoding="utf-8").read(), B.render(B.build()),
|
||||
"sizing-data.json differs from a fresh build — run scripts/build_sizing_web.py")
|
||||
|
||||
def test_offers_the_62_listed_apps_plus_builtin(self):
|
||||
self.assertEqual(len(self.all), 62)
|
||||
def test_offers_the_63_listed_apps_plus_builtin(self):
|
||||
self.assertEqual(len(self.all), 63) # 62 + Prowlarr (2026-10-15, R-1048)
|
||||
self.assertEqual([a["slug"] for a in self.d["apps"] if a.get("builtin")], ["filebrowser"])
|
||||
|
||||
def test_guest_sizes_follow_the_installer(self):
|
||||
@@ -109,7 +109,7 @@ class SizingWeb(unittest.TestCase):
|
||||
"household": (HOUSEHOLD, [N, T, W, W, W, W, W], 16, 12),
|
||||
"household without immich": ([s for s in HOUSEHOLD if s != "immich"], [T, W, W, W, W, W, W], 12, 8), # 2026-10-14 HP raise: 2,731 x 1.5 = 4,096.5 > 4,096
|
||||
"immich alone": (["immich"], [T, W, W, W, W, W, W], 12, 8),
|
||||
"all 62": (self.all, [N, N, N, N, T, W, W], 48, 32), # 24 GB: guest 19,868 < peak 22,333
|
||||
"all 63": (self.all, [N, N, N, N, T, W, W], 48, 32), # 24 GB: guest 19,868 < peak 22,377 (22,333 before Prowlarr)
|
||||
"nothing": ([], [W] * 7, 8, None),
|
||||
}
|
||||
for name, (sel, want, rec, tight) in cases.items():
|
||||
@@ -133,7 +133,7 @@ class SizingWeb(unittest.TestCase):
|
||||
|
||||
def test_segments_add_up_to_the_bar(self):
|
||||
for name, sel in {"household": HOUSEHOLD, "household without immich": [x for x in HOUSEHOLD if x != "immich"],
|
||||
"immich alone": ["immich"], "all 62": self.all, "nothing": []}.items():
|
||||
"immich alone": ["immich"], "all 63": self.all, "nothing": []}.items():
|
||||
well, segs = segments(self.d, sel)
|
||||
self.assertAlmostEqual(sum(mb for _, mb in segs), well * 1024, delta=1, msg=name)
|
||||
self.assertGreaterEqual(dict(segs)["base"], 0, name + ": base system negative")
|
||||
@@ -148,7 +148,7 @@ class SizingWeb(unittest.TestCase):
|
||||
base8 = small * 1024 - guest_mib(self.d, small)
|
||||
tiny = ["glance"] # 6 MB: its fits-well size is far below 8 GB
|
||||
self.assertLess(min_box_gb(self.d, (self.d["platform_mb"] + 7) * self.d["headroom"]), small)
|
||||
for name, sel in {"nothing": [], "tiny": tiny, "household": HOUSEHOLD, "all 62": self.all}.items():
|
||||
for name, sel in {"nothing": [], "tiny": tiny, "household": HOUSEHOLD, "all 63": self.all}.items():
|
||||
bar, segs = segments(self.d, sel)
|
||||
self.assertGreaterEqual(bar, small, name)
|
||||
self.assertAlmostEqual(sum(mb for _, mb in segs), bar * 1024, delta=1, msg=name)
|
||||
@@ -217,7 +217,7 @@ class SizingWeb(unittest.TestCase):
|
||||
elif len(cells) > 2 and not cells[0].startswith("---"):
|
||||
rows[cells[0]] = cells
|
||||
sel = {"Household set": HOUSEHOLD, "Household set without Immich": [s for s in HOUSEHOLD if s != "immich"],
|
||||
"Immich alone": ["immich"], "All 62 apps": self.all}
|
||||
"Immich alone": ["immich"], "All 63 apps": self.all}
|
||||
self.assertEqual(set(rows), set(sel))
|
||||
for name, slugs in sel.items():
|
||||
peak, verdicts = estimate(self.d, slugs)
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
## 2026-10-15 — the Prowlarr logo (unblocks the site gate)
|
||||
## 2026-10-15 — Prowlarr on the apps pages; the count 62 → 63 (R-1048)
|
||||
|
||||
- A Prowlarr card after Radarr on `alkalmazasok.html` and `en/apps.html` (the logo arrived in the commit before). The
|
||||
card says the box links it to Sonarr and Radarr, with at most one button press (the controller links it by itself only
|
||||
when Sonarr/Radarr come up after it).
|
||||
- Every stated app count 62 → 63 on both languages; the media group 19 → 20. R-1036's two owed cards are unchanged.
|
||||
|
||||
## 2026-10-15 — the Prowlarr logo (unblocks the site gate)
|
||||
|
||||
- `website/assets/prowlarr-logo.svg` added — byte-identical to the uncommitted copy in the media work folder
|
||||
(`felhom.eu-media`, untouched since 12:18). The catalog lists Prowlarr, so `site_gates.py` failed „app logos" and the
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<script>document.documentElement.className=document.documentElement.className.replace('no-js','js');</script>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Telepíthető alkalmazások — 62 app otthoni szerverre | Felhom.eu</title>
|
||||
<meta name="description" content="Nextcloud, Immich, Jellyfin, Vaultwarden — összesen 62 alkalmazás otthoni szerveredre, szinte mind nyílt forráskódú. Google Drive, iCloud Photos és Spotify alternatívák.">
|
||||
<title>Telepíthető alkalmazások — 63 app otthoni szerverre | Felhom.eu</title>
|
||||
<meta name="description" content="Nextcloud, Immich, Jellyfin, Vaultwarden — összesen 63 alkalmazás otthoni szerveredre, szinte mind nyílt forráskódú. Google Drive, iCloud Photos és Spotify alternatívák.">
|
||||
|
||||
<meta name="keywords" content="Nextcloud, Immich, Jellyfin, Plex, Sonarr, Radarr, Vaultwarden, nyílt forráskódú alkalmazások, self-hosted apps, otthoni szerver alkalmazások, Google Photos alternatíva, Dropbox alternatíva">
|
||||
<meta name="robots" content="index, follow">
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://felhom.eu/alkalmazasok">
|
||||
<meta property="og:title" content="62 alkalmazás otthoni szerverre">
|
||||
<meta property="og:title" content="63 alkalmazás otthoni szerverre">
|
||||
<meta property="og:description" content="Nextcloud, Immich, Jellyfin, Vaultwarden és még sok más. Fájlkezelés, fotók, média, dokumentumok — mind a saját szerveredről.">
|
||||
<meta property="og:image" content="https://felhom.eu/assets/og-image.png?v=3">
|
||||
<meta property="og:locale" content="hu_HU">
|
||||
<meta property="og:site_name" content="Felhom.eu">
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="62 alkalmazás otthoni szerverre">
|
||||
<meta name="twitter:title" content="63 alkalmazás otthoni szerverre">
|
||||
<meta name="twitter:description" content="Nextcloud, Immich, Jellyfin és még sok más — a te szerveredről.">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png?v=3">
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
<div class="page-header">
|
||||
<h1>Telepíthető <span>Alkalmazások</span></h1>
|
||||
</div>
|
||||
<p class="page-lede">Válassz 62 alkalmazás közül. Szinte mind ingyenes, nyílt forráskódú szoftver, és mind a saját szervereden fut.</p>
|
||||
<p class="page-lede">Válassz 63 alkalmazás közül. Szinte mind ingyenes, nyílt forráskódú szoftver, és mind a saját szervereden fut.</p>
|
||||
<p class="page-lede"><a href="/gepigeny">Mekkora gép kell ezekhez? →</a></p>
|
||||
<div class="disclaimer-banner">
|
||||
<h3><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-info"/></svg> Fontos tudnivalók</h3>
|
||||
@@ -266,7 +266,7 @@
|
||||
<div class="category-header">
|
||||
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-tv"/></svg></span>
|
||||
<h2>Média & <span>Szórakozás</span></h2>
|
||||
<span class="app-count">19 alkalmazás</span>
|
||||
<span class="app-count">20 alkalmazás</span>
|
||||
</div>
|
||||
<div class="app-grid">
|
||||
<!-- Immich -->
|
||||
@@ -540,6 +540,21 @@
|
||||
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Prowlarr -->
|
||||
<div class="app-card" id="prowlarr">
|
||||
<div class="app-card-header">
|
||||
<img src="/assets/prowlarr-logo.svg" alt="Prowlarr" class="app-logo">
|
||||
<div class="app-title-area"><h3>Prowlarr</h3><span class="app-tagline">Letöltési források egy helyen</span></div>
|
||||
</div>
|
||||
<div class="app-card-body">
|
||||
<p class="app-description">A letöltési forrásaidat (indexereket) egyszer adod meg, és a Sonarr meg a Radarr magától megkapja őket. A gép köti össze őket; legfeljebb egy gombot nyomsz meg hozzá. Saját meghajtót nem használ.</p>
|
||||
<div class="app-features"><span class="app-feature">Egyszer kell megadni</span><span class="app-feature">Sonarr és Radarr</span><span class="app-feature">A gép köti össze</span></div>
|
||||
</div>
|
||||
<div class="app-card-footer">
|
||||
<a href="https://github.com/Prowlarr/Prowlarr" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Forráskód</a>
|
||||
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Seerr -->
|
||||
<div class="app-card" id="seerr">
|
||||
<div class="app-card-header">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"source": {
|
||||
"path": "documentation/audits/sizing-2026-10-13/sizing.json",
|
||||
"commit": "c885b5ac",
|
||||
"sha256": "56e12018217fe3e05c096569321b106a73fc0a9f762480745b32340ecdbb458e"
|
||||
"sha256": "d289766cc93cf5d488eeab7567bcbda29297cb673621897bb851cd0b49613b9b"
|
||||
},
|
||||
"platform_mb": 470,
|
||||
"headroom": 1.5,
|
||||
@@ -391,6 +391,20 @@
|
||||
"cpu_note_en": "",
|
||||
"measured": true
|
||||
},
|
||||
{
|
||||
"slug": "prowlarr",
|
||||
"name_hu": "Prowlarr",
|
||||
"name_en": "Prowlarr",
|
||||
"tagline_hu": "Letöltési források egy helyen",
|
||||
"tagline_en": "Download sources in one place",
|
||||
"category": "media",
|
||||
"typical_mb": 41,
|
||||
"peak_mb": 44,
|
||||
"cpu_class": "light",
|
||||
"cpu_note_hu": "",
|
||||
"cpu_note_en": "",
|
||||
"measured": true
|
||||
},
|
||||
{
|
||||
"slug": "seerr",
|
||||
"name_hu": "Seerr",
|
||||
|
||||
+21
-6
@@ -4,8 +4,8 @@
|
||||
<script>document.documentElement.className=document.documentElement.className.replace('no-js','js');</script>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Apps to install — 62 apps for a home server | Felhom.eu</title>
|
||||
<meta name="description" content="Nextcloud, Immich, Jellyfin, Vaultwarden — 62 apps for your home server in Hungary, almost all of them open source. Alternatives to Google Drive, iCloud Photos and Spotify.">
|
||||
<title>Apps to install — 63 apps for a home server | Felhom.eu</title>
|
||||
<meta name="description" content="Nextcloud, Immich, Jellyfin, Vaultwarden — 63 apps for your home server in Hungary, almost all of them open source. Alternatives to Google Drive, iCloud Photos and Spotify.">
|
||||
|
||||
<meta name="keywords" content="Nextcloud, Immich, Jellyfin, Plex, Sonarr, Radarr, Vaultwarden, open-source apps, self-hosted apps, home server apps, Google Photos alternative, Dropbox alternative">
|
||||
<meta name="robots" content="index, follow">
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://felhom.eu/en/apps">
|
||||
<meta property="og:title" content="62 apps for a home server">
|
||||
<meta property="og:title" content="63 apps for a home server">
|
||||
<meta property="og:description" content="Nextcloud, Immich, Jellyfin, Vaultwarden and many more. Files, photos, media, documents — all from your own server.">
|
||||
<meta property="og:image" content="https://felhom.eu/assets/og-image.png?v=3">
|
||||
<meta property="og:locale" content="en_GB">
|
||||
<meta property="og:site_name" content="Felhom.eu">
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="62 apps for a home server">
|
||||
<meta name="twitter:title" content="63 apps for a home server">
|
||||
<meta name="twitter:description" content="Nextcloud, Immich, Jellyfin and many more — from your own server.">
|
||||
<meta name="twitter:image" content="https://felhom.eu/assets/og-image.png?v=3">
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
<div class="page-header">
|
||||
<h1>Apps to <span>install</span></h1>
|
||||
</div>
|
||||
<p class="page-lede">Choose from 62 apps. Almost all of them are free, open-source software, and every one runs on your own server.</p>
|
||||
<p class="page-lede">Choose from 63 apps. Almost all of them are free, open-source software, and every one runs on your own server.</p>
|
||||
<p class="page-lede"><a href="/en/sizing">How big a machine do these need? →</a></p>
|
||||
<div class="disclaimer-banner">
|
||||
<h3><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-info"/></svg> Good to know</h3>
|
||||
@@ -266,7 +266,7 @@
|
||||
<div class="category-header">
|
||||
<span class="category-icon"><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-tv"/></svg></span>
|
||||
<h2>Media & <span>Entertainment</span></h2>
|
||||
<span class="app-count">19 apps</span>
|
||||
<span class="app-count">20 apps</span>
|
||||
</div>
|
||||
<div class="app-grid">
|
||||
<!-- Immich -->
|
||||
@@ -540,6 +540,21 @@
|
||||
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Prowlarr -->
|
||||
<div class="app-card" id="prowlarr">
|
||||
<div class="app-card-header">
|
||||
<img src="/assets/prowlarr-logo.svg" alt="Prowlarr" class="app-logo">
|
||||
<div class="app-title-area"><h3>Prowlarr</h3><span class="app-tagline">Download sources in one place</span></div>
|
||||
</div>
|
||||
<div class="app-card-body">
|
||||
<p class="app-description">Enter your download sources (indexers) once, and Sonarr and Radarr get them by themselves. The box links them; at most you press one button. It uses no drive of its own.</p>
|
||||
<div class="app-features"><span class="app-feature">Enter once</span><span class="app-feature">Sonarr and Radarr</span><span class="app-feature">The box links them</span></div>
|
||||
</div>
|
||||
<div class="app-card-footer">
|
||||
<a href="https://github.com/Prowlarr/Prowlarr" target="_blank" rel="noopener" class="github-link"><img src="/assets/github.svg" alt="GitHub">Source code</a>
|
||||
<span class="open-source-badge"><svg class="ico ico-yes" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-check"/></svg>Open Source</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Seerr -->
|
||||
<div class="app-card" id="seerr">
|
||||
<div class="app-card-header">
|
||||
|
||||
+4
-4
@@ -61,7 +61,7 @@
|
||||
"name": "How is Felhom.eu different from a Synology or QNAP NAS?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Synology and QNAP make NAS (network storage) devices built mainly for storing files, with their own closed software. I offer an open, Docker-based system instead, where the catalog's apps install in a few clicks – from a photo manager to a media server to a password manager. A NAS offers a limited choice of apps and depends on the maker's software updates. With Felhom you choose from 62 apps, and if something is missing, I look at whether it can be added."
|
||||
"text": "Synology and QNAP make NAS (network storage) devices built mainly for storing files, with their own closed software. I offer an open, Docker-based system instead, where the catalog's apps install in a few clicks – from a photo manager to a media server to a password manager. A NAS offers a limited choice of apps and depends on the maker's software updates. With Felhom you choose from 63 apps, and if something is missing, I look at whether it can be added."
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -141,7 +141,7 @@
|
||||
"name": "Which apps can I run?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "I offer 62 apps – the full list is on the Apps page. A few examples: Immich – a Google Photos alternative that backs up photos and videos automatically. Jellyfin/Plex – your own Netflix for films and series. Nextcloud – store and share files (instead of Google Drive). Vaultwarden – a password manager for the whole family. Paperless-ngx – scan documents and make them searchable. If something is not on the list, ask – I will look at whether it can join the catalog."
|
||||
"text": "I offer 63 apps – the full list is on the Apps page. A few examples: Immich – a Google Photos alternative that backs up photos and videos automatically. Jellyfin/Plex – your own Netflix for films and series. Nextcloud – store and share files (instead of Google Drive). Vaultwarden – a password manager for the whole family. Paperless-ngx – scan documents and make them searchable. If something is not on the list, ask – I will look at whether it can join the catalog."
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -500,7 +500,7 @@
|
||||
</button>
|
||||
<div class="faq-answer"><div class="faq-answer-inner">
|
||||
<p>Synology and QNAP make NAS (network storage) devices built mainly for storing files, with their own closed software. I offer an open, Docker-based system instead, where the catalog's apps install in a few clicks – from a photo manager to a media server to a password manager.</p>
|
||||
<p>A NAS offers a limited choice of apps and depends on the maker's software updates. With Felhom you choose from 62 apps, and if something is missing, I look at whether it can be added.</p>
|
||||
<p>A NAS offers a limited choice of apps and depends on the maker's software updates. With Felhom you choose from 63 apps, and if something is missing, I look at whether it can be added.</p>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
@@ -628,7 +628,7 @@
|
||||
<svg class="faq-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||
</button>
|
||||
<div class="faq-answer"><div class="faq-answer-inner">
|
||||
<p>I offer <strong>62 apps</strong> – the full list is on the <a href="/en/apps">Apps</a> page. A few examples:</p>
|
||||
<p>I offer <strong>63 apps</strong> – the full list is on the <a href="/en/apps">Apps</a> page. A few examples:</p>
|
||||
<p><strong>Immich</strong> – a Google Photos alternative that backs up photos and videos automatically. <strong>Jellyfin/Plex</strong> – your own Netflix for films and series. <strong>Nextcloud</strong> – store and share files (instead of Google Drive). <strong>Vaultwarden</strong> – a password manager for the whole family. <strong>Paperless-ngx</strong> – scan documents and make them searchable.</p>
|
||||
<p>If something is not on the list, ask – I will look at whether it can join the catalog.</p>
|
||||
</div></div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<meta name="description" content="A home server in your own home in Hungary: photos, documents, media. 62 apps to install, automatic backups on three levels, a dashboard in English or Hungarian. A closed test is starting now.">
|
||||
<meta name="description" content="A home server in your own home in Hungary: photos, documents, media. 63 apps to install, automatic backups on three levels, a dashboard in English or Hungarian. A closed test is starting now.">
|
||||
<title>Felhom.eu — Your own cloud, your own rules | A home server service in Hungary</title>
|
||||
|
||||
<!-- SEO meta -->
|
||||
@@ -140,7 +140,7 @@
|
||||
<ul>
|
||||
<li>Photos, documents, media</li>
|
||||
<li>Network shares</li>
|
||||
<li>62 apps to install</li>
|
||||
<li>63 apps to install</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
@@ -246,7 +246,7 @@
|
||||
<div class="band">
|
||||
<div class="band-item">
|
||||
<h3>What you can install</h3>
|
||||
<p>62 apps — almost all of them open source</p>
|
||||
<p>63 apps — almost all of them open source</p>
|
||||
<a href="/en/apps" class="btn btn-outline">See all applications →</a>
|
||||
</div>
|
||||
<div class="band-item">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Services — what a Felhom box does today | Felhom.eu</title>
|
||||
<meta name="description" content="What a Felhom box does today: photos and documents, network shares, 62 installable applications, three-tier automatic backup and remote monitoring.">
|
||||
<meta name="description" content="What a Felhom box does today: photos and documents, network shares, 63 installable applications, three-tier automatic backup and remote monitoring.">
|
||||
<meta name="keywords" content="home server services, features, network shares, automatic backup, installable applications, remote monitoring">
|
||||
<meta name="robots" content="index, follow">
|
||||
<link rel="canonical" href="https://felhom.eu/en/services">
|
||||
@@ -111,7 +111,7 @@
|
||||
<p>The box's folders appear in Windows File Explorer and the Mac Finder — you drag files onto them like onto any other folder. Each share can be set to read-only.</p>
|
||||
</li>
|
||||
<li class="caps-item">
|
||||
<h4><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg> 62 apps to install</h4>
|
||||
<h4><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg> 63 apps to install</h4>
|
||||
<p>You install them from the Dashboard in a few clicks — no command line. Almost all of them are open source (the exceptions are marked on the apps page), and every one runs on your machine.</p>
|
||||
</li>
|
||||
<li class="caps-item">
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
<ul class="feature-list">
|
||||
<li>A web interface in English or Hungarian – the household chooses, and no command-line knowledge is needed</li>
|
||||
<li>App catalog – 62 apps to install in a few clicks</li>
|
||||
<li>App catalog – 63 apps to install in a few clicks</li>
|
||||
<li>Resource view – memory and storage use as it happens</li>
|
||||
<li>Automatic backups – databases and files, with their status watched</li>
|
||||
<li>App updates – only versions we have tried, a fresh backup first, and if the new version does not start, the box goes back to the previous one by itself</li>
|
||||
|
||||
+4
-4
@@ -61,7 +61,7 @@
|
||||
"name": "Mi a különbség a Felhom.eu és a Synology/QNAP NAS szolgáltatásai között?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "A Synology és QNAP elsősorban fájltárolásra készült NAS (hálózati adattároló) eszközök, saját zárt szoftverrel. Én ezzel szemben egy nyílt, Docker-alapú rendszert kínálok, amelyre a katalógus alkalmazásai pár kattintással telepíthetők – fotókezelőtől a média szerveren át a jelszókezelőig. A NAS-ok korlátozott alkalmazás-választékot kínálnak és a gyártó szoftverfrissítéseitől függenek. A Felhomnál 62 alkalmazásból válogathatsz, és ha valami hiányzik, megnézem, felvehető-e."
|
||||
"text": "A Synology és QNAP elsősorban fájltárolásra készült NAS (hálózati adattároló) eszközök, saját zárt szoftverrel. Én ezzel szemben egy nyílt, Docker-alapú rendszert kínálok, amelyre a katalógus alkalmazásai pár kattintással telepíthetők – fotókezelőtől a média szerveren át a jelszókezelőig. A NAS-ok korlátozott alkalmazás-választékot kínálnak és a gyártó szoftverfrissítéseitől függenek. A Felhomnál 63 alkalmazásból válogathatsz, és ha valami hiányzik, megnézem, felvehető-e."
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -141,7 +141,7 @@
|
||||
"name": "Milyen alkalmazásokat tudok futtatni?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "62 alkalmazást kínálok – a teljes listát az Alkalmazások oldalon találod. Néhány példa: Immich – Google Photos alternatíva fotók és videók automatikus mentésével. Jellyfin/Plex – saját Netflix filmekhez és sorozatokhoz. Nextcloud – fájlok tárolása és megosztása (Google Drive helyett). Vaultwarden – jelszókezelő az egész családnak. Paperless-ngx – dokumentumok digitalizálása és kereshetővé tétele. Ha valami nincs a listán, kérdezz – megnézem, felvehető-e a katalógusba."
|
||||
"text": "63 alkalmazást kínálok – a teljes listát az Alkalmazások oldalon találod. Néhány példa: Immich – Google Photos alternatíva fotók és videók automatikus mentésével. Jellyfin/Plex – saját Netflix filmekhez és sorozatokhoz. Nextcloud – fájlok tárolása és megosztása (Google Drive helyett). Vaultwarden – jelszókezelő az egész családnak. Paperless-ngx – dokumentumok digitalizálása és kereshetővé tétele. Ha valami nincs a listán, kérdezz – megnézem, felvehető-e a katalógusba."
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -500,7 +500,7 @@
|
||||
</button>
|
||||
<div class="faq-answer"><div class="faq-answer-inner">
|
||||
<p>A Synology és QNAP elsősorban fájltárolásra készült NAS (hálózati adattároló) eszközök, saját zárt szoftverrel. Én ezzel szemben egy nyílt, Docker-alapú rendszert kínálok, amelyre a katalógus alkalmazásai pár kattintással telepíthetők – fotókezelőtől a média szerveren át a jelszókezelőig.</p>
|
||||
<p>A NAS-ok korlátozott alkalmazás-választékot kínálnak és a gyártó szoftverfrissítéseitől függenek. A Felhomnál 62 alkalmazásból válogathatsz, és ha valami hiányzik, megnézem, felvehető-e.</p>
|
||||
<p>A NAS-ok korlátozott alkalmazás-választékot kínálnak és a gyártó szoftverfrissítéseitől függenek. A Felhomnál 63 alkalmazásból válogathatsz, és ha valami hiányzik, megnézem, felvehető-e.</p>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
@@ -628,7 +628,7 @@
|
||||
<svg class="faq-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
||||
</button>
|
||||
<div class="faq-answer"><div class="faq-answer-inner">
|
||||
<p><strong>62 alkalmazást</strong> kínálok – a teljes listát az <a href="/alkalmazasok">Alkalmazások</a> oldalon találod. Néhány példa:</p>
|
||||
<p><strong>63 alkalmazást</strong> kínálok – a teljes listát az <a href="/alkalmazasok">Alkalmazások</a> oldalon találod. Néhány példa:</p>
|
||||
<p><strong>Immich</strong> – Google Photos alternatíva fotók és videók automatikus mentésével. <strong>Jellyfin/Plex</strong> – saját Netflix filmekhez és sorozatokhoz. <strong>Nextcloud</strong> – fájlok tárolása és megosztása (Google Drive helyett). <strong>Vaultwarden</strong> – jelszókezelő az egész családnak. <strong>Paperless-ngx</strong> – dokumentumok digitalizálása és kereshetővé tétele.</p>
|
||||
<p>Ha valami nincs a listán, kérdezz – megnézem, felvehető-e a katalógusba.</p>
|
||||
</div></div>
|
||||
|
||||
+3
-3
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<meta name="description" content="Otthoni szerver a saját otthonodban: fényképek, dokumentumok, médiatár. 62 telepíthető alkalmazás, háromszintű automatikus mentés, magyar vagy angol nyelvű vezérlőpult. Most zárt teszt indul.">
|
||||
<meta name="description" content="Otthoni szerver a saját otthonodban: fényképek, dokumentumok, médiatár. 63 telepíthető alkalmazás, háromszintű automatikus mentés, magyar vagy angol nyelvű vezérlőpult. Most zárt teszt indul.">
|
||||
<title>Felhom.eu — Saját felhőd, saját szabályaid | Otthoni szerver szolgáltatás</title>
|
||||
|
||||
<!-- SEO meta -->
|
||||
@@ -140,7 +140,7 @@
|
||||
<ul>
|
||||
<li>Fényképek, dokumentumok, média</li>
|
||||
<li>Hálózati megosztás</li>
|
||||
<li>62 telepíthető alkalmazás</li>
|
||||
<li>63 telepíthető alkalmazás</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
@@ -246,7 +246,7 @@
|
||||
<div class="band">
|
||||
<div class="band-item">
|
||||
<h3>Amit telepíthetsz</h3>
|
||||
<p>Fájlkezelés, fotók és média, dokumentumok, jelszókezelés, okosotthon, fejlesztői eszközök. Nextcloud, Immich, Jellyfin, Paperless-ngx, Vaultwarden, Home Assistant és még 54 másik: <strong>62 alkalmazás</strong>, szinte mind nyílt forráskódú.</p>
|
||||
<p>Fájlkezelés, fotók és média, dokumentumok, jelszókezelés, okosotthon, fejlesztői eszközök. Nextcloud, Immich, Jellyfin, Paperless-ngx, Vaultwarden, Home Assistant és még 55 másik: <strong>63 alkalmazás</strong>, szinte mind nyílt forráskódú.</p>
|
||||
<a href="/alkalmazasok" class="btn btn-outline">Összes alkalmazás megtekintése →</a>
|
||||
</div>
|
||||
<div class="band-item">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Szolgáltatások — mit tud ma a Felhom doboz | Felhom.eu</title>
|
||||
<meta name="description" content="Mit tud ma egy Felhom doboz: fényképek és dokumentumok, hálózati megosztás, 62 telepíthető alkalmazás, háromszintű automatikus mentés és távoli felügyelet.">
|
||||
<meta name="description" content="Mit tud ma egy Felhom doboz: fényképek és dokumentumok, hálózati megosztás, 63 telepíthető alkalmazás, háromszintű automatikus mentés és távoli felügyelet.">
|
||||
<meta name="keywords" content="otthoni szerver szolgáltatások, funkciók, hálózati megosztás, automatikus mentés, telepíthető alkalmazások, távoli felügyelet">
|
||||
<meta name="robots" content="index, follow">
|
||||
<link rel="canonical" href="https://felhom.eu/szolgaltatasok">
|
||||
@@ -111,7 +111,7 @@
|
||||
<p>A doboz mappái megjelennek a Windows Intézőben és a Mac Finderben: úgy húzod rájuk a fájlokat, mint bármelyik másik mappára. Megosztásonként beállítható, hogy csak olvasható legyen.</p>
|
||||
</li>
|
||||
<li class="caps-item">
|
||||
<h4><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg> 62 telepíthető alkalmazás</h4>
|
||||
<h4><svg class="ico-lg" aria-hidden="true"><use href="/assets/icons.svg?v=1#i-package"/></svg> 63 telepíthető alkalmazás</h4>
|
||||
<p>A vezérlőpultból telepíthetők, pár kattintással, parancssor nélkül. Szinte mind nyílt forráskódú, és mind a te gépeden fut.</p>
|
||||
</li>
|
||||
<li class="caps-item">
|
||||
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
<ul class="feature-list">
|
||||
<li>Magyar vagy angol webes felület – a háztartás választ, és nincs szükség parancssor ismeretre</li>
|
||||
<li>Alkalmazás katalógus – 62 app telepíthető pár kattintással</li>
|
||||
<li>Alkalmazás katalógus – 63 app telepíthető pár kattintással</li>
|
||||
<li>Erőforrás figyelés – memória és tárhely használat valós időben</li>
|
||||
<li>Automatikus mentések – adatbázis és fájl backup, állapotfigyeléssel</li>
|
||||
<li>Alkalmazás frissítések – csak kipróbált verzió, előtte friss mentés, és ha az új verzió nem indul, a doboz magától visszaáll az előzőre</li>
|
||||
|
||||
Reference in New Issue
Block a user