Restore-truth run (2026-10-25): D47 + D48 recorded (09 §3 decisions 256, 257; CONTEXT); 07 §6.5 (R-1271 cause + the future-date rule), §6.6 (D48 order, the R-698 sentence), §8.2d (D47), §8.2e (R-1270); register 217 -> 219 (R-1278, R-1279 opened; R-1269/1270/1271 VERIFY; notes R-1206, R-1243 dated check done read-only, R-232 moved one day); STATUS D49 + Monday list; evidence (9202)
gates / gates (push) Successful in 13m44s

This commit is contained in:
admin committed 2026-10-25 11:04:46 +01:00
1 parent 67053335d1
commit 9647f1d158
58 files changed
+1834 -14

No files matched your search

@@ -0,0 +1,90 @@
# A backup is never changed by a new install, a restore downloads first, and a restore tells the truth (2026-10-25)
Brief: Sunday 2026-10-25, up to 12 h, commit only. Operator rulings D47 and D48 (2026-10-25 08:38, `09` §3 decisions
256, 257). Box: scratch guest **9202** on demo-hp (`ssh hp`), controller 0.342.0 for the BEFORE proofs (its restore,
unit and kept-data code is byte-identical to `e1613ae`: no commit between `42cda07` and `e1613ae` touched
`recovery_unit.go`, `restore_unit.go`, `restore_dbcreds.go`), then **0.343.0-rc.1** built from `bd9f4f7` (an `-rc` tag
is never offered to a household) for the AFTER proofs; 0.342.0 put back at the end.
## Safest readings taken (the brief allowed no question)
1. **Install identity:** a new field `install_id` (16 random hex), not the data stamps — the stamps say which VERSION
wrote the data, not which install. A unit from before D47 has none: then a carried secret that differs on both sides
means another install (a reinstall mints new ones); with no differing secret it is this install's (the old behaviour).
2. **Where the set-aside unit lives and how it is removed:** `<namespace>/backups/set-aside/<app>/<UTC stamp>/` on its
own drive (a rename), recorded as a D25 kept copy — listed on the restore page with „Visszaállítás" and
„Eltávolítás". The app's remove with „delete its backups too" deletes it too: the D25 / R-1252 H9 rule for kept copies.
3. **A „partial write"** = one half (definition or data) written into a unit whose other half belongs to another
install. The writer refuses it when the set-aside cannot be done. A definition-only unit of a fresh install (no data
yet) is not partial — it is that install's whole unit.
4. **R-1270 (the brief's own safest reading):** a health timeout does not pour the old data back; the data stays, the
undo copy is kept (the „kept for support" state a failed put-back leaves — no new retention rule), a late start
within 30 minutes turns the record into a success and releases the copy.
5. **D48 sentences:** Docker's „manifest unknown / not found / pull access denied / repository does not exist" reads as
„the maker no longer offers it"; everything else (busy, rate limit, timeout, unreachable) as „try again later".
6. **R-1271:** the clock-skew allowance is **10 minutes**. A future-dated copy that is the only copy is still offered
(it may be the household's own), marked and not recommended. The „another drive" check stays a path check (the
brief: an old box's data on a new box is what off-site is for).
7. **The `.fab` import is not a „unit" path** and is not changed here; its gap is a row (R-1279).
## Before (9202, controller 0.342.0 = `e1613ae` for these files) — `before/`
`catalog-sweep-2026-10-24/tools/unitprobe.py tandoor` on 9202 (`before/_unitprobe/tandoor/`): install, one account,
„Mentés most" (unit 07:53:46), remove keeping data and backups, install again, wait for the controller's next capture,
„Visszaállítás".
- **R-1269:** 08:00:36 „Recovery unit captured for tandoor" — the kept unit's `app.yaml` checksum `cbfcb538…` →
`e19d2610…`, `created_at` 07:53:46 → 08:00:36, the data files unchanged. Cause at `file:line`:
`felhom-controller/controller/internal/backup/recovery_unit.go:194` (`e1613ae`) — the refresh's only „same
definition" test is the pins (`frozen`), and a reinstall of the same version has the same pins; the writes at
`:254-258` then put the new install's `app.yaml` (its new database password) beside the old data. The restore takes
the unit's password (`restore_dbcreds.go` R-1106 rule) — the new one — over the old data directory.
- **R-1270:** the restore record `ok: true`, „A(z) tandoor: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás
újraindult." while the app stayed `starting`; `password authentication failed` ×44 (app) / ×23 (postgres); the account
not there (`restore_unit.go:567-569` at `e1613ae`: the health failure is a WARN).
- **Why a volume app's reinstall asks no kept-data question:** the question is about the app's drive FOLDER
(`${HDD_PATH}` binds under `appdata/`, `stacks/kept.go` `OldAppDataPaths`; `07` §6.5, decision 36). Tandoor keeps
nothing there; „remove, keep my data" removed its three named volumes (the record's `volumes_removed`) and kept only
its backup. A gap for the household → **R-1278**.
## After (9202, controller 0.343.0-rc.2 = `1f9c863`) — `after/`
| proof | before (`e1613ae`) | after |
|---|---|---|
| **R-1269 / D47, Tandoor** (`tools/unitprobe2.py`, `after/_unitprobe2/tandoor/`) | the refresh rewrote the kept unit's `app.yaml`; the restore paired the new password with the old data, `starting`, account gone | 09:13:03 „the recovery unit of an earlier install (77ea…; the install ids differ) is SET ASIDE whole → `backups/set-aside/tandoor/20261025T091303Z`"; the set-aside unit is install A's unit byte for byte (9 files, sha256 each); „Megőrzött másolatok" offers „Visszaállítás"; restored in 42 s, `running`, the account reads back, 0 password errors (app and postgres); remove with data leaves nothing, the set-aside folder included |
| **R-1269 / D47, AdventureLog** (`after/_unitprobe2/adventurelog/`) | (sweep: the same fault on its re-run) | set aside 09:23:03, byte for byte (8 files), restored, `running`, the item back, 0 password errors, nothing left |
| **D48** (`tools/pullprobe.py vikunja`, `after/_pullprobe/vikunja/`) | the first pull came after the stop (code order, `restore_unit.go` at `e1613ae`) | the unit's pin edited to `vikunja:0.0.0-felhom-d48-missing` → „REFUSED … before anything was touched: … could not be downloaded (the version does not exist any more)"; the household read „…verzióját (vikunja:0.0.0-felhom-d48-missing) nem lehet letölteni: a készítője már nem kínálja. Az alkalmazáshoz nem nyúltunk…"; the container's `StartedAt` the same before and after (09:29:54.57); the item still there; the original unit back byte for byte → a normal restore worked, the item back |
| **R-1270** (same run) | `ok: true` „…az alkalmazás újraindult." over `starting` | the unit's pin edited to `busybox:1.36.1` (pulls, exits at once) → after the 90 s wait the record `ok: false`, `not_started: true`, „A(z) vikunja: az adatokat visszatöltöttük, de az alkalmazás még nem indult el. Várj pár percet…"; the undo copy kept (`restore-undo/vikunja/20261025T093149Z`); the original back → a normal restore worked, the item back |
| **R-1271** (`tools/keptprobe.py romm`, `after/_keptprobe/romm/`) | the future-dated off-site copy chosen over the family's own (sweep) | a forged second-drive copy dated 2026-10-28 06:39 beside the app's own unit: the question named „saját mentés, 2026-10-25 10:38", no future flag; the own unit moved away for a moment: the forged copy alone was offered with `use_future: true` and „Figyelem: ennek a mentésnek a dátuma (2026-10-28 07:39) a jövőben van…"; with the own unit back, „use my kept data" loaded tier 1 (`backups/primary/romm`, 09:38:55Z), the item back |
**Two findings of the live runs, fixed without a row (each red-proved):** (1) run 1 of the Tandoor proof
(`after/run1-list-hidden/`) found the restore page listing NO kept copy on 9202: the „Megőrzött másolatok" section sat
inside the off-site card, and 9202 has no off-site — so a box without off-site never listed a D25 copy either. Fixed in
`1f9c863` (one named template, two call sites, parity fixtures unchanged); rc.2 then listed it. (2) The R-1270 run's
kept undo copy outlived the app's remove with its backups; fixed in `1f82959` (the remove deletes
`backups/restore-undo/<app>`), proven by its test only — the copy on 9202 was removed by hand (2.6 MB, mine).
`after/run1-probe-bug/` is a probe of mine that crashed on its own bug before touching anything.
**The `file:line` causes (at `e1613ae`):** R-1269 `backup/recovery_unit.go:194` (the `frozen` pins test) and `:254-258`
(the writes); R-1270 `backup/restore_unit.go:567-569`, the same WARN at `offbox_reconstitute.go` (the off-site path),
`tier2_restore.go` (the file restore) and `restore.go` (the fallback); D48 `restore_unit.go:497` (the stop) before
`:552` (the first `compose up`, the DB-only start); R-1271 `backup/kept_load.go:179-184` (`KeptNewer`: the newer date
wins, future or not) and `:97` (the „another drive" check compares `HDD_PATH`, a mount path).
**Not covered and filed:** R-1278 (a volume app's reinstall does not offer its kept backup), R-1279 (the `.fab` import
removes the app's volumes before its pull).
**Observation, NOT-A-FINDING:** 9202 logs „immich: definition REFUSED by the allow-list" at every start — it was there
before this run's image (an earlier session's Immich on `/mnt/sizing-bench`); not this run's.
## Teardown
- **Machine:** 9202 only — my throwaway installs (Tandoor ×3, AdventureLog, Vikunja, RomM) each removed through the
product with their data; the two empty folders my runs left (RomM's `appdata/romm`, the empty `backups/set-aside/`)
and the one kept undo copy (above) removed by hand after checking they held nothing else; the `0.343.0-rc.1/.2` images
removed from its Docker; the controller back on 0.342.0 (`/etc/felhom-controller-image`); the apps found running
(Immich, Paperless-ngx, the file browser, traefik) running. No VM, no LXC created; Tester 1 and the thin pool untouched.
- **Host:** DooPlex — the session's 9202 password file in the session scratchpad shredded at the end. The rc images
stay in the registry as test tags (never offered to a household).
- **Hub:** provisioned nothing (9202 has no hub). **ep0:** nothing.
@@ -0,0 +1,43 @@
{
"app": "romm",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 75,
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"1m13.631435029s\", \"last_run\": \"2026-10-25T09:40:08.943436205Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"own_unit": "/mnt/felhom-drives/scratch_hdd/backups/primary/romm",
"forged_at": "\"at\": \"2026-10-28T06:39:39Z\"\n\"at\": \"2026-10-28T06:39:39Z\"",
"q1_code": "409",
"q1": {
"code": "kept_data_choice",
"use_offered": true,
"use_desc": "Az adatbázist innen töltjük vissza: saját mentés, 2026-10-25 10:38. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.",
"use_future": null,
"use_warn": null,
"use_off": ""
},
"q2_code": "409",
"q2": {
"code": "kept_data_choice",
"use_offered": true,
"use_desc": "Az adatbázist innen töltjük vissza: második meghajtó, 2026-10-28 07:39. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.",
"use_future": true,
"use_warn": "Figyelem: ennek a mentésnek a dátuma (2026-10-28 07:39) a jövőben van. A mentést készítő doboz órája rosszul járhatott. Csak akkor válaszd, ha biztosan ez a ti mentésetek.",
"use_off": ""
},
"use_ok": true,
"load_status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"romm\", \"started_at\": \"2026-10-25T09:41:21.356199563Z\", \"last\": {\"op\": \"restore\", \"stack\": \"romm\", \"ok\": true, \"message\": \"A(z) RomM a megőrzött adataival fut.\", \"finished_at\": \"2026-10-25T09:43:03.140979706Z\"}, \"last_recent\": true}",
"item_after_load": true,
"controller_lines": "2026/10/25 09:41:10 image_retention.go:238: [INFO] [stacks] image retention (remove of romm): pass over 42 image(s) of [mariadb redis rommapp/romm] — 2 candidate(s), 2 deleted, the rest kept\n2026/10/25 09:41:14 kept_install.go:88: [INFO] [api] Deploy romm: the drive already holds its old data [/mnt/felhom-drives/scratch_hdd/appdata/romm/resources] (0 bytes) — asking the household (use offered: true, future-dated: false)\n2026/10/25 09:41:17 kept_install.go:88: [INFO] [api] Deploy romm: the drive already holds its old data [/mnt/felhom-drives/scratch_hdd/appdata/romm/resources] (0 bytes) — asking the household (use offered: true, future-dated: true)\n2026/10/25 09:41:21 kept_install.go:105: [INFO] [api] Deploy romm: USE MY KEPT DATA — loading from /mnt/felhom-drives/scratch_hdd/backups/primary/romm (tier 1, 2026-10-25T09:38:55Z) under the kept files [/mnt/felhom-drives/scratch_hdd/appdata/romm/resources]\n2026/10/25 09:41:21 restore_dbcreds.go:114: [INFO] [backup] Restore romm: database password(s) [DB_PASSWORD MYSQL_ROOT_PASSWORD] come from the backup, [] stay as installed (older than the data) — values not logged (R-1106)\n2026/10/25 09:41:21 restore_unit.go:410: [INFO] [backup] Restoring romm from recovery unit /mnt/felhom-drives/scratch_hdd/backups/primary/romm: images=3, secrets recovered=3/3, data_keys=0\n2026/10/25 09:41:32 restore_pull.go:103: [INFO] [backup] Restore romm: downloaded rommapp/romm:5.3.1@sha256:0d66b4ea152a237c7f24b95e87459f46d3c596a7c0b35a82f26bc971487278b3 before anything was touched (11s, D48)\n2026/10/25 09:41:57 restore_pull.go:103: [INFO] [backup] Restore romm: downloaded mariadb:11.8@sha256:79d59758afc91b89b120b0a8904d637f5a3b3e1c4900f29b740d6d46c72fef68 before anything was touched (25s, D48)\n2026/10/25 09:41:57 restore.go:225: [INFO] [backup] Restoring Docker volume romm_romm_assets for romm\n2026/10/25 09:42:08 restore.go:263: [DEBUG] [backup] Volume romm_romm_assets restored successfully\n2026/10/25 09:42:08 restore.go:225: [INFO] [backup] Restoring Docker volume romm_romm_config for romm\n2026/10/25 09:42:08 restore.go:263: [DEBUG] [backup] Volume romm_romm_config restored successfully\n2026/10/25 09:42:08 restore.go:225: [INFO] [backup] Restoring Docker volume romm_romm_db_data for romm\n2026/10/25 09:42:13 restore.go:263: [DEBUG] [backup] Volume romm_romm_db_data restored successfully\n2026/10/25 09:42:13 restore.go:225: [INFO] [backup] Restoring Docker volume romm_romm_redis_data for romm\n2026/10/25 09:42:13 restore.go:263: [DEBUG] [backup] Volume romm_romm_redis_data restored successfully\n2026/10/25 09:42:13 restore.go:268: [INFO] [backup] Restored 4 Docker volume(s) for romm\n2026/10/25 09:42:14 restore_db.go:87: [INFO] [backup] Restore romm: replaying DB dump into romm-db (mariadb)\n2026/10/25 09:42:18 restore_db.go:97: [INFO] [backup] Restore romm: replayed 1 DB dump(s)\n2026/10/25 09:42:32 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:42:37 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:42:42 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:42:48 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:42:53 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:42:58 restore.go:308: [DEBUG] [backup] Post-restore health check: romm not yet running, waiting...\n2026/10/25 09:43:03 restore.go:303: [DEBUG] [backup] Post-restore health check: romm is running\n2026/10/25 09:43:03 restore_unit.go:591: [INFO] [backup] Restore-from-unit completed: romm — 4 volume(s) of 4 listed, 1 database(s) of 1 listed\n2026/10/25 09:43:03 kept_load.go:391: [INFO] [backup] kept load romm from /mnt/felhom-drives/scratch_hdd/backups/primary/romm done in 1m42s (volumes 4/4, dbs 1/1)\n",
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "/mnt/felhom-drives/scratch_hdd/appdata/romm",
"kept": "",
"subdomain": "404"
},
"forged_left": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/secondary/romm': No such file or directory"
}
@@ -0,0 +1,21 @@
09:37:11Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:37:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:38:47Z [1] deployed, controller state=running, pinned={'romm': 'rommapp/romm:5.3.1', 'romm-db': 'mariadb:11.8', 'romm-redis': 'redis:7-alpine'}
09:38:47Z gate: arcade is gated — passed as the household (cookie set)
09:38:55Z romm: POST /api/users http=201
09:38:55Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:40:23Z forged a future-dated second-drive copy: "at": "2026-10-28T06:39:39Z"
"at": "2026-10-28T06:39:39Z" (own unit: /mnt/felhom-drives/scratch_hdd/backups/primary/romm)
09:41:09Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'romm', 'volumes_removed': ['romm_romm_assets', 'romm_romm_config', 'romm_romm_db_data', 'romm_romm_redis_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': ['/mn
09:41:14Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:14Z [question, own copy + future copy] 409 {"code": "kept_data_choice", "use_offered": true, "use_desc": "Az adatbázist innen töltjük vissza: saját mentés, 2026-10-25 10:38. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.", "use_future": null, "use_warn": null, "use_off": ""}
09:41:17Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:17Z [question, the future copy alone] 409 {"code": "kept_data_choice", "use_offered": true, "use_desc": "Az adatbázist innen töltjük vissza: második meghajtó, 2026-10-28 07:39. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.", "use_future": true, "use_warn": "Figyelem: ennek a mentésnek a dátuma (2026-10-28 07:39) a jövőben van. A mentést készítő doboz órája rosszul járhatott. Csak akkor válaszd, ha biztosan ez a ti mentésetek.", "use_off": ""}
09:41:21Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:21Z [1] deploy -> 202 {'ok': True, 'message': 'A(z) RomM megőrzött adatainak betöltése elindult.'}
09:42:26Z [1] deployed, controller state=degraded, pinned={'romm': 'rommapp/romm:5.3.1', 'romm-db': 'mariadb:11.8', 'romm-redis': 'redis:7-alpine'}
09:42:26Z [1] NOTE: the controller's own state is 'degraded', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:43:06Z load: {"running": false, "op": "restore", "stack": "romm", "started_at": "2026-10-25T09:41:21.356199563Z", "last": {"op": "restore", "stack": "romm", "ok": true, "message": "A(z) RomM a megőrzött adataival fut.", "finished_at": "2026-10-25T09:43:03.140979706Z"}, "last_recent": true}
09:43:15Z romm: login as the seeded user http=200 ok=True
09:43:15Z item after use-my-kept-data: True
09:43:57Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'romm', 'volumes_removed': ['romm_romm_assets', 'romm_romm_config', 'romm_romm_db_data', 'romm_romm_redis_data'], 'hdd_paths_removed': ['/mnt/felhom-drives/scratch_hdd
@@ -0,0 +1,68 @@
{
"app": "vikunja",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 55,
"status": "{\"db_dump\": {\"count\": 2, \"duration\": \"50.712761411s\", \"last_run\": \"2026-10-25T09:31:32.624265386Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"unit_files": 7,
"d48_restore": {
"points": 1,
"location": [
"location: /backups/restore?flash=flash.restore.started"
],
"seconds": 10,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"vikunja\", \"started_at\": \"2026-10-25T09:30:11.335278772Z\", \"last\": {\"op\": \"restore\", \"stack\": \"vikunja\", \"ok\": false, \"message\": \"Visszaállítás sikertelen: Ennek a mentésnek a verzióját (vikunja:0.0.0-felhom-d48-missing) nem lehet letölteni: a készítője már nem kínálja. Az alkalmazáshoz nem nyúltunk. Válassz egy másik mentést.\", \"finished_at\": \"2026-10-25T09:30:13.943080647Z\"}, \"last_recent\": true}",
"state": "running"
},
"d48_started_before": "/vikunja 2026-10-25T09:29:54.57273795Z running",
"d48_started_after": "/vikunja 2026-10-25T09:29:54.57273795Z running",
"d48_app_untouched": true,
"d48_item_still_there": true,
"original_back_1": true,
"normal_restore_1": {
"points": 1,
"location": [
"location: /backups/restore?flash=flash.restore.started"
],
"seconds": 10,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"vikunja\", \"started_at\": \"2026-10-25T09:30:31.410646319Z\", \"last\": {\"op\": \"restore\", \"stack\": \"vikunja\", \"ok\": true, \"message\": \"A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.\", \"finished_at\": \"2026-10-25T09:30:38.26202133Z\"}, \"last_recent\": true}",
"state": "running"
},
"item_after_normal_restore_1": true,
"r1270_restore": {
"points": 1,
"location": [
"location: /backups/restore?flash=flash.restore.started"
],
"seconds": 100,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"vikunja\", \"started_at\": \"2026-10-25T09:31:47.895007425Z\", \"last\": {\"op\": \"restore\", \"stack\": \"vikunja\", \"ok\": false, \"message\": \"A(z) vikunja: az adatokat visszatöltöttük, de az alkalmazás még nem indult el. Várj pár percet, majd nyisd meg újra. Ha így marad, szólj nekünk.\", \"finished_at\": \"2026-10-25T09:33:26.51097487Z\", \"not_started\": true}, \"last_recent\": true}",
"state": "restarting"
},
"r1270_state": "restarting",
"r1270_undo_copies": "20261025T093149Z",
"original_back_2": true,
"normal_restore_2": {
"points": 1,
"location": [
"location: /backups/restore?flash=flash.restore.started"
],
"seconds": 10,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"vikunja\", \"started_at\": \"2026-10-25T09:33:38.075945508Z\", \"last\": {\"op\": \"restore\", \"stack\": \"vikunja\", \"ok\": true, \"message\": \"A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.\", \"finished_at\": \"2026-10-25T09:33:44.816871537Z\"}, \"last_recent\": true}",
"state": "running"
},
"item_after_normal_restore_2": true,
"controller_lines": "2026/10/25 09:30:11 handlers.go:1852: [DEBUG] [web] backupRestoreHandler: stack=vikunja snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:30:11 handlers.go:1894: [WARN] [web] Restore requested (async): stack=vikunja, snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:30:11 restore_unit.go:398: [INFO] [backup] Restore vikunja: the data belongs to [vikunja/vikunja:0.0.0-felhom-d48-missing] (written 2026-10-25T09:29:53Z); the app ran [vikunja/vikunja:2.6.0@sha256:417ada6f94e81f0267aa2f007d0a811fc82d38dd2aa58351e3ea520ca01c2ea5] — it comes back at its data's version, an\n2026/10/25 09:30:11 restore_unit.go:410: [INFO] [backup] Restoring vikunja from recovery unit /mnt/sys_drive/felhom-data/backups/primary/vikunja: images=1, secrets recovered=1/1, data_keys=0\n2026/10/25 09:30:13 restore_pull.go:96: [ERROR] [backup] Restore REFUSED for vikunja before anything was touched: the image vikunja/vikunja:0.0.0-felhom-d48-missing could not be downloaded (the version does not exist any more; after 1s): exit status 1 — Error response from daemon: manifest for vikunja/vikunja:0.0.0-f\n2026/10/25 09:30:13 handlers.go:1902: [ERROR] [web] Restore failed (async): stack=vikunja: Ennek a mentésnek a verzióját (vikunja:0.0.0-felhom-d48-missing) nem lehet letölteni: a készítője már nem kínálja. Az alkalmazáshoz nem nyúltunk. Válassz egy másik mentést.\n2026/10/25 09:30:31 handlers.go:1852: [DEBUG] [web] backupRestoreHandler: stack=vikunja snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:30:31 handlers.go:1894: [WARN] [web] Restore requested (async): stack=vikunja, snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:30:31 restore_unit.go:410: [INFO] [backup] Restoring vikunja from recovery unit /mnt/sys_drive/felhom-data/backups/primary/vikunja: images=1, secrets recovered=1/1, data_keys=0\n2026/10/25 09:30:33 offbox_restore_undo.go:163: [INFO] [offbox] vikunja: the live volumes are copied before the restore (2 copied, 0 new from the snapshot) in 883ms — /mnt/sys_drive/felhom-data/backups/restore-undo/vikunja/20261025T093032Z (R-893)\n2026/10/25 09:30:33 restore_crash_putback.go:89: [INFO] [backup] vikunja: the restore copy is recorded — a power cut from here on puts the app back on start (R-1195)\n2026/10/25 09:30:33 restore.go:225: [INFO] [backup] Restoring Docker volume vikunja_vikunja_data for vikunja\n2026/10/25 09:30:34 restore.go:263: [DEBUG] [backup] Volume vikunja_vikunja_data restored successfully\n2026/10/25 09:30:34 restore.go:225: [INFO] [backup] Restoring Docker volume vikunja_vikunja_db for vikunja\n2026/10/25 09:30:34 restore.go:263: [DEBUG] [backup] Volume vikunja_vikunja_db restored successfully\n2026/10/25 09:30:34 restore.go:268: [INFO] [backup] Restored 2 Docker volume(s) for vikunja\n2026/10/25 09:30:38 restore.go:303: [DEBUG] [backup] Post-restore health check: vikunja is running\n2026/10/25 09:30:38 restore_unit.go:591: [INFO] [backup] Restore-from-unit completed: vikunja — 2 volume(s) of 2 listed, 0 database(s) of 0 listed\n2026/10/25 09:30:38 handlers.go:1906: [INFO] [web] Restore completed (async): stack=vikunja in 6.850941322s (volumes 2/2, dbs 0/0)\n2026/10/25 09:31:47 handlers.go:1852: [DEBUG] [web] backupRestoreHandler: stack=vikunja snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:31:47 handlers.go:1894: [WARN] [web] Restore requested (async): stack=vikunja, snapshot=helyi from 172.18.0.4:37324\n2026/10/25 09:31:47 restore_unit.go:398: [INFO] [backup] Restore vikunja: the data belongs to [busybox:1.36.1] (written 2026-10-25T09:31:31Z); the app ran [vikunja/vikunja:2.6.0@sha256:417ada6f94e81f0267aa2f007d0a811fc82d38dd2aa58351e3ea520ca01c2ea5] — it comes back at its data's version, and the update climbs from t\n2026/10/25 09:31:47 restore_unit.go:410: [INFO] [backup] Restoring vikunja from recovery unit /mnt/sys_drive/felhom-data/backups/primary/vikunja: images=1, secrets recovered=1/1, data_keys=0\n2026/10/25 09:31:50 offbox_restore_undo.go:163: [INFO] [offbox] vikunja: the live volumes are copied before the restore (2 copied, 0 new from the snapshot) in 960ms — /mnt/sys_drive/felhom-data/backups/restore-undo/vikunja/20261025T093149Z (R-893)\n2026/10/25 09:31:50 restore_crash_putback.go:89: [INFO] [backup] vikunja: the restore copy is recorded — a power cut from here on puts the app back on start (R-1195)\n2026/10/25 09:31:50 restore.go:225: [INFO] [backup] Restoring Docker volume vikunja_vikunja_data for vikunja\n2026/10/25 09:31:51 restore.go:263: [DEBUG] [backup] Volume vikunja_vikunja_data restored successfully\n2026/10/25 09:31:51 restore.go:225: [INFO] [backup] Restoring Docker volume vikunja_vikunja_db for vikunja\n2026/10/25 09:31:51 restore.go:263: [DEBUG] [backup] Volume vikunja_vikunja_db restored successfully\n2026/10/25 09:31:51 restore.go:268: [INFO] [backup] Restored 2 Docker volume(s) for vikunja\n2026/10/25 09:31:55 restore.go:308: [DEBUG] [backup] Post-restore health check: vikunja not yet running, waiting...\n2026/10/25 Line truncated
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
},
"test_copy_removed": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/d48-test-original/vikunja': No such file or directory",
"restore_undo_left": "20261025T093149Z"
}
@@ -0,0 +1,27 @@
09:28:46Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:28:56Z [1] deployed, controller state=running, pinned={'vikunja': 'vikunja/vikunja:2.6.0'}
09:28:56Z gate: tasks is gated — passed as the household (cookie set)
09:28:57Z vikunja: register http=200
09:28:57Z vikunja: create project http=201
09:28:57Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:30:08Z [D48] the unit's pin → vikunja/vikunja:0.0.0-felhom-d48-missing :: compose/docker-compose.yml:1 manifest.json:7 data-stamps.json:4
09:30:11Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:30:21Z d48_restore: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:30:11.335278772Z", "last": {"op": "restore", "stack": "vikunja", "ok": false, "message": "Visszaállítás sikertelen: Ennek a mentésnek a verzióját (vikunja:0.0.0-felhom-d48-missing) nem lehet letölteni: a készítője már nem kínálja. Az alkalmazáshoz nem nyúltunk. Válassz egy másik mentést.", "finished_at": "2026-10-
09:30:24Z [D48] containers never restarted: True (/vikunja 2026-10-25T09:29:54.57273795Z running)
09:30:25Z vikunja: readback of the seeded project http=200 ok=True
09:30:31Z the original unit is back byte for byte: True
09:30:31Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:30:41Z normal_restore_1: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:30:31.410646319Z", "last": {"op": "restore", "stack": "vikunja", "ok": true, "message": "A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:30:38.26202133Z"}, "last_recent": true}
09:30:41Z vikunja: readback of the seeded project http=200 ok=True
09:30:41Z normal restore: item back True, state running
09:30:41Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:31:47Z [R-1270] the unit's pin → busybox:1.36.1 (pulls, exits at once) :: compose/docker-compose.yml:1 manifest.json:7 data-stamps.json:4
09:31:47Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:33:28Z r1270_restore: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:31:47.895007425Z", "last": {"op": "restore", "stack": "vikunja", "ok": false, "message": "A(z) vikunja: az adatokat visszatöltöttük, de az alkalmazás még nem indult el. Várj pár percet, majd nyisd meg újra. Ha így marad, szólj nekünk.", "finished_at": "2026-10-25T09:33:26.51097487Z", "not_started": true}, "last_re
09:33:31Z [R-1270] state restarting, kept undo copy: 20261025T093149Z
09:33:38Z the original unit is back byte for byte: True
09:33:38Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:33:48Z normal_restore_2: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:33:38.075945508Z", "last": {"op": "restore", "stack": "vikunja", "ok": true, "message": "A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:33:44.816871537Z"}, "last_recent": true}
09:33:48Z vikunja: readback of the seeded project http=200 ok=True
09:33:48Z normal restore 2: item back True, state running
09:34:24Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'vikunja', 'volumes_removed': ['vikunja_vikunja_data', 'vikunja_vikunja_db'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalmazás nem tárolt
@@ -0,0 +1,34 @@
{
"app": "adventurelog",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 70,
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"1m6.314033847s\", \"last_run\": \"2026-10-25T09:20:04.942724577Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"reinstall": true,
"set_aside_line": "2026/10/25 09:23:03 unit_owner.go:182: [INFO] [backup] adventurelog: the recovery unit of an earlier install (39b3ae7e65d7c197; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z; this install (920d6a875fa0dadf) gets its own unit from its first backup (D47)",
"set_aside_dirs": [
"20261025T092303Z"
],
"set_aside_byte_identical": true,
"restore_page_offers": true,
"restore": {
"seconds": 45,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"adventurelog\", \"started_at\": \"2026-10-25T09:23:47.915496662Z\", \"last\": {\"op\": \"restore\", \"stack\": \"adventurelog\", \"ok\": true, \"message\": \"A(z) adventurelog: 2 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.\", \"finished_at\": \"2026-10-25T09:24:32.727338795Z\"}, \"last_recent\": true}"
},
"state_after_restore": "running",
"item_after_restore": true,
"db_auth_errors_after_restore": "adventurelog: 0\nadventurelog-frontend: 0\nadventurelog-postgres: 0",
"controller_lines": "2026/10/25 09:18:03 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for adventurelog → /mnt/sys_drive/felhom-data/backups/primary/adventurelog (images=3, secrets-referenced=2, data_keys=1, portable-carried=2/2, withheld=0)\n2026/10/25 09:18:22 healthprobe.go:196: [WARN] Health probe adventurelog: API GET :8000/api/ → Get \"http://adventurelog:8000/api/\": dial tcp 172.18.0.8:8000: connect: connection refused\n2026/10/25 09:20:04 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for adventurelog → /mnt/sys_drive/felhom-data/backups/primary/adventurelog (images=3, secrets-referenced=2, data_keys=1, portable-carried=2/2, withheld=0)\n2026/10/25 09:23:03 unit_owner.go:182: [INFO] [backup] adventurelog: the recovery unit of an earlier install (39b3ae7e65d7c197; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z; this install (920d6a875fa0dadf) gets its own unit\n2026/10/25 09:23:03 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for adventurelog → /mnt/sys_drive/felhom-data/backups/primary/adventurelog (images=3, secrets-referenced=2, data_keys=1, portable-carried=2/2, withheld=0)\n2026/10/25 09:23:47 kept_copies.go:108: [WARN] [web] Restore of adventurelog from a set-aside unit requested (async): /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z from 172.18.0.4:37324\n2026/10/25 09:23:47 unit_owner.go:316: [INFO] [backup] restore adventurelog from the set-aside unit /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z (an earlier install, D47)\n2026/10/25 09:23:47 restore_dbcreds.go:114: [INFO] [backup] Restore adventurelog: database password(s) [DB_PASSWORD] come from the backup, [] stay as installed (older than the data) — values not logged (R-1106)\n2026/10/25 09:23:47 restore_unit.go:410: [INFO] [backup] Restoring adventurelog from recovery unit /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z: images=3, secrets recovered=2/2, data_keys=1\n2026/10/25 09:23:56 offbox_restore_undo.go:163: [INFO] [offbox] adventurelog: the live volumes are copied before the restore (2 copied, 0 new from the snapshot) in 4.55s — /mnt/sys_drive/felhom-data/backups/restore-undo/adventurelog/20261025T092351Z (R-893)\n2026/10/25 09:23:56 restore_crash_putback.go:89: [INFO] [backup] adventurelog: the restore copy is recorded — a power cut from here on puts the app back on start (R-1195)\n2026/10/25 09:23:56 restore.go:225: [INFO] [backup] Restoring Docker volume adventurelog_adventurelog_media for adventurelog\n2026/10/25 09:23:57 restore.go:263: [DEBUG] [backup] Volume adventurelog_adventurelog_media restored successfully\n2026/10/25 09:23:57 restore.go:225: [INFO] [backup] Restoring Docker volume adventurelog_adventurelog_postgres_data for adventurelog\n2026/10/25 09:24:01 restore.go:263: [DEBUG] [backup] Volume adventurelog_adventurelog_postgres_data restored successfully\n2026/10/25 09:24:01 restore.go:268: [INFO] [backup] Restored 2 Docker volume(s) for adventurelog\n2026/10/25 09:24:01 deploy.go:866: [INFO] [stacks] adventurelog: the restored data belongs to install 39b3ae7e65d7c197 (was 920d6a875fa0dadf) — its backups follow it (D47)\n2026/10/25 09:24:02 restore_db.go:87: [INFO] [backup] Restore adventurelog: replaying DB dump into adventurelog-postgres (postgres)\n2026/10/25 09:24:08 restore_db.go:97: [INFO] [backup] Restore adventurelog: replayed 1 DB dump(s)\n2026/10/25 09:24:12 restore.go:308: [DEBUG] [backup] Post-restore health check: adventurelog not yet running, waiting...\n2026/10/25 09:24:17 restore.go:308: [DEBUG] [backup] Post-restore health check: adventurelog not yet running, waiting...\n2026/10/25 09:24:22 restore.go:308: [DEBUG] [backup] Post-restore health check: adventurelog not yet running, waiting...\n2026/10/25 09:24:27 restore.go:308: [DEBUG] [backup] Post-restore health check: adventurelog not yet running, waiting...\n2026/10/25 09:24:32 restore.go:303: [DEBUG] [backup] Post-restore health check: adventurelog is running\n2026/10/25 09:24:32 restore_unit.go:591: [INFO] [backup] Restore-from-unit completed: adventurelog — 2 volume(s) of 2 listed, 1 database(s) of 1 listed\n",
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
},
"set_aside_after_remove": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/set-aside/adventurelog': No such file or directory"
}
@@ -0,0 +1,20 @@
Megőrzött másolatok</h3>
<p class="form-hint" style="margin-bottom:.75rem">Ezek a második meghajtón lévő másolatok olyan mappákhoz tartoznak, amelyek most nem érhetők el: a meghajtó nincs csatlakoztatva, már nincs a gépen, vagy a mappa hiányzik. Megőrizzük őket, amíg te el nem távolítod őket.</p>
<div class="app-row-list">
<div class="app-row">
<img class="app-row-icon" src="/static/assets/-logo.svg" alt="" data-fallback="/static/app-placeholder.svg"
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='\/static\/assets\/-logo.png';}else if(this.dataset.fallback&&this.dataset.step==='1'){this.dataset.step='2';this.src=this.dataset.fallback;}else{this.onerror=null;this.style.visibility='hidden';}">
<div class="app-row-text">
<span class="app-row-name">adventurelog</span>
<span class="app-row-secondary">a(z) sys_drive meghajtóról megőrzött másolat · egy korábbi telepítés mentése (újratelepítés előtt készült) · 288,9 MB · 2026. 10. 25. 10:23</span>
</div>
<div class="app-row-actions">
<form method="POST" action="/backup/kept/restore" style="display:inline">
<input type="hidden" name="_csrf" value="<blanked>">
<input type="hidden" name="id" value="a76776b93e5e59df">
<input type="hidden" name="confirm" value="1">
<button type="button" class="btn btn-xs btn-outline"
@@ -0,0 +1,8 @@
c229bf3847b573aa965308952a5da555fa41f3bb96cefa4ab0ae137bd9aeb6e4 ./compose/.felhom.yml
7350a65f5a6dfc8ada83f66d28929e8ac54720d7379babf80634bbe35ebc92e1 ./compose/app.yaml
c8f2e1dec1a7adfe7026d3471bdc20962dee23aac6c1012ee048e54919e07c11 ./compose/docker-compose.yml
47344b7405fa51fc03f008501b43c3c8f6ac0dd941b953764d75aec6573147a3 ./data-stamps.json
d2238cef009ff1c540486ce80ab9c006c05c4767b684d4b78ed24e10e667d59d ./db-dumps/adventurelog-postgres.sql
5cb66a1a41ae248f122196509d36c4556130d80ebd4d20f23c113dc64d0b42a4 ./manifest.json
c3d9eb9dd880faeea2f4a6caf6ffc6ab62994cd0f1c2ca8618d6e6966721e66f ./volume-dumps/adventurelog_adventurelog_media.tar
51eee7ad0aa146554c8ecc495f089d62f018c84b2c4759073c72a85e145ed1e4 ./volume-dumps/adventurelog_adventurelog_postgres_data.tar
@@ -0,0 +1,8 @@
c229bf3847b573aa965308952a5da555fa41f3bb96cefa4ab0ae137bd9aeb6e4 ./compose/.felhom.yml
7350a65f5a6dfc8ada83f66d28929e8ac54720d7379babf80634bbe35ebc92e1 ./compose/app.yaml
c8f2e1dec1a7adfe7026d3471bdc20962dee23aac6c1012ee048e54919e07c11 ./compose/docker-compose.yml
47344b7405fa51fc03f008501b43c3c8f6ac0dd941b953764d75aec6573147a3 ./data-stamps.json
d2238cef009ff1c540486ce80ab9c006c05c4767b684d4b78ed24e10e667d59d ./db-dumps/adventurelog-postgres.sql
5cb66a1a41ae248f122196509d36c4556130d80ebd4d20f23c113dc64d0b42a4 ./manifest.json
c3d9eb9dd880faeea2f4a6caf6ffc6ab62994cd0f1c2ca8618d6e6966721e66f ./volume-dumps/adventurelog_adventurelog_media.tar
51eee7ad0aa146554c8ecc495f089d62f018c84b2c4759073c72a85e145ed1e4 ./volume-dumps/adventurelog_adventurelog_postgres_data.tar
@@ -0,0 +1,4 @@
c229bf3847b573aa965308952a5da555fa41f3bb96cefa4ab0ae137bd9aeb6e4 ./compose/.felhom.yml
61006693c9d91f9200677823a100c47ff0000cadba6085772efc28644447731b ./compose/app.yaml
c8f2e1dec1a7adfe7026d3471bdc20962dee23aac6c1012ee048e54919e07c11 ./compose/docker-compose.yml
6856f0a8df476d64a24975ec53ee56a6f6e05a0a87d165fb97eade8ba597a600 ./manifest.json
@@ -0,0 +1,26 @@
09:15:44Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:18:15Z [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.0', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}
09:18:15Z [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:18:15Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:20Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:25Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:30Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:35Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:40Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:45Z gate: travel is gated — passed as the household (cookie set)
09:18:53Z adventurelog: createsuperuser :: Superuser created successfully.
09:18:58Z adventurelog: seeded superuser drillf3d0fa
09:18:58Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:20:48Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'adventurelog', 'volumes_removed': ['adventurelog_adventurelog_media', 'adventurelog_adventurelog_postgres_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
09:20:53Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:23:24Z [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.0', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}
09:23:24Z [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:23:37Z set aside: 2026/10/25 09:23:03 unit_owner.go:182: [INFO] [backup] adventurelog: the recovery unit of an earlier install (39b3ae7e65d7c197; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z; this install (920d6a875fa0dadf) gets its own unit f
09:23:44Z the set-aside unit is install A's unit byte for byte: True (8 files)
09:23:47Z [6] POST /backup/kept/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:24:33Z restore status: {"running": false, "op": "restore", "stack": "adventurelog", "started_at": "2026-10-25T09:23:47.915496662Z", "last": {"op": "restore", "stack": "adventurelog", "ok": true, "message": "A(z) adventurelog: 2 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-2
09:25:03Z adventurelog: readback of the seeded account found=True
09:25:06Z state after restore: running, item: True, db auth errors: adventurelog: 0
adventurelog-frontend: 0
adventurelog-postgres: 0
09:25:44Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'adventurelog', 'volumes_removed': ['adventurelog_adventurelog_media', 'adventurelog_adventurelog_postgres_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
@@ -0,0 +1,34 @@
{
"app": "tandoor",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 65,
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"1m4.757425445s\", \"last_run\": \"2026-10-25T09:07:24.767762156Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"reinstall": true,
"set_aside_line": "2026/10/25 09:13:03 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (77ea4da495f5cdbf; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z; this install (bf68aee48f37e20e) gets its own unit from its first backup (D47)",
"set_aside_dirs": [
"20261025T091303Z"
],
"set_aside_byte_identical": true,
"restore_page_offers": true,
"restore": {
"seconds": 45,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"tandoor\", \"started_at\": \"2026-10-25T09:13:23.43182369Z\", \"last\": {\"op\": \"restore\", \"stack\": \"tandoor\", \"ok\": true, \"message\": \"A(z) tandoor: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.\", \"finished_at\": \"2026-10-25T09:14:05.476224352Z\"}, \"last_recent\": true}"
},
"state_after_restore": "running",
"item_after_restore": true,
"db_auth_errors_after_restore": "tandoor: 0\ntandoor-postgres: 0",
"controller_lines": "2026/10/25 09:07:24 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n2026/10/25 09:13:03 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (77ea4da495f5cdbf; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z; this install (bf68aee48f37e20e) gets its own unit from its \n2026/10/25 09:13:03 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n2026/10/25 09:13:23 kept_copies.go:108: [WARN] [web] Restore of tandoor from a set-aside unit requested (async): /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z from 172.18.0.4:37324\n2026/10/25 09:13:23 unit_owner.go:316: [INFO] [backup] restore tandoor from the set-aside unit /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z (an earlier install, D47)\n2026/10/25 09:13:23 restore_dbcreds.go:114: [INFO] [backup] Restore tandoor: database password(s) [DB_PASSWORD] come from the backup, [] stay as installed (older than the data) — values not logged (R-1106)\n2026/10/25 09:13:23 restore_unit.go:410: [INFO] [backup] Restoring tandoor from recovery unit /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z: images=2, secrets recovered=2/2, data_keys=0\n2026/10/25 09:13:31 offbox_restore_undo.go:163: [INFO] [offbox] tandoor: the live volumes are copied before the restore (3 copied, 0 new from the snapshot) in 3.532s — /mnt/sys_drive/felhom-data/backups/restore-undo/tandoor/20261025T091327Z (R-893)\n2026/10/25 09:13:31 restore_crash_putback.go:89: [INFO] [backup] tandoor: the restore copy is recorded — a power cut from here on puts the app back on start (R-1195)\n2026/10/25 09:13:31 restore.go:225: [INFO] [backup] Restoring Docker volume tandoor_tandoor_media for tandoor\n2026/10/25 09:13:31 restore.go:263: [DEBUG] [backup] Volume tandoor_tandoor_media restored successfully\n2026/10/25 09:13:31 restore.go:225: [INFO] [backup] Restoring Docker volume tandoor_tandoor_postgres_data for tandoor\n2026/10/25 09:13:33 restore.go:263: [DEBUG] [backup] Volume tandoor_tandoor_postgres_data restored successfully\n2026/10/25 09:13:33 restore.go:225: [INFO] [backup] Restoring Docker volume tandoor_tandoor_static for tandoor\n2026/10/25 09:13:36 restore.go:263: [DEBUG] [backup] Volume tandoor_tandoor_static restored successfully\n2026/10/25 09:13:36 restore.go:268: [INFO] [backup] Restored 3 Docker volume(s) for tandoor\n2026/10/25 09:13:36 deploy.go:866: [INFO] [stacks] tandoor: the restored data belongs to install 77ea4da495f5cdbf (was bf68aee48f37e20e) — its backups follow it (D47)\n2026/10/25 09:13:36 restore_db.go:87: [INFO] [backup] Restore tandoor: replaying DB dump into tandoor-postgres (postgres)\n2026/10/25 09:13:40 restore_db.go:97: [INFO] [backup] Restore tandoor: replayed 1 DB dump(s)\n2026/10/25 09:13:45 restore.go:308: [DEBUG] [backup] Post-restore health check: tandoor not yet running, waiting...\n2026/10/25 09:13:50 restore.go:308: [DEBUG] [backup] Post-restore health check: tandoor not yet running, waiting...\n2026/10/25 09:13:55 restore.go:308: [DEBUG] [backup] Post-restore health check: tandoor not yet running, waiting...\n2026/10/25 09:14:00 restore.go:308: [DEBUG] [backup] Post-restore health check: tandoor not yet running, waiting...\n2026/10/25 09:14:05 restore.go:303: [DEBUG] [backup] Post-restore health check: tandoor is running\n2026/10/25 09:14:05 restore_unit.go:591: [INFO] [backup] Restore-from-unit completed: tandoor — 3 volume(s) of 3 listed, 1 database(s) of 1 listed\n",
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
},
"set_aside_after_remove": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/set-aside/tandoor': No such file or directory"
}
@@ -0,0 +1,20 @@
Megőrzött másolatok</h3>
<p class="form-hint" style="margin-bottom:.75rem">Ezek a második meghajtón lévő másolatok olyan mappákhoz tartoznak, amelyek most nem érhetők el: a meghajtó nincs csatlakoztatva, már nincs a gépen, vagy a mappa hiányzik. Megőrizzük őket, amíg te el nem távolítod őket.</p>
<div class="app-row-list">
<div class="app-row">
<img class="app-row-icon" src="/static/assets/-logo.svg" alt="" data-fallback="/static/app-placeholder.svg"
onerror="if(!this.dataset.step){this.dataset.step='1';this.src='\/static\/assets\/-logo.png';}else if(this.dataset.fallback&&this.dataset.step==='1'){this.dataset.step='2';this.src=this.dataset.fallback;}else{this.onerror=null;this.style.visibility='hidden';}">
<div class="app-row-text">
<span class="app-row-name">tandoor</span>
<span class="app-row-secondary">a(z) sys_drive meghajtóról megőrzött másolat · egy korábbi telepítés mentése (újratelepítés előtt készült) · 144,3 MB · 2026. 10. 25. 10:13</span>
</div>
<div class="app-row-actions">
<form method="POST" action="/backup/kept/restore" style="display:inline">
<input type="hidden" name="_csrf" value="<blanked>">
<input type="hidden" name="id" value="88ecdaffa2c9c0b0">
<input type="hidden" name="confirm" value="1">
<button type="button" class="btn btn-xs btn-outline"
@@ -0,0 +1,9 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
2701229e98a7b0d269bd971e54d11015970af1df9c38cf90435d77e61c53a153 ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
ffc60018dd63fcc1aee0fc0348c601dc2b94536f44335f1a0df4313a93ed2952 ./data-stamps.json
e8a1bd7a175d4c1d021d4e5bdba2d0f9da03ad4c80d358380bc6dbfb8e71ae8c ./db-dumps/tandoor-postgres.sql
e338ce10ddf13a7356dfe37adb520bb4c737588bb8c75149118b80d686f25830 ./manifest.json
c03824f1964f4660e6c9ceb6eda1803f4a301bd96b197cf0f49909df4d52a029 ./volume-dumps/tandoor_tandoor_media.tar
c8a062715a30be5b334a2968c9337d30a6121c745c4602bf301d23694d2979ae ./volume-dumps/tandoor_tandoor_postgres_data.tar
0d110353b2234c6a7a4aa0179e101c5513a1a0dde38a914875948970e75daaaf ./volume-dumps/tandoor_tandoor_static.tar
@@ -0,0 +1,9 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
2701229e98a7b0d269bd971e54d11015970af1df9c38cf90435d77e61c53a153 ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
ffc60018dd63fcc1aee0fc0348c601dc2b94536f44335f1a0df4313a93ed2952 ./data-stamps.json
e8a1bd7a175d4c1d021d4e5bdba2d0f9da03ad4c80d358380bc6dbfb8e71ae8c ./db-dumps/tandoor-postgres.sql
e338ce10ddf13a7356dfe37adb520bb4c737588bb8c75149118b80d686f25830 ./manifest.json
c03824f1964f4660e6c9ceb6eda1803f4a301bd96b197cf0f49909df4d52a029 ./volume-dumps/tandoor_tandoor_media.tar
c8a062715a30be5b334a2968c9337d30a6121c745c4602bf301d23694d2979ae ./volume-dumps/tandoor_tandoor_postgres_data.tar
0d110353b2234c6a7a4aa0179e101c5513a1a0dde38a914875948970e75daaaf ./volume-dumps/tandoor_tandoor_static.tar
@@ -0,0 +1,4 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
d38eec97a49c2b5b3f5041ef8b1436836136f220fc4d4c72700f17e3bb834d11 ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
57eb0d21fffe2116723d34cc742ae595e462fd956d061c9f2fa774cc66c903d1 ./manifest.json
@@ -0,0 +1,17 @@
09:03:52Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:06:02Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
09:06:02Z gate: recipes is gated — passed as the household (cookie set)
09:06:15Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
09:06:19Z tandoor: seeded superuser drill69d6f1
09:06:20Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:08:02Z [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': [],
09:08:07Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:10:33Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
09:13:13Z set aside: 2026/10/25 09:13:03 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (77ea4da495f5cdbf; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z; this install (bf68aee48f37e20e) gets its own unit from its fi
09:13:20Z the set-aside unit is install A's unit byte for byte: True (9 files)
09:13:23Z [6] POST /backup/kept/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:14:08Z restore status: {"running": false, "op": "restore", "stack": "tandoor", "started_at": "2026-10-25T09:13:23.43182369Z", "last": {"op": "restore", "stack": "tandoor", "ok": true, "message": "A(z) tandoor: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:14:05.47622
09:14:38Z tandoor: readback of the seeded account found=True
09:14:41Z state after restore: running, item: True, db auth errors: tandoor: 0
tandoor-postgres: 0
09:15:19Z [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,26 @@
09:15:44Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:18:15Z [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.0', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}
09:18:15Z [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:18:15Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:20Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:25Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:30Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:35Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:40Z gate: travel not routed right now (404) — not cached, asked again next call
09:18:45Z gate: travel is gated — passed as the household (cookie set)
09:18:53Z adventurelog: createsuperuser :: Superuser created successfully.
09:18:58Z adventurelog: seeded superuser drillf3d0fa
09:18:58Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:20:48Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'adventurelog', 'volumes_removed': ['adventurelog_adventurelog_media', 'adventurelog_adventurelog_postgres_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
09:20:53Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:23:24Z [1] deployed, controller state=unhealthy, pinned={'adventurelog': 'ghcr.io/seanmorley15/adventurelog-backend:v0.13.0', 'adventurelog-frontend': 'ghcr.io/seanmorley15/adventurelog-frontend:v0.13.0', 'adventurelog-postgres': 'postgis/postgis:16-3.5-alpine'}
09:23:24Z [1] NOTE: the controller's own state is 'unhealthy', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:23:37Z set aside: 2026/10/25 09:23:03 unit_owner.go:182: [INFO] [backup] adventurelog: the recovery unit of an earlier install (39b3ae7e65d7c197; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/adventurelog/20261025T092303Z; this install (920d6a875fa0dadf) gets its own unit f
09:23:44Z the set-aside unit is install A's unit byte for byte: True (8 files)
09:23:47Z [6] POST /backup/kept/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:24:33Z restore status: {"running": false, "op": "restore", "stack": "adventurelog", "started_at": "2026-10-25T09:23:47.915496662Z", "last": {"op": "restore", "stack": "adventurelog", "ok": true, "message": "A(z) adventurelog: 2 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-2
09:25:03Z adventurelog: readback of the seeded account found=True
09:25:06Z state after restore: running, item: True, db auth errors: adventurelog: 0
adventurelog-frontend: 0
adventurelog-postgres: 0
09:25:44Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'adventurelog', 'volumes_removed': ['adventurelog_adventurelog_media', 'adventurelog_adventurelog_postgres_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [],
@@ -0,0 +1,21 @@
09:37:11Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:37:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:38:47Z [1] deployed, controller state=running, pinned={'romm': 'rommapp/romm:5.3.1', 'romm-db': 'mariadb:11.8', 'romm-redis': 'redis:7-alpine'}
09:38:47Z gate: arcade is gated — passed as the household (cookie set)
09:38:55Z romm: POST /api/users http=201
09:38:55Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:40:23Z forged a future-dated second-drive copy: "at": "2026-10-28T06:39:39Z"
"at": "2026-10-28T06:39:39Z" (own unit: /mnt/felhom-drives/scratch_hdd/backups/primary/romm)
09:41:09Z [5] stop 200, remove KEEPING data -> 200 {'ok': True, 'data': {'removed': 'romm', 'volumes_removed': ['romm_romm_assets', 'romm_romm_config', 'romm_romm_db_data', 'romm_romm_redis_data'], 'hdd_paths_removed': [], 'hdd_paths_preserved': ['/mn
09:41:14Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:14Z [question, own copy + future copy] 409 {"code": "kept_data_choice", "use_offered": true, "use_desc": "Az adatbázist innen töltjük vissza: saját mentés, 2026-10-25 10:38. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.", "use_future": null, "use_warn": null, "use_off": ""}
09:41:17Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:17Z [question, the future copy alone] 409 {"code": "kept_data_choice", "use_offered": true, "use_desc": "Az adatbázist innen töltjük vissza: második meghajtó, 2026-10-28 07:39. A régi fájlokkal indítjuk az alkalmazást. Ami ezután változott, hiányozhat.", "use_future": true, "use_warn": "Figyelem: ennek a mentésnek a dátuma (2026-10-28 07:39) a jövőben van. A mentést készítő doboz órája rosszul járhatott. Csak akkor válaszd, ha biztosan ez a ti mentésetek.", "use_off": ""}
09:41:21Z [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']
09:41:21Z [1] deploy -> 202 {'ok': True, 'message': 'A(z) RomM megőrzött adatainak betöltése elindult.'}
09:42:26Z [1] deployed, controller state=degraded, pinned={'romm': 'rommapp/romm:5.3.1', 'romm-db': 'mariadb:11.8', 'romm-redis': 'redis:7-alpine'}
09:42:26Z [1] NOTE: the controller's own state is 'degraded', not 'running' — recorded, not treated as a failure; the fixture's front-door wait is the real gate
09:43:06Z load: {"running": false, "op": "restore", "stack": "romm", "started_at": "2026-10-25T09:41:21.356199563Z", "last": {"op": "restore", "stack": "romm", "ok": true, "message": "A(z) RomM a megőrzött adataival fut.", "finished_at": "2026-10-25T09:43:03.140979706Z"}, "last_recent": true}
09:43:15Z romm: login as the seeded user http=200 ok=True
09:43:15Z item after use-my-kept-data: True
09:43:57Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'romm', 'volumes_removed': ['romm_romm_assets', 'romm_romm_config', 'romm_romm_db_data', 'romm_romm_redis_data'], 'hdd_paths_removed': ['/mnt/felhom-drives/scratch_hdd
@@ -0,0 +1,27 @@
{
"app": "tandoor",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 65,
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"1m2.524018956s\", \"last_run\": \"2026-10-25T08:53:09.393020557Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"reinstall": true,
"set_aside_line": "2026/10/25 08:57:40 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (8ea077d3afae87ba; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T085740Z; this install (1988e29c0b9f3611) gets its own unit from its first backup (D47)",
"set_aside_dirs": [
"20261025T085740Z"
],
"set_aside_byte_identical": true,
"restore_page_offers": false,
"controller_lines": "2026/10/25 08:52:40 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n2026/10/25 08:53:09 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n2026/10/25 08:57:40 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (8ea077d3afae87ba; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T085740Z; this install (1988e29c0b9f3611) gets its own unit from its \n2026/10/25 08:57:40 recovery_unit.go:297: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n",
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
},
"set_aside_after_remove": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/set-aside/tandoor': No such file or directory"
}
@@ -0,0 +1,9 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
0959651afb912a643091755a23f08dc6a2910e550afc1c6e2eb81d868f498af5 ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
02fd085023c374b9e06ac2f5db44ade05c315a779a5d403c61e8ed419053644e ./data-stamps.json
d58224a5607756e43ae669394c1257df369fc8137476d2962100a44dc531ce0d ./db-dumps/tandoor-postgres.sql
e5c5f9c4d7f236c6be033af3971fd228d485cc90e6218f69245063768b9380c5 ./manifest.json
88bbb249fd079e05bbf8154c43bf5df99112b8517e9df76394a6b3d519b22045 ./volume-dumps/tandoor_tandoor_media.tar
478ad409250e6a4233e6e50ae268af26a13dc25029670f8a4d20ded57a0c25f2 ./volume-dumps/tandoor_tandoor_postgres_data.tar
2235a32d5bda20a8a3ef2940c049aea79b009759223ad1ac6efa47ed72d7db4d ./volume-dumps/tandoor_tandoor_static.tar
@@ -0,0 +1,9 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
0959651afb912a643091755a23f08dc6a2910e550afc1c6e2eb81d868f498af5 ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
02fd085023c374b9e06ac2f5db44ade05c315a779a5d403c61e8ed419053644e ./data-stamps.json
d58224a5607756e43ae669394c1257df369fc8137476d2962100a44dc531ce0d ./db-dumps/tandoor-postgres.sql
e5c5f9c4d7f236c6be033af3971fd228d485cc90e6218f69245063768b9380c5 ./manifest.json
88bbb249fd079e05bbf8154c43bf5df99112b8517e9df76394a6b3d519b22045 ./volume-dumps/tandoor_tandoor_media.tar
478ad409250e6a4233e6e50ae268af26a13dc25029670f8a4d20ded57a0c25f2 ./volume-dumps/tandoor_tandoor_postgres_data.tar
2235a32d5bda20a8a3ef2940c049aea79b009759223ad1ac6efa47ed72d7db4d ./volume-dumps/tandoor_tandoor_static.tar
@@ -0,0 +1,4 @@
761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6 ./compose/.felhom.yml
ad9754c68958c76847c891b0b106d276ddc532788642c6c9cf861ca3e05fb91d ./compose/app.yaml
851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25 ./compose/docker-compose.yml
34699a9f0c9c642f80523e8bbee7127d699373590cfa977b626dfb110f9dbf4d ./manifest.json
@@ -0,0 +1,13 @@
08:49:25Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:51:50Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:51:50Z gate: recipes is gated — passed as the household (cookie set)
08:52:02Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
08:52:06Z tandoor: seeded superuser drilla8c353
08:52:06Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
08:53:49Z [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:53:54Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:56:10Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:57:42Z set aside: 2026/10/25 08:57:40 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (8ea077d3afae87ba; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T085740Z; this install (1988e29c0b9f3611) gets its own unit from its fi
08:57:49Z the set-aside unit is install A's unit byte for byte: True (9 files)
08:57:52Z the restore page offers NO restore of the set-aside unit
08:58:30Z [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,13 @@
08:49:25Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:51:50Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:51:50Z gate: recipes is gated — passed as the household (cookie set)
08:52:02Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
08:52:06Z tandoor: seeded superuser drilla8c353
08:52:06Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
08:53:49Z [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:53:54Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
08:56:10Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:57:42Z set aside: 2026/10/25 08:57:40 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (8ea077d3afae87ba; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T085740Z; this install (1988e29c0b9f3611) gets its own unit from its fi
08:57:49Z the set-aside unit is install A's unit byte for byte: True (9 files)
08:57:52Z the restore page offers NO restore of the set-aside unit
08:58:30Z [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,22 @@
{
"app": "vikunja",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 60,
"status": "{\"db_dump\": {\"count\": 2, \"duration\": \"55.138182754s\", \"last_run\": \"2026-10-25T09:27:17.793830395Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"unit_files": 7,
"controller_lines": "",
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
},
"test_copy_removed": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/d48-test-original/vikunja': No such file or directory",
"restore_undo_left": "ls: cannot access '/mnt/sys_drive/felhom-data/backups/restore-undo/vikunja': No such file or directory"
}
@@ -0,0 +1,7 @@
09:26:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:26:22Z [1] deployed, controller state=running, pinned={'vikunja': 'vikunja/vikunja:2.6.0'}
09:26:22Z gate: tasks is gated — passed as the household (cookie set)
09:26:22Z vikunja: register http=200
09:26:22Z vikunja: create project http=201
09:26:22Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:28:09Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'vikunja', 'volumes_removed': ['vikunja_vikunja_data', 'vikunja_vikunja_db'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalmazás nem tárolt
@@ -0,0 +1,15 @@
09:26:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:26:22Z [1] deployed, controller state=running, pinned={'vikunja': 'vikunja/vikunja:2.6.0'}
09:26:22Z gate: tasks is gated — passed as the household (cookie set)
09:26:22Z vikunja: register http=200
09:26:22Z vikunja: create project http=201
09:26:22Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:28:09Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'vikunja', 'volumes_removed': ['vikunja_vikunja_data', 'vikunja_vikunja_db'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalmazás nem tárolt
Traceback (most recent call last):
File "/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/restore-truth-2026-10-25/tools/pullprobe.py", line 121, in <module>
main(sys.argv[1], sys.argv[2], sys.argv[3] if len(sys.argv) > 3 else "")
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/mnt/5_hdd/felhom.eu/git/felhom.eu/documentation/audits/restore-truth-2026-10-25/tools/pullprobe.py", line 83, in main
say(" [D48] the unit's pin → " + repo + ":" + MISSING_TAG + " :: " + edit(f"{repo}:{MISSING_TAG}").replace("\n", " "))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'replace'
@@ -0,0 +1,17 @@
09:03:52Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:06:02Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
09:06:02Z gate: recipes is gated — passed as the household (cookie set)
09:06:15Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
09:06:19Z tandoor: seeded superuser drill69d6f1
09:06:20Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:08:02Z [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': [],
09:08:07Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:10:33Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
09:13:13Z set aside: 2026/10/25 09:13:03 unit_owner.go:182: [INFO] [backup] tandoor: the recovery unit of an earlier install (77ea4da495f5cdbf; the install ids differ) is SET ASIDE whole → /mnt/sys_drive/felhom-data/backups/set-aside/tandoor/20261025T091303Z; this install (bf68aee48f37e20e) gets its own unit from its fi
09:13:20Z the set-aside unit is install A's unit byte for byte: True (9 files)
09:13:23Z [6] POST /backup/kept/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:14:08Z restore status: {"running": false, "op": "restore", "stack": "tandoor", "started_at": "2026-10-25T09:13:23.43182369Z", "last": {"op": "restore", "stack": "tandoor", "ok": true, "message": "A(z) tandoor: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:14:05.47622
09:14:38Z tandoor: readback of the seeded account found=True
09:14:41Z state after restore: running, item: True, db auth errors: tandoor: 0
tandoor-postgres: 0
09:15:19Z [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,27 @@
09:28:46Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
09:28:56Z [1] deployed, controller state=running, pinned={'vikunja': 'vikunja/vikunja:2.6.0'}
09:28:56Z gate: tasks is gated — passed as the household (cookie set)
09:28:57Z vikunja: register http=200
09:28:57Z vikunja: create project http=201
09:28:57Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:30:08Z [D48] the unit's pin → vikunja/vikunja:0.0.0-felhom-d48-missing :: compose/docker-compose.yml:1 manifest.json:7 data-stamps.json:4
09:30:11Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:30:21Z d48_restore: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:30:11.335278772Z", "last": {"op": "restore", "stack": "vikunja", "ok": false, "message": "Visszaállítás sikertelen: Ennek a mentésnek a verzióját (vikunja:0.0.0-felhom-d48-missing) nem lehet letölteni: a készítője már nem kínálja. Az alkalmazáshoz nem nyúltunk. Válassz egy másik mentést.", "finished_at": "2026-10-
09:30:24Z [D48] containers never restarted: True (/vikunja 2026-10-25T09:29:54.57273795Z running)
09:30:25Z vikunja: readback of the seeded project http=200 ok=True
09:30:31Z the original unit is back byte for byte: True
09:30:31Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:30:41Z normal_restore_1: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:30:31.410646319Z", "last": {"op": "restore", "stack": "vikunja", "ok": true, "message": "A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:30:38.26202133Z"}, "last_recent": true}
09:30:41Z vikunja: readback of the seeded project http=200 ok=True
09:30:41Z normal restore: item back True, state running
09:30:41Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
09:31:47Z [R-1270] the unit's pin → busybox:1.36.1 (pulls, exits at once) :: compose/docker-compose.yml:1 manifest.json:7 data-stamps.json:4
09:31:47Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:33:28Z r1270_restore: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:31:47.895007425Z", "last": {"op": "restore", "stack": "vikunja", "ok": false, "message": "A(z) vikunja: az adatokat visszatöltöttük, de az alkalmazás még nem indult el. Várj pár percet, majd nyisd meg újra. Ha így marad, szólj nekünk.", "finished_at": "2026-10-25T09:33:26.51097487Z", "not_started": true}, "last_re
09:33:31Z [R-1270] state restarting, kept undo copy: 20261025T093149Z
09:33:38Z the original unit is back byte for byte: True
09:33:38Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
09:33:48Z normal_restore_2: {"running": false, "op": "restore", "stack": "vikunja", "started_at": "2026-10-25T09:33:38.075945508Z", "last": {"op": "restore", "stack": "vikunja", "ok": true, "message": "A(z) vikunja: 2 adatkötet visszaállítva — az alkalmazás újraindult.", "finished_at": "2026-10-25T09:33:44.816871537Z"}, "last_recent": true}
09:33:48Z vikunja: readback of the seeded project http=200 ok=True
09:33:48Z normal restore 2: item back True, state running
09:34:24Z [7] stop 200, remove with data -> 200 {'ok': True, 'data': {'removed': 'vikunja', 'volumes_removed': ['vikunja_vikunja_data', 'vikunja_vikunja_db'], 'hdd_paths_removed': [], 'hdd_paths_preserved': [], 'hdd_note': 'Az alkalmazás nem tárolt
@@ -0,0 +1,33 @@
{
"app": "tandoor",
"install": true,
"seed": true,
"backup": {
"code": "200",
"seconds": 65,
"status": "{\"db_dump\": {\"count\": 3, \"duration\": \"1m2.207105181s\", \"last_run\": \"2026-10-25T07:53:46.828178317Z\", \"success\": true}, \"enabled\": true, \"running\": false}"
},
"reinstall": true,
"capture_after_reinstall": "2026/10/25 08:00:36 recovery_unit.go:289: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)",
"restore": {
"points": 1,
"location": [
"location: /backups/restore?flash=flash.restore.started"
],
"seconds": 116,
"status": "{\"running\": false, \"op\": \"restore\", \"stack\": \"tandoor\", \"started_at\": \"2026-10-25T08:00:41.705408544Z\", \"last\": {\"op\": \"restore\", \"stack\": \"tandoor\", \"ok\": true, \"message\": \"A(z) tandoor: 3 adatkötet és az adatbázis visszaállítva — az alkalmazás újraindult.\", \"finished_at\": \"2026-10-25T08:02:35.841483455Z\"}, \"last_recent\": true}",
"state": "starting"
},
"state_after_restore": "starting",
"item_after_restore": false,
"db_auth_errors_after_restore": "tandoor: 44\ntandoor-postgres: 23",
"controller_restore_lines": "2026/10/25 07:55:47 manager.go:1815: [INFO] [stacks] tandoor ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72 running Up 3 seconds (health: starting)\n2026/10/25 07:55:47 manager.go:1815: [INFO] [stacks] tandoor-postgres postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24 running Up 9 seconds (healthy)\n2026/10/25 07:56:56 healthprobe.go:187: [DEBUG] Health probe tandoor: HTTP GET :80/accounts/login/ → 400 (189ms)\n2026/10/25 07:57:06 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 10s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:57:16 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 20s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:57:26 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 30s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:57:36 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 40s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:57:46 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 50s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:57:56 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m0s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:06 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m10s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:16 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m20s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:26 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m30s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:36 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m40s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:46 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 1m50s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:58:56 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m0s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:06 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m10s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:16 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m20s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:26 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m30s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:36 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m40s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:46 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 2m50s ago, effective interval 5m0s, healthy=true\n2026/10/25 07:59:56 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 3m0s ago, effective interval 5m0s, healthy=true\n2026/10/25 08:00:06 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 3m10s ago, effective interval 5m0s, healthy=true\n2026/10/25 08:00:16 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 3m20s ago, effective interval 5m0s, healthy=true\n2026/10/25 08:00:26 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 3m30s ago, effective interval 5m0s, healthy=true\n2026/10/25 08:00:36 healthprobe.go:64: [DEBUG] [stacks] RunHealthProbes: skipping tandoor — last check 3m40s ago, effective interval 5m0s, healthy=true\n2026/10/25 08:00:36 recovery_unit.go:289: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable-carried=2/2, withheld=0)\n2026/10/25 08:00:41 handlers.go:1846: [DEBUG] [web] backupRestoreHandler: stack=tandoor snapshot=helyi from 172.18.0.4:33912\n2026/10/25 08:00:41 handlers.go:1888: [WARN] [web] Restore requested (async): stack=tandoor, snapshot=helyi from 172.18.0.4:33912\n2026/10/25 08:00:41 restore_dbcreds.go:114: [INFO] [backup] Restore tandoor: database password(s) [DB_PASSWORD] come from the backup, [] stay as installed (older than the data) — values not logged (R-1106)\n2026/10/25 08:00:41 restore_unit.go:410: [INFO] [backup] Restoring tandoor from recovery unit /mnt/sys_drive/felhom-data/backups/primary/tandoor: images=2, secrets recovered=2/2, data_keys=0\n2026/10/25 08:00:50 offbox_restore_undo.go:163: [INFO] [offbox] tandoor: the live volumes are copied before the restore Line truncated
"after_remove": {
"containers": "",
"volumes": "",
"appyaml": "",
"appdata": "",
"kept": "",
"subdomain": "404"
}
}
@@ -0,0 +1,126 @@
.:
total 32
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 .
drwxr-xr-x 4 root root 4096 2026-10-25T07:52:44 ..
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:46 compose
-rw-r--r-- 1 root root 2504 2026-10-25T07:53:40 data-stamps.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 db-dumps
-rw-r--r-- 1 root root 4718 2026-10-25T07:53:46 manifest.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 volume-dumps
db-dumps:
total 400
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 .
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 ..
-rw-r--r-- 1 root root 397902 2026-10-25T07:52:45 tandoor-postgres.sql
volume-dumps:
total 147340
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 .
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 ..
-rw-r--r-- 1 root root 1536 2026-10-25T07:53:36 tandoor_tandoor_media.tar
-rw-r--r-- 1 root root 56538624 2026-10-25T07:53:37 tandoor_tandoor_postgres_data.tar
-rw-r--r-- 1 root root 94322176 2026-10-25T07:53:39 tandoor_tandoor_static.tar
== manifest.json
{
"schema_version": 2,
"app_name": "tandoor",
"display_name": "Tandoor Recipes",
"controller_version": "0.342.0",
"created_at": "2026-10-25T07:53:46Z",
"drive": "/mnt/sys_drive",
"namespace_root": "/mnt/sys_drive/felhom-data",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data_key_env_vars": null,
"secret_source": "portable secrets (data keys, DB passwords, internal signing secrets) are IN this unit's compose/app.yaml (0600); internet-reachable admin logins are NOT, and come from the guest's app.yaml or are regenerated on restore",
"config_files": [
"docker-compose.yml",
".felhom.yml",
"app.yaml"
],
"db_dumps": [
"tandoor-postgres.sql"
],
"volume_dumps": [
"tandoor_tandoor_media.tar",
"tandoor_tandoor_postgres_data.tar",
"tandoor_tandoor_static.tar"
],
"checksums": {
".felhom.yml": "761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6",
"app.yaml": "cbfcb538053217d4a9ca395383648fb47b9449ffd23e818840ab277956098e96",
"docker-compose.yml": "851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25"
},
"portable_secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data": {
"at": "2026-10-25T07:52:45Z",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
},
"files": {
"db-dumps/tandoor-postgres.sql": {
"at": "2026-10-25T07:52:45.200747249Z",
"size": 397902,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_media.tar": {
"at": "2026-10-25T07:53:36.966857429Z",
"size": 1536,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_postgres_data.tar": {
"at": "2026-10-25T07:53:37.559407527Z",
"size": 56538624,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_static.tar": {
"at": "2026-10-25T07:53:39.14242749Z",
"size": 94322176,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
}
}
}
}
@@ -0,0 +1,126 @@
.:
total 32
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 .
drwxr-xr-x 4 root root 4096 2026-10-25T07:52:44 ..
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:46 compose
-rw-r--r-- 1 root root 2504 2026-10-25T07:53:40 data-stamps.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 db-dumps
-rw-r--r-- 1 root root 4718 2026-10-25T07:53:46 manifest.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 volume-dumps
db-dumps:
total 400
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 .
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 ..
-rw-r--r-- 1 root root 397902 2026-10-25T07:52:45 tandoor-postgres.sql
volume-dumps:
total 147340
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 .
drwxr-xr-x 5 root root 4096 2026-10-25T07:53:46 ..
-rw-r--r-- 1 root root 1536 2026-10-25T07:53:36 tandoor_tandoor_media.tar
-rw-r--r-- 1 root root 56538624 2026-10-25T07:53:37 tandoor_tandoor_postgres_data.tar
-rw-r--r-- 1 root root 94322176 2026-10-25T07:53:39 tandoor_tandoor_static.tar
== manifest.json
{
"schema_version": 2,
"app_name": "tandoor",
"display_name": "Tandoor Recipes",
"controller_version": "0.342.0",
"created_at": "2026-10-25T07:53:46Z",
"drive": "/mnt/sys_drive",
"namespace_root": "/mnt/sys_drive/felhom-data",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data_key_env_vars": null,
"secret_source": "portable secrets (data keys, DB passwords, internal signing secrets) are IN this unit's compose/app.yaml (0600); internet-reachable admin logins are NOT, and come from the guest's app.yaml or are regenerated on restore",
"config_files": [
"docker-compose.yml",
".felhom.yml",
"app.yaml"
],
"db_dumps": [
"tandoor-postgres.sql"
],
"volume_dumps": [
"tandoor_tandoor_media.tar",
"tandoor_tandoor_postgres_data.tar",
"tandoor_tandoor_static.tar"
],
"checksums": {
".felhom.yml": "761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6",
"app.yaml": "cbfcb538053217d4a9ca395383648fb47b9449ffd23e818840ab277956098e96",
"docker-compose.yml": "851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25"
},
"portable_secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data": {
"at": "2026-10-25T07:52:45Z",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
},
"files": {
"db-dumps/tandoor-postgres.sql": {
"at": "2026-10-25T07:52:45.200747249Z",
"size": 397902,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_media.tar": {
"at": "2026-10-25T07:53:36.966857429Z",
"size": 1536,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_postgres_data.tar": {
"at": "2026-10-25T07:53:37.559407527Z",
"size": 56538624,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_static.tar": {
"at": "2026-10-25T07:53:39.14242749Z",
"size": 94322176,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
}
}
}
}
@@ -0,0 +1,126 @@
.:
total 32
drwxr-xr-x 5 root root 4096 2026-10-25T08:00:36 .
drwxr-xr-x 4 root root 4096 2026-10-25T07:52:44 ..
drwxr-xr-x 2 root root 4096 2026-10-25T08:00:36 compose
-rw-r--r-- 1 root root 2504 2026-10-25T07:53:40 data-stamps.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 db-dumps
-rw-r--r-- 1 root root 4718 2026-10-25T08:00:36 manifest.json
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 volume-dumps
db-dumps:
total 400
drwxr-xr-x 2 root root 4096 2026-10-25T07:52:45 .
drwxr-xr-x 5 root root 4096 2026-10-25T08:00:36 ..
-rw-r--r-- 1 root root 397902 2026-10-25T07:52:45 tandoor-postgres.sql
volume-dumps:
total 147340
drwxr-xr-x 2 root root 4096 2026-10-25T07:53:40 .
drwxr-xr-x 5 root root 4096 2026-10-25T08:00:36 ..
-rw-r--r-- 1 root root 1536 2026-10-25T07:53:36 tandoor_tandoor_media.tar
-rw-r--r-- 1 root root 56538624 2026-10-25T07:53:37 tandoor_tandoor_postgres_data.tar
-rw-r--r-- 1 root root 94322176 2026-10-25T07:53:39 tandoor_tandoor_static.tar
== manifest.json
{
"schema_version": 2,
"app_name": "tandoor",
"display_name": "Tandoor Recipes",
"controller_version": "0.342.0",
"created_at": "2026-10-25T08:00:36Z",
"drive": "/mnt/sys_drive",
"namespace_root": "/mnt/sys_drive/felhom-data",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data_key_env_vars": null,
"secret_source": "portable secrets (data keys, DB passwords, internal signing secrets) are IN this unit's compose/app.yaml (0600); internet-reachable admin logins are NOT, and come from the guest's app.yaml or are regenerated on restore",
"config_files": [
"docker-compose.yml",
".felhom.yml",
"app.yaml"
],
"db_dumps": [
"tandoor-postgres.sql"
],
"volume_dumps": [
"tandoor_tandoor_media.tar",
"tandoor_tandoor_postgres_data.tar",
"tandoor_tandoor_static.tar"
],
"checksums": {
".felhom.yml": "761d5637752bf2695aaff064bcd7973fd5301bff2536e067a762e348a58cfad6",
"app.yaml": "e19d2610820c4c974335b7b3609330fb11a5a2a608c719150642a81997288ce6",
"docker-compose.yml": "851523d2779a6739bd464fd2dc415a191164afcd7aae9d195fbc482a28ec8b25"
},
"portable_secret_env_vars": [
"SECRET_KEY",
"DB_PASSWORD"
],
"data": {
"at": "2026-10-25T07:52:45Z",
"image_pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
},
"files": {
"db-dumps/tandoor-postgres.sql": {
"at": "2026-10-25T07:52:45.200747249Z",
"size": 397902,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_media.tar": {
"at": "2026-10-25T07:53:36.966857429Z",
"size": 1536,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_postgres_data.tar": {
"at": "2026-10-25T07:53:37.559407527Z",
"size": 56538624,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
},
"volume-dumps/tandoor_tandoor_static.tar": {
"at": "2026-10-25T07:53:39.14242749Z",
"size": 94322176,
"pins": [
"ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
],
"images": {
"tandoor": "ghcr.io/tandoorrecipes/recipes:2.6.15@sha256:2e759dd1478a2ed119ee474e28522079fb1cfa50b3fd25cba89f6b9a67abad72",
"tandoor-postgres": "postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24"
}
}
}
}
}
@@ -0,0 +1,15 @@
07:50:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
07:52:27Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
07:52:27Z gate: recipes is gated — passed as the household (cookie set)
07:52:40Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
07:52:44Z tandoor: seeded superuser drill0dcaea
07:52:44Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
07:54:26Z [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': [],
07:54:35Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
07:56:46Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:00:38Z capture after the reinstall: 2026/10/25 08:00:36 recovery_unit.go:289: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable
08:00:41Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
08:03:02Z tandoor: READBACK UNUSABLE — a username that cannot exist did not read as absent (None) :: n3.13/site-packages/psycopg2/__init__.py", line 122, in connect conn = _connect(dsn, connection_factory=connection_factory, **kwasync) django.db.utils.OperationalError: connection to server at "tandoo
08:03:08Z state after restore: starting, item: False, db auth errors: tandoor: 44
tandoor-postgres: 23
08:03:43Z [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,15 @@
07:50:12Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
07:52:27Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
07:52:27Z gate: recipes is gated — passed as the household (cookie set)
07:52:40Z tandoor: createsuperuser :: Running django-vite in production mode (no HMR) Superuser created successfully.
07:52:44Z tandoor: seeded superuser drill0dcaea
07:52:44Z [4] Mentés most -> 200 {'ok': True, 'message': 'Mentés elindítva'}
07:54:26Z [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': [],
07:54:35Z [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}
07:56:46Z [1] deployed, controller state=running, pinned={'tandoor': 'ghcr.io/tandoorrecipes/recipes:2.6.15', 'tandoor-postgres': 'postgres:17-alpine'}
08:00:38Z capture after the reinstall: 2026/10/25 08:00:36 recovery_unit.go:289: [INFO] [backup] Recovery unit captured for tandoor → /mnt/sys_drive/felhom-data/backups/primary/tandoor (images=2, secrets-referenced=2, data_keys=0, portable
08:00:41Z [6] POST /backup/restore -> HTTP/2 302 ['location: /backups/restore?flash=flash.restore.started']
08:03:02Z tandoor: READBACK UNUSABLE — a username that cannot exist did not read as absent (None) :: n3.13/site-packages/psycopg2/__init__.py", line 122, in connect conn = _connect(dsn, connection_factory=connection_factory, **kwasync) django.db.utils.OperationalError: connection to server at "tandoo
08:03:08Z state after restore: starting, item: False, db auth errors: tandoor: 44
tandoor-postgres: 23
08:03:43Z [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,26 @@
# D47 red-proof: guardUnitDir returns nil at once (= e1613ae: no guard). 2026-10-25T08:02:42Z
=== RUN TestD47_TheSweepOrderNeverRewritesTheKeptUnit
unit_owner_test.go:117: install A's unit must be set aside whole (one folder), found []; primary app.yaml now: "# Captured by felhom-controller recovery unit.\n# This file CARRIES SECRETS (D5) so a Tier-1/2 restore needs the drive and nothing else:\n# data
--- FAIL: TestD47_TheSweepOrderNeverRewritesTheKeptUnit (0.00s)
=== RUN TestD47_AUnitFromBeforeD47IsSetAsideWhenItsPasswordDiffers
unit_owner_test.go:152: an unrecorded unit with another install's password must be set aside whole, found []
--- FAIL: TestD47_AUnitFromBeforeD47IsSetAsideWhenItsPasswordDiffers (0.00s)
=== RUN TestD47_TheSetAsideUnitRestoresWithItsOwnPassword
unit_owner_test.go:165: one kept copy expected, got []
--- FAIL: TestD47_TheSetAsideUnitRestoresWithItsOwnPassword (0.00s)
=== RUN TestD47_TheWriterRefusesWhenTheUnitCannotBeSetAside
unit_owner_test.go:199: the capture must refuse, got <nil>
--- FAIL: TestD47_TheWriterRefusesWhenTheUnitCannotBeSetAside (0.00s)
=== RUN TestD47_TheNightDatabaseDumpSetsTheEarlierUnitAsideFirst
unit_owner_test.go:236: install A's unit must be set aside whole before install B's dump is written, found []
--- FAIL: TestD47_TheNightDatabaseDumpSetsTheEarlierUnitAsideFirst (0.00s)
=== RUN TestD47_ASameInstallBackupStillRefreshesTheUnit
--- PASS: TestD47_ASameInstallBackupStillRefreshesTheUnit (0.00s)
=== RUN TestD47_NoSetAsideWhileTheAppIsRestored
unit_owner_test.go:275: a write during the app's restore must refuse, got <nil>
--- FAIL: TestD47_NoSetAsideWhileTheAppIsRestored (0.00s)
=== RUN TestD47_OwnerVerdict
--- PASS: TestD47_OwnerVerdict (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.015s
FAIL
@@ -0,0 +1,10 @@
# D47 with the guard: 2026-10-25T08:02:42Z
--- PASS: TestD47_TheSweepOrderNeverRewritesTheKeptUnit (0.00s)
--- PASS: TestD47_AUnitFromBeforeD47IsSetAsideWhenItsPasswordDiffers (0.00s)
--- PASS: TestD47_TheSetAsideUnitRestoresWithItsOwnPassword (0.00s)
--- PASS: TestD47_TheWriterRefusesWhenTheUnitCannotBeSetAside (0.00s)
--- PASS: TestD47_TheNightDatabaseDumpSetsTheEarlierUnitAsideFirst (0.00s)
--- PASS: TestD47_ASameInstallBackupStillRefreshesTheUnit (0.00s)
--- PASS: TestD47_NoSetAsideWhileTheAppIsRestored (0.00s)
--- PASS: TestD47_OwnerVerdict (0.00s)
ok gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.031s
@@ -0,0 +1,6 @@
# D47 web red-proof: the kept section only inside the off-site card (the old place). 2026-10-25T09:00:05Z
kept_copies_test.go:177: a box without off-site must list its kept copies once, with the restore
--- FAIL: TestD47_KeptCopiesAreListedWithoutOffsite (0.06s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.068s
FAIL
@@ -0,0 +1,9 @@
# D47 stacks red-proof: the restore never takes the unit's install (case disabled). 2026-10-25T08:03:15Z
install_id_test.go:21: the restored app must be the unit's install, got &{Deployed:true DeployedAt:2026-10-25T08:03:18Z Env:map[DOMAIN:example.hu SUBDOMAIN:gapp] LockedFields:[DOMAIN SUBDOMAIN] EmailEnabled:false DesiredState: InstalledImages:map[] PinnedImages:map[] LastUpdateUndone:<nil> FailedStep:<nil> LastAutoUpdate:<nil> ConversionCopy:<nil> EarlierConversionCopies:[] RestoredLogins:[] AfterInstall:<nil> SetupGate:<nil> FamilyGate:<nil> InstallHold:<nil> PreviousImages:map[] DefaultLogin:<nil> AfterSetup:<nil> AfterUncleanBoot:<nil> InstallID:bbbb000000000002}
--- FAIL: TestD47_ARestoreTakesTheUnitsInstall (0.00s)
--- PASS: TestD47_ARestoreOfAnUnrecordedUnitKeepsTheAppsInstall (0.00s)
--- PASS: TestD47_ARemovedAppRestoredGetsAnInstall (0.00s)
--- PASS: TestD47_EnsureInstallIDMintsOnce (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/stacks 0.016s
FAIL
@@ -0,0 +1,7 @@
# D47 web red-proof: the restore form never renders. 2026-10-25T08:13:32Z
kept_copies_test.go:112: exactly the set-aside unit's row offers the restore, found 0
--- FAIL: TestD47_RestorePageOffersRestoreOnlyForASetAsideUnit (0.06s)
--- PASS: TestD47_KeptUnitRestoreHandlerRefusals (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.071s
FAIL
@@ -0,0 +1,15 @@
# D48 red-proof: prepareRestoreImages does nothing (= e1613ae: no pull before the stop). 2026-10-25T08:36:14Z
restore_pull_test.go:36: an unpullable pin must refuse, got <nil> (pulled [])
--- FAIL: TestD48_AnUnpullablePinIsRefusedBeforeTheStop (0.00s)
restore_pull_test.go:58: the restore never asked for the image (err <nil>)
--- FAIL: TestD48_AnUnreachableRegistryReadsDifferently (0.00s)
restore_pull_test.go:80: the pull must come before the stop, calls [stop recreate startsvc:immich-postgres start]
--- FAIL: TestD48_APullablePinIsPulledFirstAndTheRestoreRuns (0.00s)
restore_pull_test.go:105: the check must refuse an unpullable pin, got <nil>
--- FAIL: TestD48_TheCheckOnlyPassCarriesThePull (0.00s)
restore_pull_test.go:118: an off-site restore with an unpullable image must refuse, got <nil>
--- FAIL: TestD48_TheOffsiteRestoreToo (0.00s)
--- PASS: TestD48_PullGone (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.016s
FAIL
@@ -0,0 +1,12 @@
# R-1270 red-proof: the health timeout back to a WARN (REDPROOF=1 skips restoreNotStarted). 2026-10-25T08:30:44Z
restore_verdict_test.go:48: a restore whose app did not start must not be a success, got <nil>
--- FAIL: TestR1270_AUnitRestoreWhoseAppDoesNotStartIsNotASuccess (0.05s)
--- PASS: TestR1270_AHealthyRestoreIsASuccessAsBefore (0.00s)
restore_verdict_test.go:87: precondition: not started, got <nil>
--- FAIL: TestR1270_ALateStartTurnsTheRecordIntoASuccess (0.05s)
restore_verdict_test.go:121: an off-site restore whose app did not start must not be a success, got <nil>
--- FAIL: TestR1270_TheOffsiteRestoreToo (0.05s)
--- PASS: TestR1270_MarkLateStartTouchesOnlyItsOwnRecord (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.170s
FAIL
@@ -0,0 +1,6 @@
# R-1270 web red-proof: endRestoreFailed treats a not-started restore as a failure. 2026-10-25T08:31:17Z
r1270_not_started_test.go:29: a not-started restore is recorded not ok and not started: &{Op:restore Stack:tandoor OK:false Message:Visszaállítás sikertelen: A(z) tandoor: az adatokat visszatöltöttük, de az alkalmazás még nem indult el. Várj pár percet, majd nyisd meg újra. Ha így marad, szólj nekünk. FinishedAt:2026-10-25 09:31:23.202219096 +0100 CET m=+0.013726945 Interrupted:false PutBack:false PutBackWaiting:false NotStarted:false}
--- FAIL: TestR1270_TheRecordOfANotStartedRestore (0.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/web 0.021s
FAIL
@@ -0,0 +1,16 @@
# R-1271 red-proof: KeptFuture always false (= e1613ae: the newest date wins, future or not). 2026-10-25T08:40:34Z
kept_pick_test.go:21: the household's own copy must win over a future-dated off-site one, got {UnitDir: Tier:3 Time:2026-10-28 06:39:00 +0000 UTC DriveLabel: SnapshotID:abba81ba UnitPath: Future:false}
--- FAIL: TestR1271_AFutureOffsiteCopyNeverBeatsTheOwnCopy (0.00s)
kept_pick_test.go:29: a future-dated copy alone is offered and marked Future (not recommended), got {UnitDir: Tier:3 Time:2026-10-28 06:39:00 +0000 UTC DriveLabel: SnapshotID:abba81ba UnitPath: Future:false} ok=true
--- FAIL: TestR1271_AFutureCopyAloneIsOfferedButMarked (0.00s)
--- PASS: TestR1271_AnOlderOffsiteCopyAloneIsChosenAsBefore (0.00s)
--- PASS: TestR1271_ANewerTrueOffsiteCopyStillWins (0.00s)
kept_pick_test.go:64: a copy beyond the skew is future-dated and never the newest, got {UnitDir: Tier:3 Time:2026-10-24 19:33:00 +0000 UTC DriveLabel: SnapshotID:f UnitPath: Future:false}
--- FAIL: TestR1271_TheClockSkewAllowance (0.00s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/backup 0.006s
r1271_future_copy_test.go:83: hu: a future-dated only copy is offered, marked and said: offered=true future=<nil> warn=""
--- FAIL: TestR1271_AFutureCopyAloneIsSaidAndNotRecommended (0.01s)
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/api 0.019s
FAIL
@@ -0,0 +1,5 @@
--- FAIL: TestR474_RemoveHandlerDeletesUnitMirrorAndPrefs (0.00s)
r474_remove_wiring_test.go:41: removeStack must call RestoreUndoDir
FAIL
FAIL gitea.dooplex.hu/admin/felhom-controller/internal/api 0.010s
FAIL
@@ -0,0 +1,102 @@
#!/usr/bin/env python3
"""keptprobe.py — R-1271 live, on a throwaway drive-folder app this run installs (never a household's unit).
The measured case (catalog sweep 2026-10-24): a copy dated in the future beat the family's own copy. Here the
future-dated copy is FORGED on 9202 in a scratch place every box looks at — a second-drive copy of the app's own unit
under the system drive's backups/secondary/<app>/recovery-unit, its data time set to 2026-10-28T06:39:39Z (the
rehearsal box's clock), the only hand-made change. Then the household's order:
install, seed, „Mentés most", remove keeping data, install again → the question (expect: the OWN copy named, no
future flag); the own unit moved aside for a moment → the question again (expect: the forged copy offered, marked
future, with the sentence, not recommended); the own unit back → „A megőrzött adataimat használom" → the item back.
Then remove with data (the forged copy goes with the app's second-drive copies).
usage: SC=… SWEEP_EV=… TARGET=9202 DRIVE_ROOT=… python3 keptprobe.py <app>
"""
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
FUTURE = "2026-10-28T06:39:39Z"
def ask(app, sub):
os.environ.pop("KEPT", None)
c, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": dict(w.deploy_values(app, sub, dict(w.GENERATED.get(app) or {})))})
data = (d.get("data") or {}) if isinstance(d, dict) else {}
return c, {k: data.get(k) for k in ("code", "use_offered", "use_desc", "use_future", "use_warn", "use_off")}
def main(app):
d = os.path.join(sw.EV, "_keptprobe", app)
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}
forged = f"/mnt/sys_drive/felhom-data/backups/secondary/{app}/recovery-unit"
t_start = int(time.time())
unit = ""
w.login()
try:
rec["install"] = w.deploy(app, sub) and w.wait_app(sub, "/", tries=120, delay=5)
tok = fx.seed(w, sub, say)
rec["seed"] = bool(tok)
sw.backup_now(rec, say)
unit = sw.g(f"for p in /mnt/felhom-drives/*/backups/primary/{app} /mnt/felhom-drives/*/felhom-data/backups/primary/{app}; do [ -f $p/manifest.json ] && echo $p; done | head -1").strip()
rec["own_unit"] = unit
if not unit:
say(" no unit of the app on its drive — stop")
return
sw.g(f"rm -rf /mnt/sys_drive/felhom-data/backups/secondary/{app}; mkdir -p /mnt/sys_drive/felhom-data/backups/secondary/{app} && cp -a {unit} {forged} && "
f"sed -i -E 's/\"at\": \"[^\"]+\"/\"at\": \"{FUTURE}\"/' {forged}/manifest.json")
rec["forged_at"] = sw.g(f"grep -o '\"at\": \"[^\"]*\"' {forged}/manifest.json | head -2").strip()
say(f" forged a future-dated second-drive copy: {rec['forged_at']} (own unit: {unit})")
sw.remove(app, keep=True, say=say)
rec["q1_code"], rec["q1"] = ask(app, sub)
say(f" [question, own copy + future copy] {rec['q1_code']} {json.dumps(rec['q1'], ensure_ascii=False)[:400]}")
sw.g(f"mv {unit} {unit}.r1271-away")
rec["q2_code"], rec["q2"] = ask(app, sub)
say(f" [question, the future copy alone] {rec['q2_code']} {json.dumps(rec['q2'], ensure_ascii=False)[:500]}")
sw.g(f"mv {unit}.r1271-away {unit}")
os.environ["KEPT"] = "use"
w.DEPLOYED_THIS_RUN.discard(app)
rec["use_ok"] = w.deploy(app, sub, dict(w.GENERATED.get(app) or {}))
os.environ.pop("KEPT", None)
t0, last = time.time(), None
while time.time() - t0 < 1200:
time.sleep(5)
c, st = w.ctl("GET", "/api/backup/restore-status")
last = (st.get("data") or {}) if isinstance(st, dict) else {}
if not last.get("running") and time.time() - t0 > 10:
break
rec["load_status"] = json.dumps(last, ensure_ascii=False)[:600]
say(" load: " + rec["load_status"][:300])
w.wait_app(sub, "/", want=("200", "301", "302", "303", "307", "308", "401", "403"), tries=90, delay=5)
rec["item_after_load"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
say(" item after use-my-kept-data: %s" % rec["item_after_load"])
finally:
os.environ.pop("KEPT", None)
if unit:
sw.g(f"[ -d {unit}.r1271-away ] && [ ! -e {unit} ] && mv {unit}.r1271-away {unit}")
rec["controller_lines"] = sw.scrub(sw.g(
f"docker logs --since {t_start} felhom-controller 2>&1 | grep -E '{app}' | grep -iE 'kept|USE MY|asking|future|restor' | cut -c1-300"))
if w.stack(app).get("deployed"):
sw.remove(app, keep=False, say=say)
rec["after_remove"] = sw.leftovers(app, sub)
rec["forged_left"] = sw.g(f"ls -d /mnt/sys_drive/felhom-data/backups/secondary/{app} 2>&1").strip()
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
if __name__ == "__main__":
main(sys.argv[1])
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
"""pullprobe.py — D48 and R-1270 live, on a throwaway app this run installs (never a household's unit).
1. install <app>, seed one item through the front door, „Mentés most";
2. keep a byte copy of the app's unit beside it (backups/d48-test-original/<app>, outside backups/primary);
3. D48: the unit's pin edited to a tag that does not exist (compose, manifest, data stamps — the same ref everywhere,
so the version check passes and the pull is what decides) → „Visszaállítás": refused, the app's containers never
restarted (StartedAt the same before and after), the household's sentence recorded;
4. the original unit back (sha256 of every file equal), a normal restore → success, the item reads back;
5. R-1270: the unit's pin edited to an image that pulls but exits at once (busybox) → „Visszaállítás": the record is
NOT ok, `not_started`, the household's sentence; the undo copy kept; then the original back and a normal restore;
6. remove with data; the test copy removed.
Endpoint-level for every household act; the unit edits are the only hand-made change (`pct exec`, files only).
usage: SC=… SWEEP_EV=… TARGET=9202 DRIVE_ROOT=… python3 pullprobe.py <app> <image-repo> [<busybox-ref>]
"""
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
NS = "/mnt/sys_drive/felhom-data"
MISSING_TAG = "0.0.0-felhom-d48-missing"
def started(app):
return sw.g(f"for c in $(docker ps -a --filter label=com.docker.compose.project={app} -q); do "
"docker inspect -f '{{.Name}} {{.State.StartedAt}} {{.State.Status}}' $c; done").strip()
def sums(path):
return sw.g(f"cd {path} 2>/dev/null && find . -type f | sort | xargs -r sha256sum")
def restore(app, rec, key, say):
sw.restore_unit(app, rec, say)
rec[key] = rec.pop("restore")
say(f" {key}: " + rec[key].get("status", "")[:400])
def main(app, repo, exiting):
d = os.path.join(sw.EV, "_pullprobe", app)
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}
unit = f"{NS}/backups/primary/{app}"
orig = f"{NS}/backups/d48-test-original/{app}"
w.login()
t_start = int(time.time())
try:
rec["install"] = w.deploy(app, sub) and w.wait_app(sub, "/", tries=90, delay=5)
tok = fx.seed(w, sub, say)
rec["seed"] = bool(tok)
sw.backup_now(rec, say)
sw.g(f"rm -rf {orig}; mkdir -p {NS}/backups/d48-test-original && cp -a {unit} {orig}")
s0 = sums(unit)
rec["unit_files"] = len(s0.splitlines())
def edit(to_ref):
# the same ref in the definition, the manifest (pins + data block) and the data stamps — files only
return sw.g(f"cd {unit} && sed -i -E 's#{repo}:[^\"[:space:]]*#{to_ref}#g' compose/docker-compose.yml manifest.json data-stamps.json "
f"&& grep -c '{to_ref}' compose/docker-compose.yml manifest.json data-stamps.json")
def put_original():
sw.g(f"rm -rf {unit} && cp -a {orig} {unit}")
same = sums(unit) == s0
say(f" the original unit is back byte for byte: {same}")
return same
# 3. D48
say(" [D48] the unit's pin → " + repo + ":" + MISSING_TAG + " :: " + edit(f"{repo}:{MISSING_TAG}").replace("\n", " "))
before = started(app)
restore(app, rec, "d48_restore", say)
after = started(app)
rec["d48_started_before"], rec["d48_started_after"] = before, after
rec["d48_app_untouched"] = bool(before) and before == after
say(f" [D48] containers never restarted: {rec['d48_app_untouched']} ({before})")
rec["d48_item_still_there"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
# 4. normal restore
rec["original_back_1"] = put_original()
restore(app, rec, "normal_restore_1", say)
rec["item_after_normal_restore_1"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
say(f" normal restore: item back {rec['item_after_normal_restore_1']}, state {w.stack(app).get('state')}")
# 5. R-1270
if exiting:
sw.backup_now(rec, say) # the unit again after the restore (its data is the app's now)
sw.g(f"rm -rf {orig}; cp -a {unit} {orig}")
s0 = sums(unit)
say(" [R-1270] the unit's pin → " + exiting + " (pulls, exits at once) :: " + edit(exiting).replace("\n", " "))
restore(app, rec, "r1270_restore", say)
rec["r1270_state"] = w.stack(app).get("state")
rec["r1270_undo_copies"] = sw.g(f"ls -1 {NS}/backups/restore-undo/{app} 2>&1").strip()
say(f" [R-1270] state {rec['r1270_state']}, kept undo copy: {rec['r1270_undo_copies']}")
rec["original_back_2"] = put_original()
restore(app, rec, "normal_restore_2", say)
rec["item_after_normal_restore_2"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
say(f" normal restore 2: item back {rec['item_after_normal_restore_2']}, state {w.stack(app).get('state')}")
finally:
rec["controller_lines"] = sw.scrub(sw.g(
f"docker logs --since {t_start} felhom-controller 2>&1 | grep -E '{app}' | grep -iE 'D48|R-1270|refused|downloaded|restor|not start|late' | cut -c1-320"))
sw.remove(app, keep=False, say=say)
rec["after_remove"] = sw.leftovers(app, sub)
rec["test_copy_removed"] = sw.g(f"rm -rf {orig}; rmdir {NS}/backups/d48-test-original 2>/dev/null; ls -d {orig} 2>&1").strip()
rec["restore_undo_left"] = sw.g(f"ls -1 {NS}/backups/restore-undo/{app} 2>&1").strip()
json.dump(rec, open(os.path.join(d, "record.json"), "w"), ensure_ascii=False, indent=1)
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2], sys.argv[3] if len(sys.argv) > 3 else "")
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""rows.py [--apply] — this run's register changes in OPEN-ITEMS.md: R-1269/R-1270/R-1271 to VERIFY (fixed on main,
wait for the release), two new rows (R-1278, R-1279) in severity order with the heading counts, and a cross-reference
on R-1206. Without --apply it prints and changes nothing."""
import os, re, sys
FE = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../.."))
OPEN = os.path.join(FE, "documentation/backlog/OPEN-ITEMS.md")
CLOSED = os.path.join(FE, "documentation/backlog/CLOSED-ITEMS.md")
EV = "`audits/restore-truth-2026-10-25/"
SEV = {"P1": 1, "P2": 2, "P3": 3, "P4": 4}
VERIFY = ("**VERIFY** — fixed on main, waits for the release", "the next controller release")
FIXED = {
"R-1269": (" **2026-10-25 (D47, controller `02daebe` + `1f9c863`):** every install has an identity, the unit records it, and "
"every unit writer sets another install's unit aside whole (`backups/set-aside/<app>/<stamp>`, listed with „Visszaállítás”). "
f"Proven on 9202 ({EV}after/`): the old unit set aside byte for byte, restored with its own password, the account back.",
"release the controller (Monday list); re-run `tools/unitprobe2.py tandoor` on the released image"),
"R-1270": (" **2026-10-25 (controller `b680db8`):** a restore whose app does not reach running is never a success on any path; "
"the household reads that the app has not started yet; the undo copy is kept; a late start turns it into a success. "
f"Proven on 9202 ({EV}after/_pullprobe/`).",
"release the controller (Monday list); D49 asks whether to pour the old data back instead"),
"R-1271": (" **2026-10-25 (controller `bd9f4f7`):** cause — the off-site copy's date was the other box's snapshot time, "
"uncapped, and „newer than every local copy” took it; the „another drive” check compares a mount path (the same on "
"every box). Now a copy more than 10 minutes in the future never counts as the newest; alone it is offered, said "
f"and not recommended. Immich's 404 was the copy's old subdomain. Proven on 9202 ({EV}after/_keptprobe/`).",
"release the controller (Monday list); re-run `tools/keptprobe.py` on the released image"),
}
NEW = [
("R-1278", "Backup & restore", "P3",
"**A volume app's reinstall does not offer its kept backup.** „Remove — keep my data” removes a volume app's named "
"volumes and keeps only its backup; the kept-data question is about drive folders only (`07` §6.5, decision 36), so "
"the reinstall starts empty and says nothing. Since D47 (2026-10-25) the earlier install's unit is set aside and listed "
f"on the restore page („Megőrzött másolatok”, „Visszaállítás”) — but the install page does not point to it ({EV}README.md`).",
"OPEN", "—", "Design: at install, when a set-aside or removed-app unit of the app exists, say so and offer it beside a fresh "
"start; a test", "CC"),
("R-1279", "Backup & restore", "P3",
"**The `.fab` import removes a running app's volumes before its images are pulled — D48 does not cover it.** "
"`felhom-controller/controller/internal/appexport/restore.go` removes the live volumes (`RemoveStackVolumes`, step 1) "
"and pulls at the database start later; a bundle whose version cannot be downloaded then leaves the app gone (the "
"bundle itself stays, so a later import works). Found reading every restore path for D48 (2026-10-25).",
"OPEN", "—", "Pull the bundle's images before step 1 (the D48 rule and its two sentences); a test with an unpullable image", "CC"),
]
R1206_NOTE = (" **2026-10-25:** the kept-data choice no longer takes such a future-dated copy as the newest (R-1271, "
"controller `bd9f4f7`); retention is unchanged — this row.")
def main(apply):
text = open(OPEN).read()
ids = [int(x) for x in re.findall(r"\bR-(\d+)\b", text + open(CLOSED).read())]
for rid, *_ in NEW:
assert int(rid[2:]) > max(i for i in ids if i < int(rid[2:])) and f"**{rid}**" not in text, rid
lines = text.split("\n")
for rid, (note, action) in FIXED.items():
i = next(i for i, l in enumerate(lines) if l.startswith(f"| **{rid}** |"))
cells = lines[i].split(" | ")
assert len(cells) == 8, (rid, len(cells))
if "2026-10-25" not in cells[3]:
cells[3] += note
cells[4], cells[5], cells[6] = VERIFY[0], VERIFY[1], action
lines[i] = " | ".join(cells)
i = next(i for i, l in enumerate(lines) if l.startswith("| **R-1206** |"))
cells = lines[i].split(" | ")
if "R-1271" not in lines[i]:
cells[4] = cells[4] + R1206_NOTE
lines[i] = " | ".join(cells)
for rid, cat, sev, what, state, blocked, action, owner in NEW:
row = f"| **{rid}** | {cat} | {sev} | {what} | {state} | {blocked} | {action} | {owner} |"
h = next(i for i, l in enumerate(lines) if re.match(rf"^## {re.escape(cat)} — \d+ rows", l))
end = next((i for i in range(h + 1, len(lines)) if lines[i].startswith("## ")), len(lines))
rows_at = [i for i in range(h, end) if lines[i].startswith("| **R-")]
pos = next((i for i in rows_at if SEV.get(lines[i].split(" | ")[2].strip(), 9) > SEV[sev]), rows_at[-1] + 1)
lines.insert(pos, row)
m = re.match(r"^(## .+? — )(\d+) rows \((.*)\)$", lines[h])
counts = {p: int(n) for p, n in re.findall(r"(P\d) (\d+)", m.group(3))}
counts[sev] = counts.get(sev, 0) + 1
lines[h] = f"{m.group(1)}{int(m.group(2)) + 1} rows ({', '.join(f'{k} {counts[k]}' for k in sorted(counts))})"
out = "\n".join(lines)
print("rows:", sum(1 for l in out.split("\n") if l.startswith("| **R-")))
if apply:
open(OPEN, "w").write(out)
if __name__ == "__main__":
main("--apply" in sys.argv)
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""unitprobe2.py — R-1269 / D47 AFTER the fix: the sweep's order (catalog-sweep-2026-10-24/tools/unitprobe.py), then
the household's way back: „Visszaállítás" on the set-aside unit of the earlier install (restore page, „Megőrzött
másolatok"). Endpoint-level, the requests the pages send; nothing is planted by hand, no secret is read or printed
(units are compared by sha256 of every file).
usage: SC=… SWEEP_EV=<evidence dir> TARGET=9202 DRIVE_ROOT=… python3 unitprobe2.py <app>
"""
import json, os, re, 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
UNIT = "/mnt/sys_drive/felhom-data/backups/primary/{app}"
ASIDE = "/mnt/sys_drive/felhom-data/backups/set-aside/{app}"
def sums(path):
return sw.g(f"cd {path} 2>/dev/null && find . -type f | sort | xargs -r sha256sum")
def page(path):
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
r = w.sh(["curl", "-sk", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", f"{w.BASE}{path}"])
return r.stdout or ""
def post_form(path, fields):
sess = open(f"{w.SC}/sess{os.getpid()}.txt").read().strip()
csrf = open(f"{w.SC}/csrf{os.getpid()}.txt").read().strip()
args = ["curl", "-sk", "-D", "-", "-o", "/dev/null", "-H", w.HOSTHDR, "-H", f"Cookie: {sess}", "-X", "POST",
"--data-urlencode", f"_csrf={csrf}"]
for k, v in fields.items():
args += ["--data-urlencode", f"{k}={v}"]
r = w.sh(args + [f"{w.BASE}{path}"])
head = (r.stdout or "").splitlines()
return (head[0] if head else "?"), [l for l in head if l.lower().startswith("location")]
def wait_restore(rec_key, rec):
t0, last = time.time(), None
while time.time() - t0 < 1800:
time.sleep(5)
c, d = w.ctl("GET", "/api/backup/restore-status")
dd = (d.get("data") or {}) if isinstance(d, dict) else {}
last = dd
if not dd.get("running") and time.time() - t0 > 10:
break
rec[rec_key] = {"seconds": round(time.time() - t0), "status": json.dumps(last, ensure_ascii=False)[:700]}
def main(app):
d = os.path.join(sw.EV, "_unitprobe2", app)
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)
tok = fx.seed(w, sub, say)
rec["seed"] = bool(tok)
sw.backup_now(rec, say)
s1 = sums(UNIT.format(app=app))
open(os.path.join(d, "unit-1-after-backup.sha256"), "w").write(s1)
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-400")
if aside.strip():
break
rec["set_aside_line"] = aside.strip()
say(" set aside: " + (aside.strip()[:300] or "NONE within 10 min"))
dirs = sw.g(f"ls -1 {ASIDE.format(app=app)} 2>/dev/null").split()
rec["set_aside_dirs"] = dirs
s2 = sums(ASIDE.format(app=app) + "/" + dirs[0]) if dirs else ""
open(os.path.join(d, "unit-2-set-aside.sha256"), "w").write(s2)
rec["set_aside_byte_identical"] = bool(s1.strip()) and s1 == s2
say(f" the set-aside unit is install A's unit byte for byte: {rec['set_aside_byte_identical']} ({len(s1.splitlines())} files)")
open(os.path.join(d, "unit-3-primary-now.sha256"), "w").write(sums(UNIT.format(app=app)))
html = page("/backups/restore")
m = re.search(r'action="/backup/kept/restore".*?name="id" value="([0-9a-f]{16})"', html, re.S)
rec["restore_page_offers"] = bool(m)
sec = html[html.find("Megőrzött másolatok"):][:1500] if "Megőrzött másolatok" in html else ""
open(os.path.join(d, "restore-page-kept-section.html"), "w").write(sw.scrub(sec))
if not m:
say(" the restore page offers NO restore of the set-aside unit")
return
head, loc = post_form("/backup/kept/restore", {"id": m.group(1), "confirm": "1"})
say(f" [6] POST /backup/kept/restore -> {head} {loc[:1]}")
wait_restore("restore", rec)
say(" restore status: " + rec["restore"]["status"][:300])
time.sleep(20)
rec["state_after_restore"] = w.stack(app).get("state")
rec["item_after_restore"] = bool(tok) and bool(fx.verify(w, sub, tok, say))
rec["db_auth_errors_after_restore"] = sw.g(
f"for c in $(docker ps -a --filter label=com.docker.compose.project={app} --format '{{{{.Names}}}}'); do "
f"docker logs --since 5m $c 2>&1 | grep -ciE 'password authentication failed|access denied for user' | sed \"s/^/$c: /\"; done").strip()
say(" state after restore: %s, item: %s, db auth errors: %s" % (rec["state_after_restore"], rec["item_after_restore"],
rec["db_auth_errors_after_restore"]))
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|restor|captured|install id|D47|D48|R-1270|refused' | 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 {ASIDE.format(app=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(sys.argv[1])