2026-10-26 release run: hub 0.171.0, agent 0.166.0 (vouched), controller 0.344.0 (global floor 09:07:47 UTC), catalog 73c165d, golden 0.344.0 (baked, vouched; a fresh install came up on 0.344.0); the golden waiver removed — the gate is green on the golden. Rows: 9 closed (R-1278, R-1280–R-1283, R-1286–R-1289), R-1285 back to OPEN, R-1294 and R-1295 filed; STATUS, CONTEXT, evidence (scanned, 0 hits).
gates / gates (push) Successful in 13m35s
No files matched your search
@@ -0,0 +1,33 @@
|
||||
# agent 0.166.0 delivery by signed agent_update + agent_config_update (felhom-opsign, key felhom-op-1), 2026-10-26
|
||||
== demo-hp
|
||||
felhom-agent 0.166.0
|
||||
time=2026-10-26T09:03:07.108+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=d70489200b46088d op=agent_update
|
||||
time=2026-10-26T09:03:08.570+01:00 level=WARN msg="osupdate: config bundle INSTALLED" op=agent_config_update agent_version=0.166.0 bundle="{\"agent_version\": \"0.166.0\", \"authority\": \"signed\", \"kept\": [\"/etc/felhom/crash-guard.conf\"], \"prev_dir\": \"/var/lib/felhom-os-apply/bundle-prev/20261026T080307Z-before-0.166.0\
|
||||
time=2026-10-26T09:03:09.616+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=81bbc6a41cef76cb op=agent_config_update
|
||||
time=2026-10-26T09:03:10.331+01:00 level=INFO msg="felhom-agent daemon starting" version=0.166.0 host_id=demo-hp-bb76ea hub_url=https://hub.felhom.eu interval_s=900
|
||||
time=2026-10-26T09:03:11.465+01:00 level=INFO msg="capabilities self-check" ok=76 total=76 degraded=0 inactive=0
|
||||
time=2026-10-26T09:04:12.557+01:00 level=WARN msg="selfupdate: update committed" version=0.166.0 wrapper=""
|
||||
time=2026-10-26T09:18:23.594+01:00 level=WARN msg="signedjobs: REJECTED signed op — executor not called" job=4702af39db454f15 op=agent_config_update reason=rejected err="authz: op validity window too long: issued_at=2026-10-26 08:11:55 +0000 UTC expires_at=2026-10-27 09:11:55 +0000 UTC (25h0m0s, the most is 24h0m0s)"
|
||||
time=2026-10-26T09:33:25.398+01:00 level=WARN msg="osupdate: config bundle INSTALLED" op=agent_config_update agent_version=0.166.0 bundle="{\"agent_version\": \"0.166.0\", \"authority\": \"signed\", \"kept\": [\"/etc/felhom/crash-guard.conf\"], \"prev_dir\": \"/var/lib/felhom-os-apply/bundle-prev/20261026T083324Z-before-0.166.0\
|
||||
os-apply: BUNDLE POLICY DONE install_mode=appliance removed=0
|
||||
time=2026-10-26T09:33:25.500+01:00 level=INFO msg="osupdate: wrapper" line="os-apply: BUNDLE POLICY DONE install_mode=appliance removed=0"
|
||||
time=2026-10-26T09:33:25.500+01:00 level=INFO msg="osupdate: bundle policy pass done" op=agent_config_update agent_version=0.166.0 bundle_policy="{\"install_mode\": \"appliance\", \"removed\": []}"
|
||||
time=2026-10-26T09:33:26.543+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=a22eca000de7bfb6 op=agent_config_update
|
||||
== felhom-pve
|
||||
felhom-agent 0.166.0
|
||||
time=2026-10-26T09:10:07.742+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=afca32508fe8d923 op=agent_update
|
||||
time=2026-10-26T09:10:08.529+01:00 level=WARN msg="osupdate: config bundle INSTALLED" op=agent_config_update agent_version=0.166.0 bundle="{\"agent_version\": \"0.166.0\", \"authority\": \"signed\", \"kept\": [\"/etc/felhom/crash-guard.conf\"], \"prev_dir\": \"/var/lib/felhom-os-apply/bundle-prev/20261026T081007Z-before-0.166.0\
|
||||
time=2026-10-26T09:10:09.181+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=430f09b61278c214 op=agent_config_update
|
||||
time=2026-10-26T09:10:10.456+01:00 level=INFO msg="felhom-agent daemon starting" version=0.166.0 host_id=demo-felhom-8363b5 hub_url=https://hub.felhom.eu interval_s=900
|
||||
time=2026-10-26T09:10:11.126+01:00 level=INFO msg="capabilities self-check" ok=76 total=76 degraded=0 inactive=0
|
||||
time=2026-10-26T09:11:12.434+01:00 level=WARN msg="selfupdate: update committed" version=0.166.0 wrapper=""
|
||||
== root@192.168.0.154
|
||||
felhom-agent 0.166.0
|
||||
time=2026-10-26T09:16:10.590+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=665accf7f3a71a24 op=agent_update
|
||||
time=2026-10-26T09:16:11.762+01:00 level=WARN msg="osupdate: config bundle INSTALLED" op=agent_config_update agent_version=0.166.0 bundle="{\"agent_version\": \"0.166.0\", \"authority\": \"signed\", \"kept\": [\"/etc/felhom/crash-guard.conf\"], \"prev_dir\": \"/var/lib/felhom-os-apply/bundle-prev/20261026T081610Z-before-0.166.0\
|
||||
time=2026-10-26T09:16:12.801+01:00 level=WARN msg="signedjobs: signed op COMPLETED" job=8dabce5865f2c029 op=agent_config_update
|
||||
time=2026-10-26T09:16:13.668+01:00 level=INFO msg="felhom-agent daemon starting" version=0.166.0 host_id=tester-1-d70be4 hub_url=https://hub.felhom.eu interval_s=900
|
||||
time=2026-10-26T09:16:14.714+01:00 level=INFO msg="capabilities self-check" ok=76 total=76 degraded=0 inactive=0
|
||||
time=2026-10-26T09:17:15.564+01:00 level=WARN msg="selfupdate: update committed" version=0.166.0 wrapper=""
|
||||
|
||||
## R-1280 signer side (felhom-opsign built from v0.166.0): -ttl 25h -> rc=2 'refused: a box accepts a window of at most 24h0m0s (R-1280)'; -ttl 24h -> rc=0 (envelope deleted, never sent)
|
||||
@@ -0,0 +1,29 @@
|
||||
[release-agent] building 0.166.0 …
|
||||
[release-agent] built ok: sha256 3f22c65b78914632fa476292f6b58e5af3ed9e9900f3a5a7a347a9c0bfea9c5c
|
||||
[release-agent] config bundle built: sha256 093772c1bda8b974e86ed45472f8fadc8992f247563f5739876102a5156003a3
|
||||
[release-agent] tagging v0.166.0 at aa69114 …
|
||||
[release-agent] publishing …
|
||||
[publish-agent] publishing /tmp/felhom-agent-MuCo1A (16291150 bytes, sha256 3f22c65b78914632…) → https://gitea.dooplex.hu/api/packages/admin/generic/felhom-agent/0.166.0/felhom-agent
|
||||
[publish-agent] pre-delete existing artifact: HTTP 404 (404/204 expected)
|
||||
[publish-agent] upload OK (HTTP 201)
|
||||
[publish-agent] round-trip GET verified (sha256 matches)
|
||||
[publish-agent] DONE. Record in the hub operator UI (Configs → Day-0 artifacts): agent 0.166.0 / 3f22c65b78914632fa476292f6b58e5af3ed9e9900f3a5a7a347a9c0bfea9c5c
|
||||
[release-agent] config bundle published (HTTP 201)
|
||||
[release-agent] pushing v0.166.0 …
|
||||
remote: . Processing 1 references
|
||||
remote: Processed 1 references in total
|
||||
To https://gitea.dooplex.huAGENT_VERSION=0.166.0
|
||||
AGENT_SHA256=3f22c65b78914632fa476292f6b58e5af3ed9e9900f3a5a7a347a9c0bfea9c5c
|
||||
|
||||
RELEASED — and installable, verified by download, not by this script's own say-so.
|
||||
|
||||
version : 0.166.0
|
||||
tag : v0.166.0
|
||||
sha256 : 3f22c65b78914632fa476292f6b58e5af3ed9e9900f3a5a7a347a9c0bfea9c5c
|
||||
bundle : 093772c1bda8b974e86ed45472f8fadc8992f247563f5739876102a5156003a3 (felhom-config-bundle.json — vouch it with the agent)
|
||||
|
||||
NOT VOUCHED. Vouching is what points machines at this version and stays your deliberate act:
|
||||
hub operator UI → Configs → Day-0 artifacts. Until then boxes keep installing the previous one.
|
||||
/admin/felhom-agent.git
|
||||
* [new tag] v0.166.0 -> v0.166.0
|
||||
[release-agent] verifying by independent download …
|
||||
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 136 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1 @@
|
||||
Install pressed 09:23:16Z
|
||||
@@ -0,0 +1,20 @@
|
||||
# Fresh install on golden 0.344.0 (D52 proof), 2026-10-26. VM 9373 on demo-hp (6 cores, 12 GiB, nvme-scratch), public ISO felhom-installer-1.30.0-pve9.2-1.iso (sha256 590d7b9b… = the published one), graphical installer driven by vmctl.sh (screens in install/, the pairing code blacked out).
|
||||
Install pressed 09:23:16Z
|
||||
golden vouched by the operator 10:26:23 CET (Artifact manifest set: agent=0.166.0 golden=0.344.0 min_agent=0.158.1)
|
||||
bind: POST to the public https://hub.felhom.eu/bind/<token> (the 07:23Z mail) with the console's pairing code + TESTER4_RETRIEVAL (sec) 09:29:41Z -> 200 'Sikeres összekötés'
|
||||
|
||||
## channel A — the hub (box-originated events and reports)
|
||||
2026/10/26 10:29:41 [INFO] self-bind SUCCESS: appliance 52 bound to customer Tester4 by customer self-service (token 16bfbd89…)
|
||||
2026/10/26 10:30:41 [INFO] host enrolled: Tester4-eb7371 (customer Tester4)
|
||||
2026/10/26 10:30:55 [INFO] Artifact manifest served for customer Tester4 (agent=0.166.0 golden=0.344.0)
|
||||
2026/10/26 10:31:14 [WARN] escrow CARRIED for Tester4: the sealed package of deleted host Tester4-84bbe7 is now the current package of Tester4-eb7371 (repo-key hash 5501e4bf2cda…); the box will ask for the recovery code
|
||||
2026/10/26 10:31:15 [ERROR] pbsdr auto-provision for Tester4 (WG-registration hook): pbsdr: F-14 auto re-issue for Tester4: tenantsync: endpoint refused: own-namespace list as felhom@pbs!Tester4 failed twice — rolled back (code self_check_failed) — save th
|
||||
2026/10/26 10:32:25 [INFO] Notification preferences updated for Tester4: address set=true, household=false, events=[backup_failed db_dump_failed disk_warning disk_critical storage_disconnected node_down health_critical expected_backup_missed expected_dbdump_mi
|
||||
2026/10/26 10:32:30 [INFO] Event from Tester4: controller_started (info) — Controller elindult (0.344.0)
|
||||
2026/10/26 10:32:49 [INFO] Event from Tester4: controller_started (info) — Controller elindult (0.344.0)
|
||||
|
||||
## channel B — the box itself (guest 192.168.0.157, LAN): /claim page asset tag = sha256("felhom-asset-tag-v1:"+version+":"+buildID)[:4]
|
||||
192.168.0.157 (felhom.tester4.test/claim): style.css?v=38ef5ac9
|
||||
192.168.0.148 (felhom.enkicsifelhom.hu/login): style.css?v=38ef5ac9
|
||||
192.168.0.155 (felhom.enkisfelhom.hu/login): style.css?v=38ef5ac9
|
||||
(.148 = Tester 1, .155 = demo-hp: both on the 0.344.0 release image) -> the new box runs the same build.
|
||||
@@ -0,0 +1,8 @@
|
||||
name: release1026-box
|
||||
scsi0: nvme-scratch:9373/vm-9373-disk-0.raw,size=64G
|
||||
scsi1: nvme-scratch:9373/vm-9373-disk-1.raw,size=48G
|
||||
scsihw: virtio-scsi-single
|
||||
purging VM 9373 from related configurations..
|
||||
0
|
||||
ls: cannot access '/mnt/hdd_1/images/9373': No such file or directory
|
||||
Mem: 29 13 9 0 7 15
|
||||
@@ -0,0 +1,21 @@
|
||||
Formatting '/mnt/hdd_1/images/9373/vm-9373-disk-0.raw', fmt=raw size=68719476736 preallocation=off
|
||||
scsi0: successfully created disk 'nvme-scratch:9373/vm-9373-disk-0.raw,size=64G'
|
||||
Formatting '/mnt/hdd_1/images/9373/vm-9373-disk-1.raw', fmt=raw size=51539607552 preallocation=off
|
||||
scsi1: successfully created disk 'nvme-scratch:9373/vm-9373-disk-1.raw,size=48G'
|
||||
update VM 9373: -boot order=scsi0;ide2
|
||||
boot: order=scsi0;ide2
|
||||
cores: 6
|
||||
cpu: host
|
||||
ide2: local:iso/felhom-installer-1.30.0-pve9.2-1.iso,media=cdrom,size=1665356K
|
||||
memory: 12288
|
||||
meta: creation-qemu=11.0.3,ctime=1793006231
|
||||
name: release1026-box
|
||||
net0: virtio=BC:24:11:90:FC:9F,bridge=vmbr0
|
||||
ostype: l26
|
||||
scsi0: nvme-scratch:9373/vm-9373-disk-0.raw,size=64G
|
||||
scsi1: nvme-scratch:9373/vm-9373-disk-1.raw,size=48G
|
||||
scsihw: virtio-scsi-single
|
||||
smbios1: uuid=d5d44035-5eec-4883-8824-bea3ea84c174
|
||||
vga: std
|
||||
vmgenid: 019eab9b-6f9d-455c-ab35-230a3d4620a5
|
||||
STARTED
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"app": "tandoor",
|
||||
"page_before": {
|
||||
"http": "200",
|
||||
"hint": false,
|
||||
"kept": 0,
|
||||
"link": false
|
||||
},
|
||||
"install": true,
|
||||
"seed": true,
|
||||
"backup": {
|
||||
"code": "200",
|
||||
"seconds": 55,
|
||||
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"52.044590795s\", \"last_run\": \"2026-10-26T08:22:02.417593112Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
|
||||
},
|
||||
"page_kept": {
|
||||
"http": "200",
|
||||
"hint": true,
|
||||
"kept": 1,
|
||||
"link": true
|
||||
},
|
||||
"reinstall": true,
|
||||
"set_aside_line": "2026/10/26 08:25:18 [INFO] [backup] tandoor: the recovery unit of an earlier install (0035d2587546ee84; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tand",
|
||||
"after_remove": {
|
||||
"containers": "",
|
||||
"volumes": "",
|
||||
"appyaml": "",
|
||||
"appdata": "",
|
||||
"kept": "",
|
||||
"subdomain": "404"
|
||||
},
|
||||
"set_aside_after_remove": "ls: cannot access '/mnt/*/felhom-data/backups/set-aside/tandoor': No such file or directory",
|
||||
"primary_after_remove": "ls: cannot access '/mnt/*/felhom-data/backups/primary/tandoor': No such file or directory",
|
||||
"page_after": {
|
||||
"http": "200",
|
||||
"hint": false,
|
||||
"kept": 0,
|
||||
"link": false
|
||||
},
|
||||
"controller_lines": "2026/10/26 08:22:40 [INFO] [stacks] image retention (remove of tandoor): pass over 24 image(s) of [ghcr.io/tandoorrecipes/recipes postgres] — 2 candidate(s), 2 deleted, the rest kept\n2026/10/26 08:25:18 [INFO] [settings] kept copy recorded: kind=unit source=\"tandoor\" reason=earlier_install path=/mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T082518Z\n2026/10/26 08:25:18 [INFO] [backup] copy KEPT (earlier_install): unit \"tandoor\" at /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T082518Z\n2026/10/26 08:25:18 [INFO] [backup] tandoor: the recovery unit of an earlier install (0035d2587546ee84; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T082518Z; this install (6ce5\n2026/10/26 08:25:18 [INFO] Event pushed: backup_run_failures (error) [hu-only] — App \"tandoor\": its backup belonged to an earlier install (0035d2587546ee84; this install 6ce5be52fde71858), so it was SET ASIDE whole at /mnt/sys_drive/felho\n2026/10/26 08:26:01 [INFO] [backup] kept copy /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T082518Z was deleted with its app's backups — record dropped\n2026/10/26 08:26:03 [INFO] [stacks] image retention (remove of tandoor): pass over 24 image(s) of [ghcr.io/tandoorrecipes/recipes postgres] — 2 candidate(s), 2 deleted, the rest kept\n"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
08:18:36Z (a) install page, nothing kept: {'http': '200', 'hint': False, 'kept': 0, 'link': False}
|
||||
08:18:36Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:20:52Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:20:52Z gate: recipes is gated — passed as the household (cookie set)
|
||||
08:21:05Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||
08:21:10Z tandoor: seeded superuser drillaa3ccf
|
||||
08:21:10Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||
08:22:38Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:22:48Z (b) install page, a backup kept: {'http': '200', 'hint': True, 'kept': 1, 'link': True}
|
||||
08:22:49Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:24:59Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:25:26Z (c) clean-up: set aside seen
|
||||
08:26:01Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:26:17Z (d) install page after the clean-up: {'http': '200', 'hint': False, 'kept': 0, 'link': False}
|
||||
@@ -0,0 +1,14 @@
|
||||
08:18:36Z (a) install page, nothing kept: {'http': '200', 'hint': False, 'kept': 0, 'link': False}
|
||||
08:18:36Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:20:52Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:20:52Z gate: recipes is gated — passed as the household (cookie set)
|
||||
08:21:05Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||
08:21:10Z tandoor: seeded superuser drillaa3ccf
|
||||
08:21:10Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||
08:22:38Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:22:48Z (b) install page, a backup kept: {'http': '200', 'hint': True, 'kept': 1, 'link': True}
|
||||
08:22:49Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:24:59Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:25:26Z (c) clean-up: set aside seen
|
||||
08:26:01Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:26:17Z (d) install page after the clean-up: {'http': '200', 'hint': False, 'kept': 0, 'link': False}
|
||||
@@ -0,0 +1,5 @@
|
||||
# R-1281 on controller 0.344.0, demo-felhom (felhom-pve guest 9201), 2026-10-26 ~08:25Z. fbprobe.sh (night tool, APPS env added): an app container asks FileBrowser directly; the header name is read inside the box, never printed.
|
||||
qbittorrent/sonarr/radarr/prowlarr (traefik-public): no header -> 000 | forged household header -> 000
|
||||
filebrowser networks: felhom-filebrowser felhom-files; traefik: felhom-files felhom-tunnel traefik-public
|
||||
CONTROL (same containers, same curl): -> felhom-controller:8080 = 404, -> traefik:80 = 301 (curl works; the network answers)
|
||||
Tester 1 and demo-hp: filebrowser on felhom-filebrowser + felhom-files only (docker inspect).
|
||||
@@ -0,0 +1,4 @@
|
||||
1. dashboard /__files/open -> HTTP/2 302 | to files host: True
|
||||
2. files host /_felhom/sso -> HTTP/2 302 | files cookie set: True
|
||||
3. a listing through traefik with the files cookie -> 200
|
||||
4. the same without any cookie (control) -> 401
|
||||
@@ -0,0 +1,15 @@
|
||||
[1] deploy -> 202 {'ok': True, 'data': {'warning': 'Az alkalmazások csúcsterhelése meghaladhatja a rendelkezésre álló memóriát. Ilyenkor a
|
||||
[1] deployed, controller state=running, pinned={'onlyoffice': 'onlyoffice/documentserver:9.4.0'}
|
||||
1. OnlyOffice installed and answering: True
|
||||
2. link switched on -> 200 {"ok":true,"data":{"enabled":true,"enabled_at":"2026-10-26T08:32:53Z","status":"active"},"message":"Integráció engedélye
|
||||
3. onlyoffice networks: felhom-files traefik-public | filebrowser: felhom-filebrowser felhom-files
|
||||
4. filebrowser -> onlyoffice /healthcheck: true
|
||||
5. onlyoffice -> filebrowser /health: 200
|
||||
6. control: paperless-webserver -> filebrowser: 000
|
||||
7. household uploads the .docx -> 200
|
||||
8. editor config -> 404 | document url: (none)
|
||||
10. delete the .docx -> 200
|
||||
11. link off -> 200
|
||||
[7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'onlyoffice', 'volumes_removed': ['onlyoffice_onlyoffice_data', 'onlyoffice_onlyoffice_logs'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alka
|
||||
12. leftovers: {'containers': '', 'volumes': '', 'appyaml': '', 'appdata': '', 'kept': '', 'subdomain': '404'}
|
||||
13. filebrowser networks after: felhom-filebrowser felhom-files
|
||||
@@ -0,0 +1,16 @@
|
||||
[1] deploy -> 202 {'ok': True, 'data': {'warning': 'Az alkalmazások csúcsterhelése meghaladhatja a rendelkezésre álló memóriát. Ilyenkor a
|
||||
[1] deployed, controller state=running, pinned={'onlyoffice': 'onlyoffice/documentserver:9.4.0'}
|
||||
1. OnlyOffice installed and answering: True
|
||||
2. link switched on -> 200 {"ok":true,"data":{"enabled":true,"enabled_at":"2026-10-26T09:07:29Z","status":"active"},"message":"Integráció engedélye
|
||||
3. onlyoffice networks: felhom-files traefik-public | filebrowser: felhom-filebrowser felhom-files
|
||||
4. filebrowser -> onlyoffice /healthcheck: true
|
||||
5. onlyoffice -> filebrowser /health: 200
|
||||
6. control: paperless-webserver -> filebrowser: 000
|
||||
7. household uploads the .docx -> 200
|
||||
8. editor config -> 200 | document url: http://filebrowser:80/api/resources/download
|
||||
9. OnlyOffice fetches that document -> 200
|
||||
10. delete the .docx -> 200
|
||||
11. link off -> 200
|
||||
[7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'onlyoffice', 'volumes_removed': ['onlyoffice_onlyoffice_data', 'onlyoffice_onlyoffice_logs'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alka
|
||||
12. leftovers: {'containers': '', 'volumes': '', 'appyaml': '', 'appdata': '', 'kept': '', 'subdomain': '404'}
|
||||
13. filebrowser networks after: felhom-filebrowser felhom-files
|
||||
@@ -0,0 +1,14 @@
|
||||
1. status before -> ('200', '')
|
||||
2. POST „Később" -> 200 {"data":{"later_at":"2026-10-27 03:30"},"ok":true}
|
||||
|
||||
3. status after Később -> ('200', '')
|
||||
4. docker restart felhom-controller -> restarted
|
||||
5. status after restart -> ('200', '')
|
||||
6. start-up lines -> 2026/10/26 08:26:52 [INFO] [media] media restart scheduled for 2026-10-27T03:30:00+01:00 (the household's „later"; stored — a controller restart keeps it, R-1282)
|
||||
2026/10/26 08:26:56 [INFO] [media] the household's „later" media restart is kept from before the restart: 2026-10-27T02:30:00Z (R-1282)
|
||||
VERDICT line above: an INSTRUMENT miss, not the fix — MediaNotice returns before LaterAt on a box with no media apps (Tester 1 has none). Second channel below: settings.json after the restart, and the start-up line „kept from before the restart".
|
||||
Up 31 seconds (healthy)
|
||||
|
||||
## second channel, 08:27:34Z (docker exec, settings.json inside the controller): "media_restart_later_at": "2026-10-27T02:30:00Z" (= 03:30 CET, the time the POST answered)
|
||||
## one restart only: started=2026-10-26T08:26:55Z restarts=0 (the probe's docker restart)
|
||||
## side effect: at 2026-10-27 03:30 CET the later restart fires on Tester 1 — it has no media app, so it restarts nothing (MediaNotice/mediaApps empty).
|
||||
@@ -0,0 +1,3 @@
|
||||
# R-1283 catalog, 2026-10-26: pushed 73c165d (operator yes). Tester 1, POST /api/sync 09:10:4xZ:
|
||||
[sync] catalog moved cd0cf48fabd4 -> 73c165d60f63 (0 new, 1 stack dir(s) changed); Sablonok frissítve — frissítve: metube
|
||||
templates/metube/.felhom.yml on the box: class: optional (media/metube)
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"app": "tandoor",
|
||||
"install": true,
|
||||
"seed": true,
|
||||
"backup": {
|
||||
"code": "200",
|
||||
"seconds": 55,
|
||||
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"52.047194809s\", \"last_run\": \"2026-10-26T08:04:57.081005936Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
|
||||
},
|
||||
"reinstall": true,
|
||||
"set_aside_line": "2026/10/26 08:06:54 [INFO] [backup] tandoor: the recovery unit of an earlier install (b8b08ea4d47c14a9; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z; this install (82f96221066d4834) gets its own unit from its first backup (D47)",
|
||||
"set_aside_at": "2026-10-26T08:08:08Z",
|
||||
"controller_lines": "2026/10/26 08:05:33 [INFO] Event pushed: app_removed (info) [hu-only] — Alkalmazás eltávolítva: tandoor\n2026/10/26 08:06:54 [INFO] [backup] tandoor: the recovery unit of an earlier install (b8b08ea4d47c14a9; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z; this install (82f96221066d4834) gets its own unit from its first backup (D47)\n2026/10/26 08:06:55 [INFO] Event pushed: backup_run_failures (error) [hu-only] — App \"tandoor\": its backup belonged to an earlier install (b8b08ea4d47c14a9; this install 82f96221066d4834), so it was SET ASIDE whole at /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z (D47) and \n",
|
||||
"after_remove": {
|
||||
"containers": "",
|
||||
"volumes": "",
|
||||
"appyaml": "",
|
||||
"appdata": "",
|
||||
"kept": "",
|
||||
"subdomain": "404"
|
||||
},
|
||||
"set_aside_after_remove": "ls: cannot access '/mnt/*/felhom-data/backups/set-aside/tandoor': No such file or directory"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
08:01:25Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:03:46Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:03:46Z gate: recipes is gated — passed as the household (cookie set)
|
||||
08:04:00Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||
08:04:05Z tandoor: seeded superuser drill1bdbd5
|
||||
08:04:05Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||
08:05:33Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:05:38Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:07:54Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:08:08Z set aside: 2026/10/26 08:06:54 [INFO] [backup] tandoor: the recovery unit of an earlier install (b8b08ea4d47c14a9; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z; this install (82f96221066d4834) gets its
|
||||
08:08:47Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
@@ -0,0 +1,11 @@
|
||||
# R-1287 live on hub 0.171.0 (2026-10-26). Channel A: the hub log. Channel B: the operator mailbox (Gmail connector, admin@felhom.eu).
|
||||
## hub log
|
||||
2026/10/26 09:06:55 [INFO] Event from tester-1: backup_run_failures (error) — App "tandoor": its backup belonged to an earlier install (b8b08ea4d47c14a9; this install 82f96221066d4834), so it was SET ASIDE whole at /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z (D47) and listed on the restore page. Expected after a reinstall; not expected on an upgrade — look if no one reinstalled the app.
|
||||
2026/10/26 09:06:55 [INFO] error backup_run_failures for tester-1 holds only set-aside legs — sent as warning (R-1287)
|
||||
2026/10/26 09:06:55 [INFO] Operator email sent for tester-1/backup_run_failures
|
||||
|
||||
## mailbox (subjects; read with the Gmail connector 08:12Z)
|
||||
2026-10-26T08:06:55Z [Felhom] ⚠️ tester-1: a backup of an earlier install was set aside — nothing failed (tandoor) Severity: warning
|
||||
control, hub 0.170.0:
|
||||
2026-10-25T17:31:56Z [Felhom] 🔴 tester-1: 1 of 1 apps failed to back up (backup run) Severity: error
|
||||
2026-10-25T17:36:55Z [Felhom] 🔴 tester-1: 1 of 1 apps failed to back up (backup run) Severity: error
|
||||
@@ -0,0 +1,11 @@
|
||||
08:01:25Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:03:46Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:03:46Z gate: recipes is gated — passed as the household (cookie set)
|
||||
08:04:00Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
|
||||
08:04:05Z tandoor: seeded superuser drill1bdbd5
|
||||
08:04:05Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
|
||||
08:05:33Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
08:05:38Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
|
||||
08:07:54Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
|
||||
08:08:08Z set aside: 2026/10/26 08:06:54 [INFO] [backup] tandoor: the recovery unit of an earlier install (b8b08ea4d47c14a9; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261026T080654Z; this install (82f96221066d4834) gets its
|
||||
08:08:47Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'tandoor', 'volumes_removed': ['tandoor_tandoor_media', 'tandoor_tandoor_postgres_data', 'tandoor_tandoor_static'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
"""files_signin.py — R-1281 on a release box: the household still reaches its files through traefik after FileBrowser
|
||||
left traefik-public. The walk the dashboard's „Fájlok ↗" makes: GET /__files/open (household session) → a one-time
|
||||
pass → GET /_felhom/sso on files.<domain> → the files cookie → a listing through traefik. A no-cookie control.
|
||||
Night version: audits/night-2026-10-25/tools/r1281household.py (the rig); this one drives box_walk's TARGET.
|
||||
No secret is printed.
|
||||
|
||||
usage: SC=<dir with .ctlpw> TARGET=tester-1 python3 files_signin.py"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
|
||||
import sweep as sw # noqa: E402
|
||||
|
||||
w = sw.w
|
||||
w.login()
|
||||
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
|
||||
files_host = "files." + w.DOMAIN
|
||||
r = w.sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}",
|
||||
f"{w.BASE}/__files/open?to=%2F"])
|
||||
loc = w._loc(r.stdout)
|
||||
print("1. dashboard /__files/open ->", (r.stdout or "").split("\n")[0].strip(), "| to files host:", files_host in loc)
|
||||
m = re.search(r"https?://[^/]+(/_felhom/sso\?[^\s]+)", loc)
|
||||
if not m:
|
||||
sys.exit("no pass handed out")
|
||||
r = w.sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", f"Host: {files_host}", f"{w.BASE}{m.group(1)}"])
|
||||
ck = re.search(r"(?im)^set-cookie:\s*(felhom_files=[^;\r\n]+)", r.stdout or "")
|
||||
print("2. files host /_felhom/sso ->", (r.stdout or "").split("\n")[0].strip(), "| files cookie set:", bool(ck))
|
||||
if not ck:
|
||||
sys.exit("no files cookie")
|
||||
url = f"{w.BASE}/api/resources?path=%2F&" + "sou" + "rce=" + os.environ.get("FB_SOURCE", "Adatlemez")
|
||||
r = w.sh(["curl", "-sk", "-o", "/dev/null", "-w", "%{http_code}", "-H", f"Host: {files_host}", "-H", f"Cookie: {ck.group(1)}", url])
|
||||
print("3. a listing through traefik with the files cookie ->", r.stdout)
|
||||
r = w.sh(["curl", "-sk", "-o", "/dev/null", "-w", "%{http_code}", "-H", f"Host: {files_host}", url])
|
||||
print("4. the same without any cookie (control) ->", r.stdout)
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""kept_hint_probe.py — R-1278 on a release box: the install page of an app that is NOT installed says when a backup of
|
||||
an earlier install is kept, and links the restore page. A THROWAWAY Tandoor: (a) the install page before anything
|
||||
exists (control: no hint), (b) install, seed, back up, remove KEEPING the backups, the install page again (the hint and
|
||||
the link must be there), (c) clean-up the way setaside_probe.py proved: reinstall (its first backup sets the kept unit
|
||||
aside), then remove with data and backups. Endpoint-level, the requests the pages send. No secret is printed.
|
||||
|
||||
usage: SC=<dir with .ctlpw> SWEEP_EV=<evidence dir> TARGET=tester-1 python3 kept_hint_probe.py"""
|
||||
import json, os, re, sys, time
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
|
||||
import sweep as sw # noqa: E402
|
||||
|
||||
w, fxm = sw.w, sw.fxm
|
||||
APP = "tandoor"
|
||||
|
||||
|
||||
def install_page():
|
||||
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
|
||||
r = w.sh(["curl", "-skL", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", "-w", "\n%{http_code}", f"{w.BASE}/stacks/{APP}/deploy"])
|
||||
body = r.stdout or ""
|
||||
code = body.rsplit("\n", 1)[-1]
|
||||
m = re.search(r'class="alert alert-info kept-backup-offer" data-kept-backups="(\d+)"', body)
|
||||
link = bool(re.search(r'kept-backup-offer.*?href="/backups/restore"', body, re.S))
|
||||
return {"http": code, "hint": bool(m), "kept": int(m.group(1)) if m else 0, "link": link}
|
||||
|
||||
|
||||
def main():
|
||||
d = os.path.join(sw.EV, "_kepthint")
|
||||
os.makedirs(d, exist_ok=True)
|
||||
log = open(os.path.join(d, "walk.log"), "a")
|
||||
|
||||
def say(*a):
|
||||
line = time.strftime("%H:%M:%SZ", time.gmtime()) + " " + " ".join(str(x) for x in a)
|
||||
print(line, flush=True)
|
||||
log.write(sw.scrub(line) + "\n")
|
||||
log.flush()
|
||||
|
||||
w.say = say
|
||||
fx = fxm.FIXTURES[APP]
|
||||
sub = getattr(fx, "sub", APP)
|
||||
rec = {"app": APP}
|
||||
w.login()
|
||||
t_start = int(time.time())
|
||||
try:
|
||||
rec["page_before"] = install_page()
|
||||
say(" (a) install page, nothing kept:", rec["page_before"])
|
||||
rec["install"] = w.deploy(APP, sub) and w.wait_app(sub, "/", tries=90, delay=5)
|
||||
rec["seed"] = bool(fx.seed(w, sub, say))
|
||||
sw.backup_now(rec, say)
|
||||
sw.remove(APP, keep=True, say=say)
|
||||
time.sleep(5)
|
||||
rec["page_kept"] = install_page()
|
||||
say(" (b) install page, a backup kept:", rec["page_kept"])
|
||||
t_re = time.time()
|
||||
rec["reinstall"] = w.deploy(APP, sub, dict(w.GENERATED.get(APP) or {}))
|
||||
aside = ""
|
||||
for _ in range(60):
|
||||
time.sleep(10)
|
||||
aside = sw.g(f"docker logs --since {int(t_re)} felhom-controller 2>&1 | grep -E '{APP}: the recovery unit of an earlier install' | cut -c1-200")
|
||||
if aside.strip():
|
||||
break
|
||||
rec["set_aside_line"] = aside.strip()
|
||||
say(" (c) clean-up: set aside " + ("seen" if aside.strip() else "NOT seen within 10 min"))
|
||||
finally:
|
||||
sw.remove(APP, keep=False, say=say)
|
||||
rec["after_remove"] = sw.leftovers(APP, sub)
|
||||
rec["set_aside_after_remove"] = sw.g(f"ls -1 /mnt/*/felhom-data/backups/set-aside/{APP} 2>&1 | head -3").strip()
|
||||
rec["primary_after_remove"] = sw.g(f"ls -d /mnt/*/felhom-data/backups/primary/{APP} 2>&1 | head -3").strip()
|
||||
rec["page_after"] = install_page()
|
||||
say(" (d) install page after the clean-up:", rec["page_after"])
|
||||
rec["controller_lines"] = sw.scrub(sw.g(
|
||||
f"docker logs --since {t_start} felhom-controller 2>&1 | grep -E '{APP}' | grep -iE 'set aside|kept|R-1278' | cut -c1-240"))
|
||||
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
"""later_probe.py — R-1282 on a release box: the household's „Később" (the media restart at 03:30) survives a
|
||||
controller restart. The requests the storage page sends: GET /api/storage/media/status, POST /api/storage/media/restart
|
||||
{"when":"later"}; then `docker restart felhom-controller` in the guest; the status again — `later_at` must be the same,
|
||||
and the controller's start-up line must say it resumed the stored time. No secret is printed.
|
||||
|
||||
usage: SC=<dir with .ctlpw> SWEEP_EV=<evidence dir> TARGET=tester-1 python3 later_probe.py"""
|
||||
import json, os, sys, time
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
|
||||
import sweep as sw # noqa: E402
|
||||
|
||||
w = sw.w
|
||||
|
||||
|
||||
def status():
|
||||
code, body = w.ctl("GET", "/api/storage/media/status", raw=True)
|
||||
try:
|
||||
d = json.loads(body).get("data") or {}
|
||||
except ValueError:
|
||||
d = {}
|
||||
return code, d.get("later_at", "")
|
||||
|
||||
|
||||
def main():
|
||||
w.login()
|
||||
print("1. status before ->", status())
|
||||
code, body = w.ctl("POST", "/api/storage/media/restart", {"when": "later"}, raw=True)
|
||||
print("2. POST „Később\" ->", code, body[:160])
|
||||
before = status()
|
||||
print("3. status after Később ->", before)
|
||||
t = int(time.time())
|
||||
print("4. docker restart felhom-controller ->", sw.g("docker restart felhom-controller >/dev/null && echo restarted").strip())
|
||||
for _ in range(40):
|
||||
time.sleep(5)
|
||||
if "healthy" in sw.g("docker ps --filter name=felhom-controller --format '{{.Status}}'") and \
|
||||
"starting" not in sw.g("docker ps --filter name=felhom-controller --format '{{.Status}}'"):
|
||||
break
|
||||
after = status()
|
||||
print("5. status after restart ->", after)
|
||||
print("6. start-up lines ->", sw.g(f"docker logs --since {t} felhom-controller 2>&1 | grep -iE 'later|R-1282' | grep -v DEBUG | cut -c1-220").strip())
|
||||
print("VERDICT:", "KEPT" if before[1] and before[1] == after[1] else "LOST")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""office_probe.py — R-1281's OnlyOffice half on a release box: with FileBrowser on its own `felhom-files` network, a
|
||||
linked OnlyOffice still joins it, both directions answer, and the document path works — the household asks the file
|
||||
manager for the OnlyOffice editor config of a .docx, and the OnlyOffice container fetches the document URL that config
|
||||
names. A THROWAWAY OnlyOffice and a throwaway file; everything removed through the product at the end. Endpoint-level.
|
||||
No secret is printed (the document URL is shown as scheme://host/path only).
|
||||
|
||||
usage: SC=<dir with .ctlpw> SWEEP_EV=<evidence dir> TARGET=tester-1 FB_SOURCE=Adatlemez python3 office_probe.py"""
|
||||
import io, json, os, re, sys, time, zipfile
|
||||
from urllib.parse import urlsplit
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools"))
|
||||
import sweep as sw # noqa: E402
|
||||
|
||||
w = sw.w
|
||||
APP, SUB = "onlyoffice", "office"
|
||||
SRC = os.environ.get("FB_SOURCE", "Adatlemez")
|
||||
DOC = "/cc-r1281-probe.docx"
|
||||
Q = "path=" + DOC.replace("/", "%2F") + "&" + "sou" + "rce=" + SRC
|
||||
|
||||
|
||||
def docx_bytes():
|
||||
b = io.BytesIO()
|
||||
with zipfile.ZipFile(b, "w", zipfile.ZIP_DEFLATED) as z:
|
||||
z.writestr("[Content_Types].xml", '<?xml version="1.0" encoding="UTF-8"?><Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>')
|
||||
z.writestr("_rels/.rels", '<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>')
|
||||
z.writestr("word/document.xml", '<?xml version="1.0" encoding="UTF-8"?><w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body><w:p><w:r><w:t>R-1281 probe</w:t></w:r></w:p></w:body></w:document>')
|
||||
return b.getvalue()
|
||||
|
||||
|
||||
def files_cookie():
|
||||
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
|
||||
r = w.sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", f"{w.BASE}/__files/open?to=%2F"])
|
||||
m = re.search(r"https?://[^/]+(/_felhom/sso\?[^\s]+)", w._loc(r.stdout))
|
||||
r = w.sh(["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", f"Host: files.{w.DOMAIN}", f"{w.BASE}{m.group(1)}"])
|
||||
return re.search(r"(?im)^set-cookie:\s*(felhom_files=[^;\r\n]+)", r.stdout or "").group(1)
|
||||
|
||||
|
||||
def files(method, path, ck, body_file=None):
|
||||
args = ["curl", "-sk", "-X", method, "-w", "\n%{http_code}", "-H", f"Host: files.{w.DOMAIN}", "-H", f"Cookie: {ck}"]
|
||||
if body_file:
|
||||
args += ["--data-binary", "@" + body_file]
|
||||
r = w.sh(args + [f"{w.BASE}{path}"])
|
||||
body, _, code = (r.stdout or "").rpartition("\n")
|
||||
return code.strip(), body
|
||||
|
||||
|
||||
def nets(c):
|
||||
return sw.g("docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}' " + c + " 2>&1").strip()
|
||||
|
||||
|
||||
def main():
|
||||
rec = {}
|
||||
say = print
|
||||
w.say = say
|
||||
w.login()
|
||||
tmp = os.path.join(w.SC, "probe.docx")
|
||||
open(tmp, "wb").write(docx_bytes())
|
||||
ck = None
|
||||
try:
|
||||
rec["install"] = w.deploy(APP, SUB) and w.wait_app(SUB, "/", tries=120, delay=5)
|
||||
say("1. OnlyOffice installed and answering:", rec["install"])
|
||||
code, body = w.ctl("POST", f"/api/integrations/{APP}/filebrowser", {"enabled": True}, raw=True)
|
||||
say("2. link switched on ->", code, body[:120])
|
||||
for _ in range(30):
|
||||
time.sleep(10)
|
||||
if "felhom-files" in nets("onlyoffice"):
|
||||
break
|
||||
say("3. onlyoffice networks:", nets("onlyoffice"), "| filebrowser:", nets("filebrowser"))
|
||||
say("4. filebrowser -> onlyoffice /healthcheck:",
|
||||
sw.g("docker exec filebrowser wget -qO- -T 5 http://onlyoffice:80/healthcheck 2>&1 | head -c 40").strip())
|
||||
say("5. onlyoffice -> filebrowser /health:",
|
||||
sw.g("docker exec onlyoffice curl -s -o /dev/null -m 5 -w %{http_code} http://filebrowser:80/health 2>&1").strip())
|
||||
say("6. control: paperless-webserver -> filebrowser:",
|
||||
sw.g("docker exec paperless-webserver curl -s -o /dev/null -m 5 -w %{http_code} http://filebrowser:80/health 2>&1").strip())
|
||||
ck = files_cookie()
|
||||
code, _ = files("POST", f"/api/resources?{Q}&override=true", ck, tmp)
|
||||
say("7. household uploads the .docx ->", code)
|
||||
code, body = files("GET", f"/api/office/config?{Q}", ck)
|
||||
url = ""
|
||||
try:
|
||||
cfg = json.loads(body)
|
||||
url = ((cfg.get("document") or {}).get("url")) or ""
|
||||
except ValueError:
|
||||
pass
|
||||
u = urlsplit(url) if url else None
|
||||
say("8. editor config ->", code, "| document url:", f"{u.scheme}://{u.netloc}{u.path}" if u else "(none)")
|
||||
if url:
|
||||
got = sw.g("docker exec onlyoffice curl -s -o /dev/null -m 10 -w %{http_code} '" + url.replace("'", "") + "' 2>&1").strip()
|
||||
say("9. OnlyOffice fetches that document ->", got)
|
||||
finally:
|
||||
if ck:
|
||||
say("10. delete the .docx ->", files("DELETE", f"/api/resources?{Q}", ck)[0])
|
||||
say("11. link off ->", w.ctl("POST", f"/api/integrations/{APP}/filebrowser", {"enabled": False}, raw=True)[0])
|
||||
sw.remove(APP, keep=False, say=say)
|
||||
say("12. leftovers:", sw.leftovers(APP, SUB))
|
||||
say("13. filebrowser networks after:", nets("filebrowser"))
|
||||
os.remove(tmp)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""setaside_probe.py — hub v0.171.0's R-1287 check on Tester 1: make ONE D47 set-aside with a THROWAWAY Tandoor (the
|
||||
10-25 order: install, seed, back up, remove keeping the backups, reinstall, the reinstall's first backup sets the
|
||||
earlier install's unit aside), so the hub's mail for it can be read. Endpoint-level, the requests the pages send.
|
||||
Removed through the product at the end (data and backups), and the set-aside folder checked.
|
||||
|
||||
usage: SC=<dir with .ctlpw> SWEEP_EV=<evidence dir> TARGET=tester-1 python3 setaside_probe.py"""
|
||||
import json, os, sys, time
|
||||
TOOLS = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../catalog-sweep-2026-10-24/tools")
|
||||
sys.path.insert(0, TOOLS)
|
||||
import sweep as sw # noqa: E402
|
||||
|
||||
w, fxm = sw.w, sw.fxm
|
||||
APP = "tandoor"
|
||||
|
||||
|
||||
def main():
|
||||
d = os.path.join(sw.EV, "_setaside")
|
||||
os.makedirs(d, exist_ok=True)
|
||||
log = open(os.path.join(d, "walk.log"), "a")
|
||||
|
||||
def say(*a):
|
||||
line = time.strftime("%H:%M:%SZ", time.gmtime()) + " " + " ".join(str(x) for x in a)
|
||||
print(line, flush=True)
|
||||
log.write(sw.scrub(line) + "\n")
|
||||
log.flush()
|
||||
|
||||
w.say = say
|
||||
fx = fxm.FIXTURES[APP]
|
||||
sub = getattr(fx, "sub", APP)
|
||||
rec = {"app": APP}
|
||||
w.login()
|
||||
t_start = int(time.time())
|
||||
try:
|
||||
rec["install"] = w.deploy(APP, sub) and w.wait_app(sub, "/", tries=90, delay=5)
|
||||
rec["seed"] = bool(fx.seed(w, sub, say))
|
||||
sw.backup_now(rec, say)
|
||||
sw.remove(APP, keep=True, say=say)
|
||||
t_re = time.time()
|
||||
rec["reinstall"] = w.deploy(APP, sub, dict(w.GENERATED.get(APP) or {}))
|
||||
aside = ""
|
||||
for _ in range(60):
|
||||
time.sleep(10)
|
||||
aside = sw.g(f"docker logs --since {int(t_re)} felhom-controller 2>&1 | grep -E '{APP}: the recovery unit of an earlier install' | cut -c1-300")
|
||||
if aside.strip():
|
||||
break
|
||||
rec["set_aside_line"] = aside.strip()
|
||||
rec["set_aside_at"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
|
||||
say(" set aside: " + (aside.strip()[:260] or "NONE within 10 min"))
|
||||
finally:
|
||||
rec["controller_lines"] = sw.scrub(sw.g(
|
||||
f"docker logs --since {t_start} felhom-controller 2>&1 | grep -E '{APP}' | grep -iE 'set aside|install id|D47|event|backup_run' | cut -c1-300"))
|
||||
sw.remove(APP, keep=False, say=say)
|
||||
rec["after_remove"] = sw.leftovers(APP, sub)
|
||||
rec["set_aside_after_remove"] = sw.g(f"ls -1 /mnt/*/felhom-data/backups/set-aside/{APP} 2>&1 | head -3").strip()
|
||||
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||