Agent 0.159.1, the catalog allow-list (controller 0.328.0), break-glass rotation: report, register, design
gates / gates (push) Successful in 8m49s

Closed R-971, R-954, R-1124, R-1012 (174 -> 175 rows); opened R-1139..R-1143; R-895 READY with the design
and hub slice 1; R-972 waits on the vouch. [DESIGN] "The catalog allow-list" in 02; the catalog trust line in
01; FELHOM_THINCHECK and unit-forget in 03. Evidence audits/agent-allowlist-rotation-2026-10-17/.

Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
admin committed 2026-10-17 18:00:05 +02:00
1 parent d968f8490e
commit 5a5486104a
36 files changed
+816 -16

No files matched your search

@@ -0,0 +1,24 @@
== root@192.168.0.154
felhom-agent 0.159.1
Oct 17 17:38:26 felhom felhom-agent[1278]: time=2026-10-17T17:38:26.285+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=076f93320a4eddaa op=agent_update
Oct 17 17:38:27 felhom felhom-os-apply[3912437]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
Oct 17 17:38:27 felhom felhom-agent[1278]: time=2026-10-17T17:38:27.406+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
Oct 17 17:38:28 felhom felhom-agent[1278]: time=2026-10-17T17:38:28.285+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=73 degraded=""
Oct 17 17:38:28 felhom felhom-agent[1278]: time=2026-10-17T17:38:28.285+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=8d9bf40b122037c7 op=agent_config_update
Oct 17 17:39:31 felhom felhom-agent[3912599]: time=2026-10-17T17:39:31.112+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
Oct 17 17:53:42 felhom felhom-os-apply[3935466]: os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False
Oct 17 17:53:42 felhom felhom-agent[3912599]: time=2026-10-17T17:53:42.245+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False"
Oct 17 17:53:43 felhom felhom-agent[3912599]: time=2026-10-17T17:53:43.165+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
Oct 17 17:53:43 felhom felhom-agent[3912599]: time=2026-10-17T17:53:43.165+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=33c061b404a445e1 op=agent_config_update
== felhom-pve
felhom-agent 0.159.1
Oct 17 17:39:46 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:46.899+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=c994ded3d077a21b op=agent_update
Oct 17 17:39:47 demo-felhom felhom-os-apply[2418991]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
Oct 17 17:39:47 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:47.651+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
Oct 17 17:39:48 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:48.278+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=73 degraded=""
Oct 17 17:39:48 demo-felhom felhom-agent[1207]: time=2026-10-17T17:39:48.278+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=0f93931bec704435 op=agent_config_update
Oct 17 17:40:51 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:40:51.620+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
Oct 17 17:55:00 demo-felhom felhom-os-apply[2438672]: os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False
Oct 17 17:55:00 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:00.806+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=3 same=27 self-check=ok signers-created=False"
Oct 17 17:55:01 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:01.446+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
Oct 17 17:55:01 demo-felhom felhom-agent[2419165]: time=2026-10-17T17:55:01.446+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=1e7a09eb163bd82a op=agent_config_update
@@ -0,0 +1,24 @@
Oct 17 15:37:46 demo-hp felhom-agent[1266]: time=2026-10-17T15:37:46.203+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=e67e21347e268540 op=agent_update
Oct 17 15:38:50 demo-hp felhom-agent[3044359]: time=2026-10-17T15:38:50.528+02:00 level=WARN msg="selfupdate: update committed" version=0.159.0 wrapper=""
Oct 17 15:53:02 demo-hp felhom-os-apply[3098908]: os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False
Oct 17 15:53:02 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:02.040+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0-step1 written=1 same=28 self-check=ok signers-created=False"
Oct 17 15:53:03 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:03.082+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=73 total=75 degraded=thin-orphan-check,mount-unit-forget
Oct 17 15:53:03 demo-hp felhom-agent[3044359]: time=2026-10-17T15:53:03.082+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=ed248025668b456b op=agent_config_update
Oct 17 16:08:02 demo-hp felhom-os-apply[3151947]: os-apply: BUNDLE DONE agent=0.159.0 written=3 same=27 self-check=ok signers-created=False
Oct 17 16:08:02 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:02.131+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.0 written=3 same=27 self-check=ok signers-created=False"
Oct 17 16:08:03 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:03.154+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
Oct 17 16:08:03 demo-hp felhom-agent[3044359]: time=2026-10-17T16:08:03.155+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=f6b59d99eaed6396 op=agent_config_update
Oct 17 16:11:10 demo-hp felhom-agent[3044359]: time=2026-10-17T16:11:10.435+02:00 level=INFO msg="local-api: guest-bind recorded for startup re-assert" vmid=9201 where=/mnt/r1124test durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
Oct 17 16:23:00 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:00.920+02:00 level=WARN msg="decommission: operator-signed decommission complete (drive will never auto-mount)" durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
Oct 17 16:23:00 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:00.920+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=7eb567e3dff73267 op=decommission
Oct 17 16:23:50 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:50.743+02:00 level=INFO msg="storage: forgot a decommissioned drive that is gone — its mount unit is removed" name=5de8066f-0887-4dd1-a329-9b595e4c1d9e where=/mnt/r1124test uuid=5de8066f-08
Oct 17 16:40:55 demo-hp felhom-agent[3044359]: time=2026-10-17T16:40:55.234+02:00 level=INFO msg="backup: completed" vmid=9201 target=local archive=local:backup/vzdump-lxc-9201-2026_10_17-16_33_32.tar.zst size_bytes=6768484797 uncovered_volumes=2
Oct 17 16:53:01 demo-hp felhom-agent[3044359]: time=2026-10-17T16:53:01.776+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=b3aa07f6104caae6 op=agent_update
Oct 17 16:54:06 demo-hp felhom-agent[3320002]: time=2026-10-17T16:54:06.099+02:00 level=WARN msg="selfupdate: update committed" version=0.159.1 wrapper=""
Oct 17 17:08:18 demo-hp felhom-os-apply[3376289]: os-apply: BUNDLE DONE agent=0.159.1 written=0 same=30 self-check=ok signers-created=False
Oct 17 17:08:18 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:18.348+02:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE DONE agent=0.159.1 written=0 same=30 self-check=ok signers-created=False"
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.386+02:00 level=WARN msg="osupdate: capability probe after the config bundle" ok=75 total=75 degraded=""
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.386+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=b5cc740c36f4bed2 op=agent_config_update
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=INFO msg="decommission: drive removed from the guest's bind record" vmid=9201 durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=WARN msg="decommission: operator-signed decommission complete (drive will never auto-mount)" durable_id=uuid:5de8066f-0887-4dd1-a329-9b595e4c1d9e
Oct 17 17:08:19 demo-hp felhom-agent[3320002]: time=2026-10-17T17:08:19.402+02:00 level=WARN msg="signedjobs: signed op COMPLETED" job=e9303dec85a1f5bd op=decommission
@@ -0,0 +1,19 @@
== before unplug
-rw-r--r-- 1 root root 292 Oct 17 16:11 /etc/systemd/system/mnt-r1124test.mount
lrwxrwxrwx 1 root root 39 Oct 17 16:11 /etc/systemd/system/multi-user.target.wants/mnt-r1124test.mount -> /etc/systemd/system/mnt-r1124test.mount
GET /disks 200 rows 5 r1124test listed: True
16:23:42
== unplug: unmount the bind and the drive, detach the loop device
ls: cannot access '/dev/disk/by-uuid/5de8066f-0887-4dd1-a329-9b595e4c1d9e': No such file or directory
== 45 s later
ls: cannot access '/etc/systemd/system/mnt-r1124test.mount': No such file or directory
ls: cannot access '/etc/systemd/system/multi-user.target.wants/mnt-r1124test.mount': No such file or directory
GET /disks 200 rows 4 r1124test listed: False
Oct 17 16:23:42 demo-hp systemd[1]: mnt-felhom\x2ddrives-r1124test.mount: Deactivated successfully.
Oct 17 16:23:42 demo-hp systemd[1]: Unmounting mnt-r1124test.mount - Felhom storage mount 5de8066f-0887-4dd1-a329-9b595e4c1d9e...
Oct 17 16:23:42 demo-hp systemd[1]: mnt-r1124test.mount: Deactivated successfully.
Oct 17 16:23:42 demo-hp systemd[1]: Unmounted mnt-r1124test.mount - Felhom storage mount 5de8066f-0887-4dd1-a329-9b595e4c1d9e.
Oct 17 16:23:50 demo-hp sudo[3208627]: felhom-agent : PWD=/ ; USER=root ; COMMAND=/usr/bin/systemctl disable -- mnt-r1124test.mount
Oct 17 16:23:50 demo-hp sudo[3208690]: felhom-agent : PWD=/ ; USER=root ; COMMAND=/usr/local/sbin/felhom-priv-apply unit-forget mnt-r1124test.mount
Oct 17 16:23:50 demo-hp felhom-priv-apply[3208698]: felhom-priv-apply: REMOVED unit-forget /etc/systemd/system/mnt-r1124test.mount (where=/mnt/r1124test)
Oct 17 16:23:50 demo-hp felhom-agent[3044359]: time=2026-10-17T16:23:50.743+02:00 level=INFO msg="storage: forgot a decommissioned drive that is gone — its mount unit is removed" name=5de8066f-0887-4dd1-a329-9b595e4c1d9e where=/mnt/r1124test uuid=5de8066f-0887-4dd1-a329-9b595e4c1d9e unit=mnt-r1124test.mount
@@ -0,0 +1,8 @@
== red-proof: the prune loop removed
decommission_test.go:120: 9201 record = [uuid:keep uuid:gone], want [uuid:keep]
--- FAIL: TestDecommissionExecutor_PrunesTheGuestBindRecord (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/signedjobs 0.009s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-agent/internal/signedjobs 0.016s
@@ -0,0 +1,24 @@
== mutation A: ForgetRetiredDrives body = return 0
--- FAIL: TestForgetRetiredDrives_DecommissionedAndGone_UnitRemovedAndNotListed (0.00s)
--- FAIL: TestForgetRetiredDrives_AlreadyDisabled_NoDisableCall (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit (0.00s)
--- PASS: TestForgetRetiredDrives_NilIntent_ForgetsNothing (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.011s
FAIL
== mutation B: the present-drive check removed
--- PASS: TestForgetRetiredDrives_DecommissionedAndGone_UnitRemovedAndNotListed (0.00s)
--- PASS: TestForgetRetiredDrives_AlreadyDisabled_NoDisableCall (0.00s)
--- FAIL: TestForgetRetiredDrives_KeepsEveryOtherUnit (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/decommissioned_but_mounted (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/enrolled_and_absent (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/ejected_and_absent (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/no_intent (0.00s)
--- PASS: TestForgetRetiredDrives_KeepsEveryOtherUnit/mount_table_unreadable (0.00s)
--- FAIL: TestForgetRetiredDrives_KeepsEveryOtherUnit/decommissioned_but_present (0.00s)
--- PASS: TestForgetRetiredDrives_NilIntent_ForgetsNothing (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.010s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-agent/internal/storage 0.009s
@@ -0,0 +1,25 @@
== M1: Orphans() returns nil
--- FAIL: TestParse_TheOrphanOf20261014 (0.00s)
--- FAIL: TestCheck_OrphanOnBothReads_IsNamed (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/thincheck 0.006s
FAIL
== M2: explainFailure appends nothing
--- FAIL: TestBackup_SnapshotFailure_NamesTheOrphan (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-agent/internal/backup 0.009s
FAIL
== M3: helper ignores a held snapshot
FAIL: test_a_snapshot_someone_else_holds_is_never_touched (__main__.Refuses.test_a_snapshot_someone_else_holds_is_never_touched)
FAILED (failures=1)
== M4: helper without the release trap
FAIL: test_thin_ls_failure_still_releases (__main__.Refuses.test_thin_ls_failure_still_releases)
FAILED (failures=1)
== M5: helper sends a delete
FAIL: test_the_only_pool_messages_are_reserve_and_release (__main__.NeverDeletes.test_the_only_pool_messages_are_reserve_and_release)
FAIL: test_healthy_pool_lists_both_sides_and_releases (__main__.Reads.test_healthy_pool_lists_both_sides_and_releases)
FAILED (failures=2)
== restored
ok gitea.dooplex.hu/admin/felhom-agent/internal/thincheck (cached)
ok gitea.dooplex.hu/admin/felhom-agent/internal/backup (cached)
OK
@@ -0,0 +1,23 @@
== red-proof: the tests against the pre-R-1124 wrapper (HEAD)
FAIL: test_F1_a_symlinked_unit_is_not_followed (__main__.UnitForget.test_F1_a_symlinked_unit_is_not_followed)
FAIL: test_F2_a_network_unit_or_a_foreign_unit_is_not_removed (__main__.UnitForget.test_F2_a_network_unit_or_a_foreign_unit_is_not_removed)
FAIL: test_F3_an_enabled_unit_is_not_removed (__main__.UnitForget.test_F3_an_enabled_unit_is_not_removed)
FAIL: test_F4_a_mounted_drive_keeps_its_unit (__main__.UnitForget.test_F4_a_mounted_drive_keeps_its_unit)
FAIL: test_F5_a_present_drive_keeps_its_unit (__main__.UnitForget.test_F5_a_present_drive_keeps_its_unit)
FAIL: test_U3_a_unit_whose_name_lies_about_where_is_not_removed (__main__.UnitForget.test_U3_a_unit_whose_name_lies_about_where_is_not_removed)
FAIL: test_already_gone_is_fine (__main__.UnitForget.test_already_gone_is_fine)
FAIL: test_an_absent_disabled_unmounted_drive_unit_is_removed (__main__.UnitForget.test_an_absent_disabled_unmounted_drive_unit_is_removed)
Ran 46 tests in 0.010s
FAILED (failures=8)
== mutation: F5 check disabled
FAIL: test_F5_a_present_drive_keeps_its_unit (__main__.UnitForget.test_F5_a_present_drive_keeps_its_unit)
Ran 46 tests in 0.007s
FAILED (failures=1)
== mutation: F4 check disabled
FAIL: test_F4_a_mounted_drive_keeps_its_unit (__main__.UnitForget.test_F4_a_mounted_drive_keeps_its_unit)
Ran 46 tests in 0.007s
FAILED (failures=1)
== mutation: F3 check disabled
FAIL: test_F3_an_enabled_unit_is_not_removed (__main__.UnitForget.test_F3_an_enabled_unit_is_not_removed)
Ran 46 tests in 0.008s
FAILED (failures=1)
@@ -0,0 +1,45 @@
loop=/dev/loop2
Physical volume "/dev/loop2" successfully created.
Volume group "felhomscratch" successfully created
Thin pool volume with chunk size 64.00 KiB can address at most <15.88 TiB of data.
Logical volume "pool" created.
Logical volume "t1" created.
LV ThId Pool
pool
t1 1 pool
== healthy read
lvm-before 1 t1
pool 1
lvm-after 1 t1
ok
rc=0
== make an orphan (kernel only, scratch pool): create_thin 7
lvm-before 1 t1
pool 1
pool 7
lvm-after 1 t1
ok
rc=0
0 819200 thin-pool 1 113/1024 0/6400 - rw discard_passdown queue_if_no_space - 256
== someone else holds a metadata snapshot
felhom-thin-check: REFUSED: a metadata snapshot of felhomscratch-pool-tpool is already held (by someone else) — not touched 3
rc=3
held root: 30
== demo-hp real pool pve/data (read only)
lvm-before 1 vm-9201-disk-0
lvm-before 2 vm-9201-disk-1
pool 1
pool 2
lvm-after 1 vm-9201-disk-0
lvm-after 2 vm-9201-disk-1
ok
rc=0
held root after: -
== teardown scratch
Logical volume "t1" successfully removed.
Logical volume "pool" successfully removed.
Volume group "felhomscratch" successfully removed
Labels on physical volume "/dev/loop2" successfully wiped.
pve
0
0
@@ -0,0 +1,17 @@
== before
79e7877dc3e8577d7623f9b5ba57d300eca7a2a0f86c27458385b97517f2c480 /opt/docker/stacks/privatebin/docker-compose.yml
494270e42262ac772dd2033a0dc2c2530b52bf8132a5245c9bb3e2a9f9df9e3a 2026-10-17T14:34:24.634717373Z running
== after the refused correction
79e7877dc3e8577d7623f9b5ba57d300eca7a2a0f86c27458385b97517f2c480 /opt/docker/stacks/privatebin/docker-compose.yml
0
494270e42262ac772dd2033a0dc2c2530b52bf8132a5245c9bb3e2a9f9df9e3a 2026-10-17T14:34:24.634717373Z running
2026/10/17 15:10:34 allowlist.go:122: [WARN] [stacks] privatebin: definition REFUSED by the allow-list (R-971), nothing written: the catalog definition of privatebin asks for container rights the box does not allow: priv
2026/10/17 15:10:34 sync.go:511: [WARN] [sync] privatebin: catalog definition REFUSED by the allow-list — the app keeps its last good compose, nothing written: the catalog definition of privatebin asks for container ri
2026/10/17 15:10:34 notifier.go:315: [DEBUG] PushEvent: type=app_definition_refused severity=warning url=https://hub.felhom.eu/api/v1/event
2026/10/17 15:10:34 notifier.go:341: [DEBUG] PushEvent: app_definition_refused pushed OK (HTTP 200)
2026/10/17 15:10:34 notifier.go:353: [INFO] Event pushed: app_definition_refused (warning) [hu-only] — privatebin: the box REFUSED a catalog definition — it asks for container rights not on the box's allow-list. Noth
== hub
2026/10/17 17:10:34 [INFO] Event from demo-hp: app_definition_refused (warning) — privatebin: the box REFUSED a catalog definition — it asks for container rights not on the box's allow-list. Nothing was written; the app keeps its last good compose. Check w
2026/10/17 17:10:34 [INFO] Operator email sent for demo-hp/app_definition_refused
/apps/privatebin 200 True True
/apps/opengist 200 False False
@@ -0,0 +1,14 @@
2026/10/17 15:11:32 sync.go:318: [INFO] [sync] Cloning https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git → /opt/docker/felhom-controller/data/catalog-cache
2026/10/17 15:11:33 sync.go:261: [INFO] [sync] catalog moved c3d0fb37df7f -> 45763e31c2fc (0 new, 0 stack dir(s) changed)
2026/10/17 15:11:33 sync.go:299: [INFO] [sync] Catalog sync complete
2026/10/17 15:11:33 sync.go:142: [INFO] [sync] Initial sync: Sablonok frissítve — a katalógus új változata betöltve; a telepített alkalmazások fájljai nem változtak
23: repo_url: https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
24: sync_interval: 15m
-rw------- 1 root root 2989 Aug 31 08:32 /var/lib/docker/volumes/felhom-controller-data/_data/controller.yaml.pre-r971
mirror main c3d0fb3 DRILL privatebin: privileged: true — the box must REFUSE this correction (R-971 proof on 9201)
cache HEAD 45763e3 CHANGELOG: the privileges gate's round-2/3 changes
https://gitea.dooplex.hu/admin/app-catalog-felhom.eu.git
/apps/privatebin 200 False False
/apps/opengist 200 False False
@@ -0,0 +1,38 @@
== M1: Admit admits everything
--- FAIL: TestAdmit_EveryClassIsRefused (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/network_mode_host (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/pid (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/uts (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/volumes_from (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/extends_file (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/devices (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/seccomp_off (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/apparmor_off (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/sysctls (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/env_file_outside (0.00s)
--- FAIL: TestAdmit_EveryClassIsRefused/interpolated (0.00s)
== M2: copyTemplates asks nothing
--- FAIL: TestR971_RefusedCorrectionWritesNothing (0.00s)
--- FAIL: TestR971_RefusedTemplateOfAnAppNotInstalled (0.00s)
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.010s
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.20s)
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.208s
== M3: a NEW compose writer nobody gated
allowlist_wiring_test.go:124: internal/stacks/zz_redproof_writer.go:redproofNewWriter writes a file and names the compose file, and the allow-list guard does not know it — gate it (admitCompose before the write) or add it to `writers` as exempt with the reason
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.23s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.237s
== M4: no once-per-definition
--- FAIL: TestAllowList_OneEventPerRefusedDefinition (0.00s)
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.007s
== M5: the app page line removed
--- FAIL: TestR971_AppPage_SaysTheDefinitionWasRefused (0.28s)
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.296s
== M6: the install asks nothing
--- FAIL: TestAllowList_IsWiredIntoEveryComposeWriter (0.24s)
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.251s
== restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy (cached)
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync (cached)
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 423.793s
13
@@ -0,0 +1,14 @@
== catalog gate red-proof: the allow-list check never refuses
XX FACT: privileged true rc=0 (expected 1)
XX FACT: cap_add rc=0 (expected 1)
XX FACT: the host root bound rc=0 (expected 1)
XX FACT: a bind through another variable rc=0 (expected 1)
XX FACT: homepage's socket READ-WRITE rc=0 (expected 1)
XX FACT: the allowed socket in ANOTHER app rc=0 (expected 1)
XX FACT: network_mode host rc=0 (expected 1)
XX FACT: a driver_opts bind volume rc=0 (expected 1)
XX FACT: a ${VAR} in a privileged key rc=0 (expected 1)
XX FACT: privileged in a steps/ file rc=0 (expected 1)
fails: 10
== restored
check-privileges: 123 files judged, every class-setting on the allow-list
@@ -0,0 +1,8 @@
== live finding (9201, rc.4) red-proof: roots resolved only when they exist
privpolicy_test.go:438: binds under roots that do not exist yet were refused: the catalog definition of app asks for container rights the box does not allow: app: bind /mnt/felhom-drives/check/felhom-data/appdata/app -> /c rw; app: bind /mnt/felhom-drives/check/felhom-data/userdata/media -> /m rw
--- FAIL: TestAdmit_RootsThatDoNotExistYet (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.006s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.147s
@@ -0,0 +1,22 @@
== security-review fixes, red-proofs
-- F1: the image/start binding removed
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart (0.00s)
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/another_image (0.00s)
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/added_entrypoint (0.00s)
--- FAIL: TestAdmit_TheAllowedSettingIsBoundToItsImageAndStart/added_command (0.00s)
-- F2: Resolve ignored
--- FAIL: TestAdmit_ASymlinkOutOfARootIsOutside (0.00s)
-- F3: the later classes removed
--- FAIL: TestAdmit_TheLaterClasses (0.00s)
--- FAIL: TestAdmit_TheLaterClasses/provider (0.00s)
--- PASS: TestAdmit_TheLaterClasses/post_start (0.00s)
--- PASS: TestAdmit_TheLaterClasses/cgroup_parent (0.00s)
--- PASS: TestAdmit_TheLaterClasses/runtime (0.00s)
--- FAIL: TestAdmit_TheLaterClasses/gpus (0.00s)
--- PASS: TestAdmit_TheLaterClasses/device_request (0.00s)
-- F4: any /mnt/ path a root again
--- FAIL: TestAdmit_ARootElsewhereUnderMntIsNoRoot (0.00s)
== restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.137s
ok gitea.dooplex.hu/admin/felhom-controller/internal/sync 0.388s
ok gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.236s
@@ -0,0 +1,17 @@
== security review round 2, red-proofs
-- same-file extends not refused
--- FAIL: TestAdmit_Round2 (0.00s)
--- FAIL: TestAdmit_Round2/a_second_service_extends_the_allowed_one (0.00s)
-- healthcheck not bound
--- FAIL: TestAdmit_Round2 (0.00s)
--- FAIL: TestAdmit_Round2/the_allowed_service's_healthcheck_runs_a_shell (0.00s)
-- image variable not refused
--- FAIL: TestAdmit_Round2 (0.00s)
--- FAIL: TestAdmit_Round2/the_allowed_service's_image_through_a_variable (0.00s)
-- options variable allowed
--- FAIL: TestAdmit_Round2 (0.00s)
--- FAIL: TestAdmit_Round2/a_variable_in_a_bind's_options (0.00s)
-- a missing path judged by name again (fail open)
--- FAIL: TestAdmit_ANotYetCreatedPathBehindASymlink (0.00s)
== restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.123s
@@ -0,0 +1,8 @@
== round 3 red-proof: HDD_PATH whole again
privpolicy_test.go:416: " - ${HDD_PATH}:/drive\n" was admitted
--- FAIL: TestAdmit_HDDPathRootIsAppdataOnly (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy 0.005s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-controller/internal/privpolicy (cached)
@@ -0,0 +1,41 @@
FILES 123
SET audiobookshelf final audiobookshelf security_opt ["no-new-privileges:true"]
SET audiobookshelf step audiobookshelf security_opt ["no-new-privileges:true"]
SET crafty-controller final crafty-controller ports ["25565-25575:25565-25575"]
SET komga final komga security_opt ["no-new-privileges:true"]
SET komga step komga security_opt ["no-new-privileges:true"]
BIND audiobookshelf audiobookshelf ${USERDATA_PATH}/media/audiobooks:/audiobooks 2
BIND audiobookshelf audiobookshelf ${USERDATA_PATH}/media/podcasts:/podcasts 2
BIND calibre-web calibre-web ${IMPORT_PATH}/calibre:/cwa-book-ingest 1
BIND calibre-web calibre-web ${USERDATA_PATH}/media/books:/calibre-library 1
BIND emby emby ${USERDATA_PATH}/media:/media:ro 3
BIND grimmory grimmory ${HDD_PATH}/appdata/grimmory/data:/app/data 1
BIND grimmory grimmory ${IMPORT_PATH}/grimmory:/bookdrop 1
BIND grimmory grimmory ${USERDATA_PATH}/media/grimmory:/books 1
BIND homepage homepage /var/run/docker.sock:/var/run/docker.sock:ro 1
BIND immich immich-server ${HDD_PATH}/appdata/immich:/usr/src/app/upload 3
BIND immich immich-server ${USERDATA_PATH}/media/photos:/external/photos:ro 3
BIND jellyfin jellyfin ${USERDATA_PATH}/media:/media:ro 1
BIND komga komga ${USERDATA_PATH}/media/comics:/data 2
BIND metube metube ${USERDATA_PATH}/media/metube:/downloads 1
BIND navidrome navidrome ${USERDATA_PATH}/media/music:/music:ro 3
BIND nextcloud nextcloud ${HDD_PATH}/appdata/nextcloud:/var/www/html/data 3
BIND nzbget nzbget ${USERDATA_PATH}/media/nzbget:/downloads 1
BIND paperless-ngx paperless-webserver ${HDD_PATH}/appdata/paperless/export:/usr/src/paperless/export 1
BIND paperless-ngx paperless-webserver ${HDD_PATH}/appdata/paperless/media:/usr/src/paperless/media 1
BIND paperless-ngx paperless-webserver ${IMPORT_PATH}/paperless:/usr/src/paperless/consume 1
BIND plex plex ${USERDATA_PATH}/media:/media:ro 1
BIND qbittorrent qbittorrent ${USERDATA_PATH}/media/torrents:${USERDATA_PATH}/media/torrents 1
BIND qbittorrent qbittorrent ${USERDATA_PATH}/media/torrents:/downloads 1
BIND radarr radarr ${USERDATA_PATH}/media:${USERDATA_PATH}/media 1
BIND romm romm ${HDD_PATH}/appdata/romm/resources:/romm/resources 3
BIND romm romm ${USERDATA_PATH}/roms:/romm/library 2
BIND romm romm ${USERDATA_PATH}/roms:/romm/library/roms 1
BIND romm romm ${USERDATA_PATH}/roms-bios:/romm/library/bios 1
BIND sabnzbd sabnzbd ${USERDATA_PATH}/media/usenet:/downloads 1
BIND sonarr sonarr ${USERDATA_PATH}/downloads:/downloads 1
BIND sonarr sonarr ${USERDATA_PATH}/media:${USERDATA_PATH}/media 1
BIND sonarr sonarr ${USERDATA_PATH}/media/tv:/media/tv 1
BIND transmission transmission ${USERDATA_PATH}/media/transmission:${USERDATA_PATH}/media/transmission 1
BIND transmission transmission ${USERDATA_PATH}/media/transmission:/downloads 1
BIND transmission transmission ${USERDATA_PATH}/media/transmission/watch:/watch 1
@@ -0,0 +1,36 @@
# R-971 survey — every container right the catalog asks for (2026-10-17)
Catalog `app-catalog-felhom.eu` at `1af6ea7` (the survey) and `d5a443d` (the gate). **123 files: 65 `templates/<app>/docker-compose.yml`
and 58 ladder `steps/*.yml`.** Read with PyYAML (`survey-raw.txt`, the raw scan) and again with the controller's own
check (`privpolicy.Check` on the placeholder env, the test `TestAllowList_TheWholeCatalogPasses`).
Classes looked for: `privileged`, `cap_add`, `devices`, `device_cgroup_rules`, `network_mode`, `pid`, `ipc`, `uts`,
`userns_mode`, `cgroup`, `security_opt`, `sysctls`, `volumes_from`, `build`, `include`, `extends`, `env_file`, top-level
volumes with `driver`/`driver_opts`/`external`/`name`, `configs`/`secrets` with `file:`, and every bind source.
## The allow-list (what the catalog needs)
| app | service | setting | why the app needs it | upstream doc |
|---|---|---|---|---|
| homepage | homepage | `bind /var/run/docker.sock -> /var/run/docker.sock ro` | the Docker widget and Docker service discovery list the household's containers and their state | https://gethomepage.dev/configs/docker/ |
That is the whole list. **No template or step asks for any other class member.** Note (security review C5-5, R-782): a
read-only socket mount does not limit the Docker API; the entry keeps today's behaviour, it does not bless it — a
read-only socket proxy for homepage stays a separate catalog change.
## Seen and NOT a class member (no entry needed)
| app | setting | why it passes |
|---|---|---|
| audiobookshelf, komga (final + step) | `security_opt: [no-new-privileges:true]` | a hardening, not a relaxation |
| every bind (35 distinct) | `${HDD_PATH}/…`, `${USERDATA_PATH}/…`, `${IMPORT_PATH}/…` | inside the data roots the box gives |
| crafty-controller | `ports: 25565-25575` | not in the brief's classes: a published port is LAN reach of the guest, not a right on the host (documented in `01-topology-and-trust.md`) |
| vikunja | `user: 0:0` | root INSIDE the container; not a host right |
| karakeep-chrome | `init: true` | a tini init, no privilege |
| 94 compose files | `networks: traefik-public: external: true` | a network, not a volume; not a class |
## The controller's infra stacks (out of scope, stated)
traefik (holds the Docker socket at the internet edge), cloudflared, filebrowser and samba (`network_mode: host` for LAN
discovery) are rendered by the controller from its own code, not the catalog. Since v0.328.0 the sync also refuses to
copy a catalog template named like one of them into its directory.
@@ -0,0 +1,15 @@
== before
demo-felhom-8363b5 HTTP 200 user root@pam set_at 2026-07-18T16:30:41Z password_len 32
192.168.0.162 PVE ticket HTTP 200 ticket_issued True
== rotate (installer step 4b alone, on demo-felhom)
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
== after (hub 0.157.0: set_at should move now)
demo-felhom-8363b5 HTTP 200 user root@pam set_at 2026-10-17T15:10:04Z password_len 32
== the NEW vaulted value logs in
192.168.0.162 PVE ticket HTTP 200 ticket_issued True
== the OLD value no longer does
192.168.0.162 PVE ticket HTTP 401
values differ: yes
@@ -0,0 +1,14 @@
== before
demo-hp-bb76ea HTTP 200 user root@pam set_at 2026-07-21T16:24:27Z password_len 32
== rotate (installer step 4b alone, on demo-hp)
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
== after
demo-hp-bb76ea HTTP 200 user root@pam set_at 2026-07-21T16:24:27Z password_len 32
== the NEW vaulted value logs in
192.168.0.104 PVE ticket HTTP 200 ticket_issued True
== the OLD value no longer does
192.168.0.104 PVE ticket HTTP 401
values differ: yes
@@ -0,0 +1,8 @@
== red-proof: the upsert without set_at
r954_revault_set_at_test.go:31: credential set_at = 2025-10-17 10:00:00 +0000 UTC — the re-vault kept the first vault's time
--- FAIL: TestHostRecovery_ReVaultMovesSetAt (0.04s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/store 0.045s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-hub/internal/store 0.044s
@@ -0,0 +1,14 @@
== before
tester-1-d70be4 HTTP 200 user root@pam set_at 2026-10-04T19:40:27Z password_len 32
== rotate (installer step 4b alone, on Tester 1)
[STEP] 4b/8 break-glass credential (root@pam console password → hub vault)
[OK] root@pam password set + vaulted to the hub (retrieve via the operator /admin path; never logged here)
[WARN] NOTE: the root@pam password just CHANGED — the old one now fails at the PVE web GUI (:8006).
[WARN] Retrieve the new one at hub → host page (vaulted recovery credential).
== after
tester-1-d70be4 HTTP 200 user root@pam set_at 2026-10-04T19:40:27Z password_len 32
== the NEW vaulted value logs in
192.168.0.154 PVE ticket HTTP 200 ticket_issued True
== the OLD value no longer does
192.168.0.154 PVE ticket HTTP 401
values differ: yes
@@ -0,0 +1,65 @@
# R-895 — the hub counts a box's off-site snapshots itself (option B, updated with the measurement) — 2026-10-17
Baselines: felhom.eu `8f97b800` (hub v0.157.0 code), design origin `audits/night-burndown-2026-10-06/design-R-822.md`
option B. Architecture: `07-backup-architecture.md` (the off-site tier; decision 68 — the box-trusted count; decision
69 — the hub writes the pinned key line), `06-offsite-connectivity.md`.
## 1. The question
The clean-up window's drop alarm (`EventWindowDrop`) compares counts the BOX reports before and after a window. A box
that was broken into, or fakes planted with its add-only key, keep the count level while the real history shrinks.
Option B: the hub counts the files in the box's restic `snapshots/` directory itself, over a login of its own.
## 2. The measurement (read-only, demo-hp's repository folder only)
**What login would the hub need?** None new. The hub already logs in to every provisioned sub-account once a day with
the sub-account PASSWORD (sealed at rest, R-821) for the `authorized_keys` audit (`offsitekeys.Registrar.Audit`,
port 23, host key pinned). That login can list `snapshots/`. **It is NOT read-only** — the same password can `rm`,
`mv` and rewrite `authorized_keys` (measured 2026-10-03, `audits/offsite-append-only-2026-10-03/live/`). The listing
itself only reads (`ls -l`), and adds no capability the hub does not already hold.
**Does the provider show upload times?** Yes, by prior measurement on this very sub-account: on 2026-09-01 the
password login on demo-hp's sub-account (`u629488-sub3`) listed entries with their modification time to the minute
over SFTP (`ls -la` → `Sep 1 12:12`), and the port-23 shell offers `ls|ll`, `stat`
(`audits/evidence-drill-r95-recovery-2026-09-01/phase1-find-the-snapshot/01-probe-tree.txt`, `03-shell-capabilities.txt`).
A restic snapshot file is written once and never changed, so its mtime is its upload time.
**Today's re-measurement from DooPlex: NOT done — and why, with what was tried.** Since decision 69 no box holds the
sub-account password; the hub alone holds it, sealed. Tried: (a) CC's secret store (`sec list`) — no Storage Box
credential; (b) the box's own key — pinned to `rclone serve restic --append-only`, it reaches only restic's REST API
(names and sizes, no times, and it is the box's key, which is exactly what the hub must not rely on); (c) the hub — it
has no command or endpoint that lists. Reading the sealed password out of the hub DB to measure by hand was not done:
it would put a delete-capable credential of a customer sub-account on DooPlex for a measurement the hub can make
itself. **So the measurement ships as code:** hub v0.157.0's daily audit lists `snapshots/` read-only and LOGS the
count, the newest and the oldest upload time (`internal/offsitekeys/snapshots.go`). The first daily run after the
deploy IS the measurement; compare its count with the box's own (`offsite.snapshot_count` in the host report) — a
control from a different channel.
## 3. The design (the alarm slice, after the measurement)
1. **Before/after a window, the hub's own count** (`OpenWindowFor` / `CloseWindowFor` take the listing, the box's
numbers logged beside). `EventWindowDrop` fires on the hub's numbers. Red test first (design-R-822 §5): a fake
listing 17 → 3 while the box reports 17 → 15 must fire; today it does not.
2. **Files no box run explains:** each box run reports its time (manual runs, catch-ups and crash retries included —
they are runs). A snapshot file whose upload time falls outside every reported run (± a slack), or more files than
runs, is the injection signature → an operator-only event; the next window is refused while such files exist.
3. **Snapshots that vanished outside a window:** today's list minus yesterday's, when no window was open → an
operator-only event. The hub keeps only names and times (custody unchanged, `07` §8a: never contents).
## 4. Costs
| | cost |
|---|---|
| credential | none new; the existing sealed password (write-capable — a fact today, not a new exposure) |
| per box | one more SSH login per day (the listing), and the stored list (≈ 70 names × 100 bytes) |
| build | slice 1 (this release, ~1 h: list + log); slice 2 (§3.1–3.3, ~1 day with the red tests); a live proof on scratch 9202's sub-account |
| what can go wrong | `ls -l` output differing on the provider (slice 1 logs it before anything alarms); a run that does not report its time (false alarm — every run path must report) |
**A read-only login would be better, and costs a per-box sub-account:** a second sub-account with `readonly=true`
on the same directory (Hetzner API) would let the hub list without holding delete rights for this purpose. It adds
one provisioning step and one sealed secret per box. Not built; named as the alternative.
## 5. State
R-895 stays OPEN (READY) with this design. Slice 1 (the listing, log-only) is in hub v0.157.0 — deployed only on the
operator's yes. Slice 2 (the alarms) needs: the first logged listings on real boxes (the measurement), then about a day.
@@ -0,0 +1,8 @@
== red-proof: every line counted as a snapshot
snapshots_test.go:44: files=3 other=0, want 2 and 1
--- FAIL: TestListSnapshots_CountsTheBoxSnapshotFilesReadOnly (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-hub/internal/offsitekeys 0.008s
FAIL
== restored
ok gitea.dooplex.hu/admin/felhom-hub/internal/offsitekeys 0.262s
@@ -0,0 +1,21 @@
=== demo-hp (enkisfelhom.hu)
containers: 24 not-healthy/running:
2026/10/17 15:21:35 updater.go:855: [INFO] [selfupdate] Post-update startup: update successful (0.328.0-rc.5 → 0.328.0)
allow-list refusals since start: 0
2026/10/17 15:21:35 sync.go:142: [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
public https://felhom.enkisfelhom.hu/login: 200
public https://files.enkisfelhom.hu/: 200
=== demo-felhom (demo-felhom.eu)
containers: 9 not-healthy/running:
2026/10/17 15:21:24 [INFO] [selfupdate] Post-update startup: update successful (0.327.1 → 0.328.0)
allow-list refusals since start: 0
2026/10/17 15:21:25 [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
public https://felhom.demo-felhom.eu/login: 200
public https://files.demo-felhom.eu/: 200
=== tester-1 (enkicsifelhom.hu)
containers: 10 not-healthy/running:
2026/10/17 15:21:34 [INFO] [selfupdate] Post-update startup: update successful (0.327.1 → 0.328.0)
allow-list refusals since start: 0
2026/10/17 15:21:35 [INFO] [sync] Initial sync: Sablonok naprakészek — nincs változás
public https://felhom.enkicsifelhom.hu/login: 200
public https://files.enkicsifelhom.hu/: 200
@@ -0,0 +1,12 @@
== global floor
HTTP/1.1 303 See Other
Location: /configuration?flash=floor_set
clear tester-1:
HTTP/1.1 303 See Other
Location: /customers/tester-1?flash=floor_set
clear demo-hp:
HTTP/1.1 303 See Other
Location: /customers/demo-hp?flash=floor_set
clear demo-felhom:
HTTP/1.1 303 See Other
Location: /customers/demo-felhom?flash=floor_set
@@ -0,0 +1,7 @@
integrity: ok
('min_controller_version', '0.328.0')
('min_controller_version_declared_min_agent', '0.328.0=0.158.1')
per-box floor columns: ['min_controller_version', 'min_controller_declared_min_agent', 'min_controller_set_at']
min_controller_version set: []
min_controller_declared_min_agent set: []
min_controller_set_at set: []
@@ -0,0 +1,8 @@
OK http://files.demo-felhom.eu/r1033-check?q=1 -> 301 https://files.demo-felhom.eu/r1033-check?q=1
OK http://gist.demo-felhom.eu/r1033-check?q=1 -> 301 https://gist.demo-felhom.eu/r1033-check?q=1
OK http://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1 -> 301 https://no-such-name-r1033.demo-felhom.eu/r1033-check?q=1
OK http://prowlarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://prowlarr.demo-felhom.eu/r1033-check?q=1
OK http://radarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://radarr.demo-felhom.eu/r1033-check?q=1
OK http://sonarr.demo-felhom.eu/r1033-check?q=1 -> 301 https://sonarr.demo-felhom.eu/r1033-check?q=1
OK http://torrent.demo-felhom.eu/r1033-check?q=1 -> 301 https://torrent.demo-felhom.eu/r1033-check?q=1
== every public name redirects http -> https