The N100 becomes the lived-in box (09 §3 decision 254): media apps installed and wired through the dashboard; films proven never off-site; the USB split NOT done (it is the whole-guest backup target)
gates / gates (push) Successful in 6m59s
gates / gates (push) Successful in 6m59s
- 09 §3 decision 254 (operator decisions 240/243 written down); target-selection: a "lived-in" tier, Tier 0 = demo-hp alone; nodes.md role + drive; 11-os-updates ring 0 wording; CLAUDE.md + docs.md: the diary. - documentation/lived-in/n100.md (new diary); audits/n100-lived-in-2026-10-15/ (state, drive read, Part C capture sets, installs, wiring, stranger probes, demo-hp clean-up, the operator's SHEET.md). - Register: R-1062 (the split, operator decides), R-1063 (decommission half-state on an agent refusal), R-1064 (path removal silent about cross-drive copies), R-1065 (a claimed Plex gets no libraries until a wiring run). - demo-hp: /mnt/sizing-bench removed through the dashboard; the hub shows demo-hp OK (14:56 UTC). Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
1 parent
3263bb26bc
commit
06e7cf8c3f
30 files changed
+614
-12
No files matched your search
@@ -0,0 +1,46 @@
|
||||
== host
|
||||
demo-felhom
|
||||
felhom-agent 0.156.1
|
||||
total used free shared buff/cache available
|
||||
Mem: 15772 2408 8108 66 5664 13363
|
||||
NAME SIZE TYPE FSTYPE MOUNTPOINT MODEL SERIAL
|
||||
sda 476.9G disk AirDisk 512GB SSD QDF922W009654S30EX
|
||||
|-sda1 1007K part
|
||||
|-sda2 1G part vfat /boot/efi
|
||||
`-sda3 475.9G part LVM2_member
|
||||
|-pve-swap 8G lvm swap [SWAP]
|
||||
|-pve-root 96G lvm ext4 /
|
||||
|-pve-data_tmeta 3.6G lvm
|
||||
| `-pve-data-tpool 348.8G lvm
|
||||
| |-pve-data 348.8G lvm
|
||||
| |-pve-vm--9201--disk--2 32G lvm ext4
|
||||
| `-pve-vm--9201--disk--3 250G lvm ext4
|
||||
`-pve-data_tdata 348.8G lvm
|
||||
`-pve-data-tpool 348.8G lvm
|
||||
|-pve-data 348.8G lvm
|
||||
|-pve-vm--9201--disk--2 32G lvm ext4
|
||||
`-pve-vm--9201--disk--3 250G lvm ext4
|
||||
sdb 931.5G disk ext4 /mnt/hdd_1 TOSHIBA MQ04ABF100 65NOP3HDT
|
||||
VMID Status Lock Name
|
||||
9201 running demo-felhom
|
||||
== guest
|
||||
cores: 3
|
||||
memory: 12288
|
||||
mp0: local-lvm:vm-9201-disk-3,mp=/var/lib/felhom,backup=1,size=250G
|
||||
mp8: /mnt/felhom-drives,mp=/mnt/felhom-drives
|
||||
mp9: /var/lib/felhom-agent/guests/9201/bootstrap,mp=/etc/felhom-bootstrap,ro=1
|
||||
rootfs: local-lvm:vm-9201-disk-2,size=32G
|
||||
swap: 512
|
||||
gitea.dooplex.hu/admin/felhom-controller:0.314.0
|
||||
192.168.0.149 169.254.253.2 172.16.253.1 172.17.0.1 172.18.0.1
|
||||
total used free shared buff/cache available
|
||||
Mem: 12288 222 10945 8 1128 12065
|
||||
Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/mapper/pve-vm--9201--disk--2 32G 1.2G 29G 4% /
|
||||
/dev/sdb 916G 6.2G 864G 1% /mnt/felhom-drives/hdd_1
|
||||
ls: cannot access '/dev/dri': No such file or directory
|
||||
cloudflared Up 41 hours (healthy)
|
||||
felhom-controller Up 2 hours (healthy)
|
||||
filebrowser Up 21 hours (healthy)
|
||||
opengist Up 12 hours (healthy)
|
||||
traefik Up 12 hours
|
||||
@@ -0,0 +1,26 @@
|
||||
NAME TRAN VENDOR MODEL SERIAL SIZE
|
||||
sdb usb ADATA TOSHIBA MQ04ABF100 65NOP3HDT 931.5G
|
||||
ID_BUS=ata
|
||||
ID_MODEL=TOSHIBA_MQ04ABF100
|
||||
ID_SERIAL=TOSHIBA_MQ04ABF100_65NOP3HDT
|
||||
ID_USB_MODEL=HD710_PRO
|
||||
ID_USB_VENDOR=ADATA
|
||||
by-path
|
||||
card0
|
||||
renderD128
|
||||
== top
|
||||
total 32
|
||||
drwxr-xr-x 5 root root 4096 Jul 28 21:25 .
|
||||
drwxr-xr-x 5 root root 4096 Aug 3 09:15 ..
|
||||
drwxr-xr-x 2 root root 4096 Oct 15 04:59 dump
|
||||
drwxr-xr-x 6 100000 100000 4096 Jul 18 22:11 felhom-data
|
||||
drwx------ 2 root root 16384 Jul 18 18:41 lost+found
|
||||
== du
|
||||
2.7G /mnt/hdd_1/dump
|
||||
3.5G /mnt/hdd_1/felhom-data
|
||||
16K /mnt/hdd_1/lost+found
|
||||
== felhom-data
|
||||
32K /mnt/hdd_1/felhom-data/shares
|
||||
528K /mnt/hdd_1/felhom-data/userdata
|
||||
422M /mnt/hdd_1/felhom-data/appdata
|
||||
3.1G /mnt/hdd_1/felhom-data/backups
|
||||
@@ -0,0 +1,47 @@
|
||||
Name Type Status Total (KiB) Used (KiB) Available (KiB) %
|
||||
felhom-backup dir active 960303848 6435888 905013448 0.67%
|
||||
felhom-pbs pbs active 0 0 0 0.00%
|
||||
local dir active 98497780 32496832 60951400 32.99%
|
||||
local-lvm lvmthin active 365760512 9290317 356470194 2.54%
|
||||
dir: felhom-backup
|
||||
|
||||
== dump
|
||||
-rw-r--r-- 1 root root 950588793 Oct 13 04:53 vzdump-lxc-9201-2026_10_13-04_52_51.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 13 04:53 vzdump-lxc-9201-2026_10_13-04_52_51.tar.zst.notes
|
||||
-rw-r--r-- 1 root root 1505 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.log
|
||||
-rw-r--r-- 1 root root 951109351 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 14 04:54 vzdump-lxc-9201-2026_10_14-04_54_24.tar.zst.notes
|
||||
-rw-r--r-- 1 root root 1504 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.log
|
||||
-rw-r--r-- 1 root root 951089306 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.tar.zst
|
||||
-rw-r--r-- 1 root root 16 Oct 15 04:59 vzdump-lxc-9201-2026_10_15-04_59_17.tar.zst.notes
|
||||
== backups
|
||||
4.0K /mnt/hdd_1/felhom-data/backups/offsite-proof
|
||||
1.6G /mnt/hdd_1/felhom-data/backups/offsite-restore
|
||||
1.3G /mnt/hdd_1/felhom-data/backups/primary
|
||||
274M /mnt/hdd_1/felhom-data/backups/secondary
|
||||
== appdata
|
||||
12K /mnt/hdd_1/felhom-data/appdata/romm
|
||||
24K /mnt/hdd_1/felhom-data/appdata/paperless
|
||||
63M /mnt/hdd_1/felhom-data/appdata/nextcloud
|
||||
360M /mnt/hdd_1/felhom-data/appdata/immich
|
||||
== userdata
|
||||
/mnt/hdd_1/felhom-data/userdata
|
||||
/mnt/hdd_1/felhom-data/userdata/media
|
||||
/mnt/hdd_1/felhom-data/userdata/media/nzbget
|
||||
/mnt/hdd_1/felhom-data/userdata/media/usenet
|
||||
/mnt/hdd_1/felhom-data/userdata/media/movies
|
||||
/mnt/hdd_1/felhom-data/userdata/media/music
|
||||
/mnt/hdd_1/felhom-data/userdata/media/comics
|
||||
/mnt/hdd_1/felhom-data/userdata/media/podcasts
|
||||
/mnt/hdd_1/felhom-data/userdata/media/audiobooks
|
||||
/mnt/hdd_1/felhom-data/userdata/media/transmission
|
||||
/mnt/hdd_1/felhom-data/userdata/media/transmission/watch
|
||||
/mnt/hdd_1/felhom-data/userdata/media/grimmory
|
||||
/mnt/hdd_1/felhom-data/userdata/media/torrents
|
||||
/mnt/hdd_1/felhom-data/userdata/media/tv
|
||||
/mnt/hdd_1/felhom-data/userdata/media/photos
|
||||
/mnt/hdd_1/felhom-data/userdata/media/metube
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db-shm
|
||||
/mnt/hdd_1/felhom-data/userdata/media/books/metadata.db-wal
|
||||
@@ -0,0 +1,7 @@
|
||||
standing now: typical 27 MB, peak 68 MB; rule (platform 470 + peak) x 1.5 = 807 MB vs guest 12288 MB -> fits
|
||||
standing + the five: typical 636 MB, peak 841 MB; rule (platform 470 + peak) x 1.5 = 1966 MB vs guest 12288 MB -> fits
|
||||
plex: typical 232 MB, peak 234 MB (measured)
|
||||
qbittorrent: typical 163 MB, peak 318 MB (onboarding)
|
||||
prowlarr: typical 41 MB, peak 44 MB (onboarding)
|
||||
sonarr: typical 77 MB, peak 77 MB (onboarding)
|
||||
radarr: typical 96 MB, peak 100 MB (measured)
|
||||
@@ -0,0 +1,16 @@
|
||||
/api/storage/paths -> 404 {"_raw": "404 page not found\n"}
|
||||
/api/disks -> 200 {"data": {"vmid": 9201, "disks": [{"name": "felhom-backup", "type": "local-dir", "state": "attached", "backing_device": "/dev/sdb", "mount_path": "/mnt/hdd_1", "class": "slow", "role": "user-data", "data_bearing": true, "data_reason": "device is mounted", "total_bytes": 983351140352, "used_bytes": 6590349312, "used_fraction": 0.00670192878369056, "durable_id": "uuid:47a3361a-91e0-4831-a69d-27f540ed3f48", "wipe_durable_id": "byid:wwn-0x5000039ddb108568", "guest_attached": false, "backup_target": true, "guest_path": "/mnt/felhom-drives/hdd_1", "bound_under_parent": true, "smart": {"health": "PASSED", "model_name": "TOSHIBA MQ04ABF100", "temperature_c": 35, "power_on_hours": 5449, "reallocated_sectors": 0, "pending_sectors": 0, "offline_uncorrectable": 0, "udma_crc_errors": 0, "critical_warning": null, "media_errors": null, "percentage_used": null}}, {"name": "local", "type": "local", "stat
|
||||
/api/backup/status -> 200 {"ok": true, "data": {"enabled": true, "running": false}}
|
||||
/api/offbox/status -> 404 {"ok": false, "error": "endpoint not found"}
|
||||
/api/backup/offsite/status -> 404 {"ok": false, "error": "endpoint not found"}
|
||||
/api/selfupdate/status -> 200 {"ok": true, "data": {"running": false, "last_check": {"current_version": "0.314.0", "latest_version": "0.314.0", "update_available": false, "checked_at": "2026-10-15T12:56:24Z"}, "last_state": {"status": "success", "previous_version": "0.313.0", "previous_image": "gitea.dooplex.hu/admin/felhom-controller:0.313.0", "target_version": "0.314.0", "target_image": "gitea.dooplex.hu/admin/felhom-controller:0.314.0", "initiated_at": "2026-10-15T12:55:48Z", "initiated_by": "auto-floor", "completed_at": "2026-10-15T12:55:54Z"}}}
|
||||
/api/storage/backup-target -> 200 {"data": {"degraded": false, "known": true, "label": "Külső tárhely (hdd_1)", "target": "felhom-backup"}, "ok": true}
|
||||
/api/storage/media/status -> 200 {"data": {"pending": false, "drives": null, "apps": null}, "ok": true}
|
||||
/api/storage/ -> 404 {"_raw": "404 page not found\n"}
|
||||
|
||||
|
||||
{'path': '/mnt/felhom-drives/hdd_1', 'label': 'Külső tárhely (hdd_1)', 'schedulable': True}
|
||||
keys: ['password_hash', 'filebrowser_admin_state', 'filebrowser_admin_decided_at', 'claimed', 'claim_code_hash', 'claim_code_generation', 'claim_code_issued_at', 'claim_consumed_generation', 'offbox_enlarge_notice_seeded', 'app_update_events_seeded', 'unhealthy_stop_event_seeded', 'hub_escrow_identity_present', 'hub_escrow_superseded_present', 'hub_escrow_superseded_at', 'hub_escrow_key_sha256', 'hub_escrow_key_checked_at', 'app_backup', 'offsite_data_at', 'backup_window_start', 'storage_paths', 'last_guest_boot_id', 'hub_verified', 'hub_verified_at', 'hub_last_check', 'applied_config_version', 'offbox']
|
||||
offbox: {"enabled": true, "host": "u629488-sub1.your-storagebox.de", "port": 23, "user": "u629488-sub1", "repo_path": "/home/felhom-repo", "schedule": "daily", "quota_gb": 50, "transport": "rclone-pinned", "last_run": "2026-10-15T02:15:10Z", "last_status": "ok", "last_success": "2026-10-15T02:15:10Z", "last_integrity_check": "2026-10-11T04:00:00Z", "last_integrity_ok": true, "last_integrity_depth": "100%", "proved_snapshots": {"opengist": "0ef3edb5"}, "last_proof_run": "2026-10-15T03:30:00Z", "last_proof_stack": "opengist", "last_proof_snapshot": "0ef3edb5", "last_proof_result": "pass", "last_duration": "7s", "repo_size_human": "181.6 KB", "repo_size_bytes": 185936, "snapshot_count": 15, "stats_know
|
||||
app_backup: {"opengist": {"enabled": false, "cross_drive": {"enabled": true, "method": "rsync", "destination_path": "/mnt/felhom-drives/hdd_1", "schedule": "daily", "last_run": "2026-10-15T01:30:00Z", "last_status": "ok", "last_success": "2026-10-15T01:30:00Z", "success_tracked": true, "unit_package_date": "2026-10-15T00:30:00Z", "last_duration": "0s", "last_size_human": "202.8 KB"}, "offbox": true}}
|
||||
offsite_data_at: {'opengist': {'pushed_at': '2026-10-15T02:15:05Z', 'data_at': '2026-10-15T02:15:00Z'}}
|
||||
@@ -0,0 +1,10 @@
|
||||
qbittorrent 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None), ('QBT_ADMIN_PASSWORD', 'password', True, None)]
|
||||
deployed: False
|
||||
prowlarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None)]
|
||||
deployed: False
|
||||
sonarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
radarr 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
plex 200 [('DOMAIN', 'domain', True, None), ('SUBDOMAIN', 'subdomain', True, None), ('PLEX_CLAIM', 'text', True, True), ('HDD_PATH', 'path', True, None)]
|
||||
deployed: False
|
||||
@@ -0,0 +1,18 @@
|
||||
16:36:53 qbittorrent: deploy (fields sent: ['DOMAIN', 'QBT_ADMIN_PASSWORD', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
qbittorrent: state=running after 13s; pinned={'qbittorrent': 'qbittorrentofficial/qbittorrent-nox:5.2.4-1'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
16:37:06 prowlarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
prowlarr: state=running after 28s; pinned={'prowlarr': 'lscr.io/linuxserver/prowlarr:version-2.6.5.5623'};
|
||||
16:37:34 sonarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
sonarr: state=running after 33s; pinned={'sonarr': 'lscr.io/linuxserver/sonarr:4.0.20'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
16:38:07 radarr: deploy (fields sent: ['DOMAIN', 'SUBDOMAIN']) -> 202 {"ok": true, "message": "Telepítés elindítva – az állapot a kártyán követhető"}
|
||||
radarr: state=running after 28s; pinned={'radarr': 'lscr.io/linuxserver/radarr:6.4.4'}; HDD_PATH: /mnt/felhom-drives/hdd_1
|
||||
cloudflared Up 41 hours (healthy)
|
||||
felhom-controller Up 2 hours (healthy)
|
||||
filebrowser Up 21 hours (healthy)
|
||||
opengist Up 12 hours (healthy)
|
||||
prowlarr Up About a minute (healthy)
|
||||
qbittorrent Up About a minute (healthy)
|
||||
radarr Up 15 seconds (healthy)
|
||||
sonarr Up 56 seconds (healthy)
|
||||
traefik Up 12 hours
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
14:38:45 qbittorrent / -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v3/system/status -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v1/system/status -> HTTP/2 404
|
||||
14:38:46 qbittorrent /initialize.json -> HTTP/2 404
|
||||
14:38:46 qbittorrent /api/v2/app/version -> HTTP/2 404
|
||||
14:38:46 prowlarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2F
|
||||
14:38:47 prowlarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:47 prowlarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:47 prowlarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:47 prowlarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fprowlarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
14:38:48 sonarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2F
|
||||
14:38:48 sonarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:48 sonarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:48 sonarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:49 sonarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fsonarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
14:38:49 radarr / -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2F
|
||||
14:38:49 radarr /api/v3/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv3%2Fsystem%2Fstatus
|
||||
14:38:49 radarr /api/v1/system/status -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv1%2Fsystem%2Fstatus
|
||||
14:38:50 radarr /initialize.json -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Finitialize.json
|
||||
14:38:50 radarr /api/v2/app/version -> HTTP/2 302 location: https://felhom.demo-felhom.eu/__gate/start?rd=https%3A%2F%2Fradarr.demo-felhom.eu%2Fapi%2Fv2%2Fapp%2Fversion
|
||||
(the qbittorrent lines above used the wrong name; its address is torrent.demo-felhom.eu)
|
||||
14:39:24 torrent / -> HTTP/2 200 body: <!DOCTYPE html><html lang="C"><head> <meta charset="UTF-8"> <meta nam
|
||||
14:39:25 torrent /api/v2/app/version -> HTTP/2 403 body: Forbidden
|
||||
@@ -0,0 +1,27 @@
|
||||
== the controller's wiring runs:
|
||||
2026/10/15 14:36:47 [INFO] [stacks] media_library qbittorrent: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:37:28 [INFO] [stacks] media_library sonarr: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:38:01 [INFO] [stacks] media_library radarr: per-drive binds 0 []; drives not bound: []
|
||||
2026/10/15 14:39:15 [INFO] [media] wiring the drives into the media apps (a media app came up: radarr)
|
||||
2026/10/15 14:39:18 [INFO] [mediawire] 1 drive(s) wired in 3.504s: folders=done(0) qbittorrent=done(3) sonarr=done(4) radarr=done(4) prowlarr=done(2)
|
||||
|
||||
== per-drive binds (docker's own view):
|
||||
qbittorrent: /var/lib/docker/volumes/qbittorrent_qbittorrent_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media/torrents -> /downloads; /mnt/felhom-drives/hdd_1/userdata/media/torrents -> /mnt/felhom-drives/hdd_1/userdata/media/torrents;
|
||||
sonarr: /var/lib/docker/volumes/sonarr_sonarr_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media -> /mnt/felhom-drives/hdd_1/userdata/media;
|
||||
radarr: /var/lib/docker/volumes/radarr_radarr_config/_data -> /config; /mnt/felhom-drives/hdd_1/userdata/media -> /mnt/felhom-drives/hdd_1/userdata/media;
|
||||
prowlarr: /var/lib/docker/volumes/prowlarr_prowlarr_config/_data -> /config;
|
||||
== sonarr: root folders ['/mnt/felhom-drives/hdd_1/userdata/media/tv']
|
||||
tags ['hdd-1']
|
||||
download clients [('qBittorrent hdd-1', 'QBittorrent', ['qbittorrent', 'tv-hdd-1'], [1])]
|
||||
== radarr: root folders ['/mnt/felhom-drives/hdd_1/userdata/media/movies']
|
||||
tags ['hdd-1']
|
||||
download clients [('qBittorrent hdd-1', 'QBittorrent', ['qbittorrent', 'movies-hdd-1'], [1])]
|
||||
== prowlarr: apps [('Radarr', 'fullSync', 'http://radarr:7878'), ('Sonarr', 'fullSync', 'http://sonarr:8989')]
|
||||
== qbittorrent categories: Forbidden
|
||||
== qbittorrent (its own API, after its login):
|
||||
{"movies-hdd-1":{"download_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp","inactive_seeding_time_limit":-2,"name":"movies-hdd-1","ratio_limit":-2,"savePath":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/movies","seeding_time_limit":-2,"share_limit_action":"Default"},"tv-hdd-1":{"download_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp","inactive_seeding_time_limit":-2,"name":"tv-hdd-1","ratio_limit":-2,"savePath":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/tv","seeding_time_limit":-2,"share_limit_action":"Default"}}
|
||||
"auto_tmm_enabled":true
|
||||
"save_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents"
|
||||
"save_path_changed_tmm_enabled":false
|
||||
"temp_path":"/mnt/felhom-drives/hdd_1/userdata/media/torrents/.temp"
|
||||
"temp_path_enabled":true
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"opengist": {
|
||||
"enabled": false,
|
||||
"cross_drive": {
|
||||
"enabled": true,
|
||||
"method": "rsync",
|
||||
"destination_path": "/mnt/felhom-drives/hdd_1",
|
||||
"schedule": "daily",
|
||||
"last_run": "2026-10-15T01:30:00Z",
|
||||
"last_status": "ok",
|
||||
"last_success": "2026-10-15T01:30:00Z",
|
||||
"success_tracked": true,
|
||||
"unit_package_date": "2026-10-15T00:30:00Z",
|
||||
"last_duration": "0s",
|
||||
"last_size_human": "202.8 KB"
|
||||
},
|
||||
"offbox": true
|
||||
},
|
||||
"prowlarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"qbittorrent": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"radarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
},
|
||||
"sonarr": {
|
||||
"enabled": false,
|
||||
"offbox": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
== qbittorrent: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media/torrents class=optional origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes [/mnt/felhom-drives/hdd_1/felhom-data/userdata/media/torrents (optional)]
|
||||
== sonarr: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media class=excluded origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
== radarr: 1 classifiable bind(s), classified=true
|
||||
bind userdata:media class=excluded origin=explicit
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
== prowlarr: 0 classifiable bind(s), classified=true
|
||||
tier offsite takes []
|
||||
tier secondary takes []
|
||||
--- PASS: TestN100CaptureSetTmp (0.00s)
|
||||
2026-10-15 04:59:17 INFO: including mount point mp0 ('/var/lib/felhom') in backup
|
||||
2026-10-15 04:59:17 INFO: excluding bind mount point mp8 ('/mnt/felhom-drives') from backup (not a volume)
|
||||
2026-10-15 04:59:17 INFO: excluding bind mount point mp9 ('/etc/felhom-bootstrap') from backup (not a volume)
|
||||
mp0: local-lvm:vm-9201-disk-3,mp=/var/lib/felhom,backup=1,size=250G
|
||||
mp8: /mnt/felhom-drives,mp=/mnt/felhom-drives
|
||||
mp9: /var/lib/felhom-agent/guests/9201/bootstrap,mp=/etc/felhom-bootstrap,ro=1
|
||||
Tier 2 with ONE data drive (backup/tier2.go selectTier2TargetFrom): no other drive -> the internal SSD, STATE-ONLY set (never the optional media/torrents), and only if the SSD has headroom; so no film or download reaches tier 2 on the N100 today.
|
||||
@@ -0,0 +1,9 @@
|
||||
{'path': '/mnt/felhom-drives/hdd_1', 'label': 'NVME 1TB', 'is_default': True, 'schedulable': True}
|
||||
{'path': '/mnt/sizing-bench', 'label': 'Tárhely (sizing-bench)', 'schedulable': True}
|
||||
total 16
|
||||
drwxr-xr-x 4 root root 4096 Oct 15 01:30 .
|
||||
drwxr-xr-x 5 root root 4096 Oct 14 20:43 ..
|
||||
drwxr-xr-x 3 root root 4096 Oct 15 01:30 backups
|
||||
drwxrwsr-x 6 root 1000 4096 Oct 14 20:43 userdata
|
||||
2026/10/15 14:41:46 info.go:13: [DEBUG] [system] GetDiskUsage: path="/mnt/sizing-bench" total=31.2 GB used=1.3 GB avail=28.3GB (4.3%)
|
||||
2026/10/15 14:42:21 info.go:13: [DEBUG] [system] GetDiskUsage: path="/mnt/sizing-bench" total=31.2 GB used=1.3 GB avail=28.3GB (4.3%)
|
||||
@@ -0,0 +1,9 @@
|
||||
16:44:24 POST /settings/storage/remove storage_path=/mnt/sizing-bench -> HTTP/2 302 | location: /storage?storage_msg=success&storage_detail=Adatt%C3%A1rol%C3%B3+elt%C3%A1vol%C3%ADtva%3A+%2Fmnt%2Fsizing-bench
|
||||
2
|
||||
2026/10/15 14:44:24 settings.go:1632: [INFO] [settings] Removed storage path: /mnt/sizing-bench
|
||||
2026/10/15 14:44:24 handlers.go:3527: [INFO] [web] Storage path removed: /mnt/sizing-bench
|
||||
2026/10/15 14:44:25 handlers.go:3805: [INFO] [web] FileBrowser mounts synced (recreated) — 1 storage path(s), config updated
|
||||
|
||||
/app_backup/calibre-web/cross_drive/destination_path = /mnt/sizing-bench
|
||||
/app_backup/paperless-ngx/cross_drive/destination_path = /mnt/sizing-bench
|
||||
storage paths now: ['/mnt/felhom-drives/hdd_1']
|
||||
@@ -0,0 +1,3 @@
|
||||
14:56:26 atus-dot-nominal"> Demo HP OK 1 1 just now 28% 26% 27%/22% 17/17 –
|
||||
|
||||
[exited with code 0]
|
||||
@@ -0,0 +1,19 @@
|
||||
# The N100 becomes the lived-in box (2026-10-15)
|
||||
|
||||
Rule: `architecture/09-update-architecture.md` §3 decision 254. Diary: `documentation/lived-in/n100.md`.
|
||||
Read first: `runbooks/target-selection.md`, `operations/nodes.md`, `07-backup-architecture.md`, `15-media-library.md`.
|
||||
|
||||
| folder | what |
|
||||
|---|---|
|
||||
| `B/01-state.txt` | the host and guest: versions, memory, disks, `/dev/dri` (host yes, guest no) |
|
||||
| `B/02-drive.txt`, `B/03-drive-detail.txt` | the USB drive (ADATA HD710 PRO / TOSHIBA MQ04ABF100 `65NOP3HDT`) and its 6.2 GB: vzdumps, app backups, leftovers — no family files; PVE storage `felhom-backup` = the whole-guest backup target |
|
||||
| `B/04-sizing.txt` | the five media apps by the estimator's rule: ~2 GB needed of 12 GB |
|
||||
| `B/05-dashboard-view.txt` | the dashboard's own view: one enrolled drive, `backup_target: true`, off-site on (182 KB) |
|
||||
| `B/06-deploy-fields.txt` | the install fields per app |
|
||||
| `D/01-install.txt` | qBittorrent, Prowlarr, Sonarr, Radarr through the deploy call — no drive sent; the box chose `hdd_1` |
|
||||
| `D/02-stranger.txt` | a stranger from the internet: the gate on Prowlarr/Sonarr/Radarr; qBittorrent's own login page and 403 API |
|
||||
| `D/03-wiring.txt` | what the box wired, from the apps' own APIs |
|
||||
| `D/04-app-backup-settings.txt`, `D/05-capture-sets.txt` | **Part C:** the controller's classifier over the deployed files — off-site takes no media; tier 2 only qBittorrent's downloads and only if switched on (not on; with one drive state-only to the SSD); vzdump excludes the drives |
|
||||
| `F/` | demo-hp: `/mnt/sizing-bench` removed through the dashboard; the hub's next report |
|
||||
| `SHEET.md` | the operator's sheet |
|
||||
| `tools/` | `n100.py` (the box-walk library pointed at the N100), `install_media.py`, `read_wiring.py` |
|
||||
@@ -0,0 +1,50 @@
|
||||
# Your sheet — the N100 becomes the lived-in box (about 30 minutes)
|
||||
|
||||
Do these when it suits you. Use one browser. Sign in to the dashboard first: then the apps let you through.
|
||||
|
||||
## 1. The addresses
|
||||
|
||||
- Dashboard: **https://felhom.demo-felhom.eu**
|
||||
- qBittorrent: **https://torrent.demo-felhom.eu**
|
||||
- Prowlarr: **https://prowlarr.demo-felhom.eu**
|
||||
- Sonarr: **https://sonarr.demo-felhom.eu**
|
||||
- Radarr: **https://radarr.demo-felhom.eu**
|
||||
- Plex (after you install it): **https://plex.demo-felhom.eu**
|
||||
|
||||
## 2. Plex
|
||||
|
||||
1. Dashboard → Alkalmazások → Plex → install. It asks no code.
|
||||
2. Wait until Plex runs. Open Plex's page in the dashboard.
|
||||
3. Open **plex.tv/claim**. Copy the code. Paste it on Plex's page within 4 minutes.
|
||||
4. The box opens Plex by itself when Plex is claimed. If it asks, press „Kész, beállítottam".
|
||||
5. Wait 2 minutes. Open Plex. **If Plex shows no library,** press „Bekötés most" on the dashboard (the card about the
|
||||
drives and the apps), and tell me that you had to. (I expect this; it is R-1065.)
|
||||
|
||||
## 3. Prowlarr, Sonarr, Radarr
|
||||
|
||||
1. Open each address. The app asks you to make its admin login. Make one for each.
|
||||
2. On each app's page in the dashboard, press „Kész, beállítottam". Until you do, only you can reach the app.
|
||||
3. Add your download sources **in Prowlarr only.** They reach Sonarr and Radarr by themselves (the box linked them).
|
||||
|
||||
## 4. One show, one film
|
||||
|
||||
1. Sonarr: add one show. Radarr: add one film.
|
||||
2. When they finish, open Plex. Check that both are there.
|
||||
|
||||
## 5. Passwords
|
||||
|
||||
- qBittorrent: user `admin`. The password is on qBittorrent's page in the dashboard (the password row, show button).
|
||||
The same value is in a private file on DooPlex: `~/.felhom-demofelhom/qbittorrent-admin`.
|
||||
- Prowlarr, Sonarr, Radarr, Plex: the logins you make. None is written here.
|
||||
|
||||
## 6. qBittorrent — the legal line
|
||||
|
||||
„Csak olyan tartalmat tölts le, amihez jogod van. A letöltés a háztartásod internetcíméről történik, és a torrent
|
||||
természetéből adódóan a többi résztvevő látja a címedet."
|
||||
|
||||
## 7. Anything odd
|
||||
|
||||
Tell any CC session. It goes into the diary (`documentation/lived-in/n100.md`) and the register.
|
||||
|
||||
When you are done, say „done". I then read back: Plex claimed, its libraries, the show and the film imported as
|
||||
hardlinks, and visible in Plex.
|
||||
@@ -0,0 +1,26 @@
|
||||
"""install_media.py — Part D1: qBittorrent, Prowlarr, Sonarr, Radarr through the dashboard's deploy call, with the fields
|
||||
the wizard sends (no HDD_PATH for a media app — the box picks its drive). Admins and indexers are the operator's."""
|
||||
import json, os, time, n100
|
||||
w = n100.w
|
||||
w.login()
|
||||
for app in ("qbittorrent", "prowlarr", "sonarr", "radarr"):
|
||||
if w.stack(app).get("deployed"):
|
||||
print(f"{app}: already installed — skipped"); continue
|
||||
c, d = w.ctl("GET", f"/api/stacks/{app}/deploy-fields")
|
||||
fields = (((d.get("data") or {}).get("metadata") or {}).get("deploy_fields")) or []
|
||||
sub = next((f.get("default") for f in fields if f.get("env_var") == "SUBDOMAIN"), None) or app
|
||||
values = {"DOMAIN": w.DOMAIN, "SUBDOMAIN": sub}
|
||||
if any(f.get("env_var") == "QBT_ADMIN_PASSWORD" for f in fields):
|
||||
values["QBT_ADMIN_PASSWORD"] = open(os.path.expanduser("~/.felhom-demofelhom/qbittorrent-admin")).read().strip()
|
||||
t0 = time.time()
|
||||
code, d = w.ctl("POST", f"/api/stacks/{app}/deploy", {"values": values})
|
||||
print(f"{time.strftime('%H:%M:%S')} {app}: deploy (fields sent: {sorted(values)}) -> {code} {json.dumps(d, ensure_ascii=False)[:120]}")
|
||||
for _ in range(120):
|
||||
time.sleep(5)
|
||||
st = w.stack(app)
|
||||
if st.get("deployed") and (st.get("app_config") or {}).get("pinned_images") and st.get("state") in ("running", "unhealthy"):
|
||||
break
|
||||
st = w.stack(app)
|
||||
hdd = w.guest(f"grep -E '^\\s*HDD_PATH:' /opt/docker/stacks/{app}/app.yaml | head -1").strip()
|
||||
print(f" {app}: state={st.get('state')} after {time.time()-t0:.0f}s; pinned={(st.get('app_config') or {}).get('pinned_images')}; {hdd}")
|
||||
print(w.guest("docker ps --format '{{.Names}} {{.Status}}' | sort"))
|
||||
@@ -0,0 +1,12 @@
|
||||
"""n100.py — the box-walk library pointed at the N100 (demo-felhom guest 9201). Import this, not box_walk, for the N100.
|
||||
box_walk.py has no demo-felhom row; this overrides the target AFTER import (no catalog change). Every call is the
|
||||
dashboard's own endpoint, as box_walk documents."""
|
||||
import os, sys
|
||||
os.environ.setdefault("TARGET", "9201")
|
||||
os.environ.setdefault("SC", os.path.expanduser("~/.felhom-demofelhom"))
|
||||
sys.path.insert(0, "/mnt/5_hdd/felhom.eu/git/app-catalog-felhom.eu/scripts")
|
||||
import box_walk as w # noqa: E402
|
||||
w._T = {"hp": "demo-felhom", "ssh": "felhom-pve", "jump": None, "guest": "9201",
|
||||
"base": "https://192.168.0.149", "domain": "demo-felhom.eu"}
|
||||
w.GUEST, w.BASE, w.DOMAIN, w.HP = "9201", "https://192.168.0.149", "demo-felhom.eu", "demo-felhom"
|
||||
w.HOSTHDR = "Host: felhom.demo-felhom.eu"
|
||||
@@ -0,0 +1,23 @@
|
||||
"""read_wiring.py — Part D2: what the box wired by itself, read from each app's OWN API inside its container (keys read
|
||||
from the app's config at use, never printed) and from the controller's log. Read only."""
|
||||
import json, shlex, n100
|
||||
w = n100.w
|
||||
def arr(app, port, path, ver="v3"):
|
||||
script = ("K=$(sed -n 's:.*<ApiKey>\\(.*\\)</ApiKey>.*:\\1:p' /config/config.xml); "
|
||||
f"curl -s -H \"X-Api-Key: $K\" http://127.0.0.1:{port}/api/{ver}{path}")
|
||||
out = w.guest(f"docker exec {app} sh -c {shlex.quote(script)}")
|
||||
try: return json.loads(out)
|
||||
except Exception: return out[:200]
|
||||
print("== the controller's wiring runs:")
|
||||
print(w.guest("docker logs --since 10m felhom-controller 2>&1 | grep -E '\\[media\\] wiring|\\[mediawire\\]|media_library .*binds' | cut -c1-330"))
|
||||
print("== per-drive binds (docker's own view):")
|
||||
for a in ("qbittorrent", "sonarr", "radarr", "prowlarr"):
|
||||
print(f" {a}:", w.guest(f"docker inspect {a} -f '{{{{range .Mounts}}}}{{{{.Source}}}} -> {{{{.Destination}}}}; {{{{end}}}}'").strip())
|
||||
for a, port in (("sonarr", 8989), ("radarr", 7878)):
|
||||
rf = arr(a, port, "/rootfolder"); tags = arr(a, port, "/tag"); dc = arr(a, port, "/downloadclient")
|
||||
print(f"== {a}: root folders {[r.get('path') for r in rf] if isinstance(rf, list) else rf}")
|
||||
print(f" tags {[t.get('label') for t in tags] if isinstance(tags, list) else tags}")
|
||||
print(f" download clients {[(c.get('name'), c.get('implementation'), [f.get('value') for f in c.get('fields', []) if f.get('name') in ('host', 'tvCategory', 'movieCategory')], c.get('tags')) for c in dc] if isinstance(dc, list) else dc}")
|
||||
apps = arr("prowlarr", 9696, "/applications", "v1")
|
||||
print(f"== prowlarr: apps {[(a.get('name'), a.get('syncLevel'), next((f.get('value') for f in a.get('fields', []) if f.get('name') == 'baseUrl'), None)) for a in apps] if isinstance(apps, list) else apps}")
|
||||
print("== qbittorrent categories:", w.guest("docker exec qbittorrent sh -c 'curl -s http://127.0.0.1:8080/api/v2/torrents/categories'").strip()[:600])
|
||||
Reference in new issue
Block a user