[2026-09-02] eagle: family/documents/vault-sync/2026-09-02-restore-privilege-scope.md family/how-to/arr-stack-taiga.md family/how-to/vault-git-sync.md
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
tags: [truenas, restore, incident, git, media, arr, permission]
|
||||
created: 2026-09-02
|
||||
updated: 2026-09-02
|
||||
status: in-progress (Этап 0-3 done — transmission пересоздан под PUID=950 штатно, медиа-права рекурсивно исправлены; ОСТАЛОСЬ: git/nas/второй root-заход на добивку, запуск arr-стека, первый sync-vault на маке)
|
||||
status: in-progress (Этап 0-3 + 2-й root-проход DONE — storage все 950, git-sync fetch ОК; ОСТАЛОСЬ основной блокер: NFS4 ACL DENY READ_DATA на ~1946 git-объектах → push на маке падает)
|
||||
---
|
||||
|
||||
# Incident 2026-09-02: Поломка прав uid 921/0000 после restore — масштаб и влияния
|
||||
@@ -169,11 +169,60 @@ ssh truenas_admin@mallexxx.duckdns.org 'bash /tmp/fix-storage-nfs4-acl.sh'
|
||||
- ✅ **Этап 3 — рекурсивный фикс прав вглубь ВЫПОЛНЕН Alex (root) + проверен.** Результат верификации 2026-09-02:
|
||||
- Медиа-папки → `950:950 drwxrwx---`: Cartoons, Downloads, Movies, Music, art, books, cartoons-series, documentaries(-series), series, shared, work. ✅
|
||||
- Вглубь Movies: файлы → `950:950`, права разблокированы (`rw-r-----`/`rwxrwx---`). ✅
|
||||
- **ЕЩЁ НЕ ДОБИТО (остаточек):** `git/` bare repo dir → `d--------- 950:950` (0000) → **git-sync на маке всё ещё стоит** `fatal: not a git repository`; `nas` (921/0000, не попал в chown/chmod), `ada3s1`, `photo_dedup_test`, `seafile`, `singularity` (0000/700); скрытые mac-файлы корня `.DS_Store/.bash*/.profile/.com.apple*` (921); сам корень `storage` → `921:921 drwxrwx---`.
|
||||
- ✅ **Второй root-проход ВЫПОЛНЕН Alex (вторая команда ниже) — добиты `git`, `nas`, `ada3s1`, `photo_dedup_test`, `seafile`, `singularity`, `radarr`, `sonarr`:** все теперь `950:950 drwxrwx---`. Проверено:
|
||||
- Все топ-папки storage теперь `950:950 drwxrwx---` (сплошняком, кроме скрытых файлов корня и самого корня). ✅
|
||||
- `storage/git/obsidian-vault.git` теперь **открывается** — `git log` показывает коммиты (HEAD `a2c72793` [2026-08-17]...).
|
||||
- `git/nas` уже не «matching вне-списка» — chown/chmod догнаны вторым проходом.
|
||||
|
||||
### ⬜ Остаточный root-шаг (второй проход, готов для Alex) — добить git + nas + прочее
|
||||
### ⬜ Найден БЛОКЕР PUSH: NFS4 ACL `DENY READ_DATA` на тировых объектах git-репозитория
|
||||
|
||||
Команда подготовлена в сессии, Alex ещё не запускал:
|
||||
**Симптом (после починки прав):** на маке git-sync теперь:
|
||||
```
|
||||
git fetch nas main → OK (bare repo доступен, fetch exit=0)
|
||||
git push nas main → FAIL:
|
||||
remote: fatal: loose object acd1b45542e82aa40f345da3b8ac9f721633b138 ... is corrupt
|
||||
remote unpack failed: index-pack abnormal exit
|
||||
```
|
||||
`sync-vault.sh` — `Committed` потом `Push failed`. Ahead вырос 55 → 62 (коммиты локально копятся, не пушатся).
|
||||
|
||||
**Диагностика — это НЕ повреждение данных, а NFS4 ACL-блокировка чтения:**
|
||||
|
||||
| Проверка | Результат |
|
||||
|---|---|
|
||||
| `git fsck --full` через **root** (контейнер gitea, монтирует `/git-repos`) | ЧИСТО: только `dangling commit/tree`, **ни одного corrupt/missing/bad** |
|
||||
| `git cat-file -t acd1b45...` под root (gitea) | `tree` — объект читается, цел |
|
||||
| NFS4 ACL самого файла `objects/ac/d1b...` (через `filesystem.getacl`) | **`owner@ DENY READ_DATA=True`** поверх `ALLOW` → перекрывает |
|
||||
|
||||
**Суть:** у ~**1946 из 3373** loose git-объектов в `obsidian-vault.git/objects/` стоит битый NFS4 ACL `owner@ type=DENY READ_DATA=True`. DENY-запись в NFSv4 **перекрывает ALLOW**, поэтому владелец (uid 950 = truenas_admin) **не может mmap/прочитать эти объекты** при push. Git на приеме (`git-receive-pack`/`index-pack`) трактует нечитаемость как «loose object corrupt» → push rejected. Root игнорирует ACL → поэтому fsck под gitea чист, а push от 950 падает. **Данные целы.**
|
||||
|
||||
POSIX-признак битых файлов: **mode `40` (`r--------`)**; нормальные объекты — mode `750`. (count: 3373 объектов, ~1946 с mode 4xx.)
|
||||
|
||||
**Фикс (root/root-midclt) — ГОТОВ, Alex ещё не запускал (ждёт отдельного подтверждения, т.к. влияет на ACL объектов):**
|
||||
```bash
|
||||
# снять битые NFS4 ACL (DENY) на весь git-репозиторий, вернуть стандарт из uid/gid
|
||||
midclt call filesystem.setacl /mnt/RED_2TB/storage/git/obsidian-vault.git \
|
||||
'{"uid":950,"gid":950,"dacl":[],"options":{"recursive":true,"traverse":true,"stripacl":true}}'
|
||||
|
||||
# проверить, что проблемный объект читается владельцем:
|
||||
git --git-dir=/mnt/RED_2TB/storage/git/obsidian-vault.git cat-file -t acd1b45542e82aa40f345da3b8ac9f721633b138
|
||||
|
||||
# затем с мака:
|
||||
cd ~/obsidian && git push nas main
|
||||
```
|
||||
> ⚠️ `chmod`/`chown` НЕ снимает NFS4 `DENY` ACE — нужен именно `stripacl:true` (или `setfacl -Rb` на хосте, если доступен). TrueNAS SCALE: `setacl` с `stripacl:true` + пустым `dacl` переведёт на POSIX-default из owner@/group@.
|
||||
> ⚠️ Перед применением снять бэкап ACL `git/` (read-only): `midclt call filesystem.getacl /mnt/RED_2TB/storage/git > ~/variantA_bk/git_after.acl`.
|
||||
> ⚠️ Стоп-правило Alex: nothing destructive без явного подтверждения — не делался, ждёт команды.
|
||||
|
||||
**Куда попадают DENY-ACL:** артефакт restore — часть loose-объектов при переносе данных получили инверсивный NFS4 ACL (`owner@ DENY read`). Это НЕ родние git-права (git-репо хранит объекты как read-only `r--r--r--` в обычном случае); на полке после поломки.
|
||||
|
||||
### Диагностические insights (для будущих сессий)
|
||||
- `docker exec transmission ...` даёт root вглубь `/mnt/storage` (transmission монтирует `storage`); `gitea` контейнер монтирует `/mnt/RED_2TB/storage/git → /git-repos` и имеет `git` — удобен для `git fsck`-честных проверок (root-контекст). `hermes-taiga` монтирует `/vault.git` = `storage/git/obsidian-vault.git` и тоже имеет git.
|
||||
- NFS4 `owner@ DENY` перекрывает `ALLOW` — клинический кейс «ls показывает доступно, а процесс не читает».
|
||||
- POSIX-бит файла (mode 40/750) коррелирует с NFS4 ACL; «corrupt» от `index-pack` при целых данных = почти всегда ACL/права на приеме, не реальное повреждение.
|
||||
|
||||
### ✅ Остаточный root-шаг (второй проход) — ВЫПОЛНЕН Alex; команда для справки (историческая)
|
||||
|
||||
> Уже пройдено — итоговое состояние `950:950 drwxrwx---` на всех топ-папках см. в Этапе 3 выше. Команда зафиксирована как рецепт для будущего:
|
||||
|
||||
```bash
|
||||
S=/mnt/RED_2TB/storage
|
||||
@@ -190,9 +239,9 @@ git --git-dir="$S/git/obsidian-vault.git" log --oneline -2 2>&1 | head # пр
|
||||
|
||||
> ⚠️ `rm -f` скрытых файлов корня — mac-мусор/остатки старого владельца 921, безопасно. Если `.profile`/`.bashrc` рабочие — убрать их из rm по решению.
|
||||
|
||||
### После остаточного фикса
|
||||
- **На маке**: `bash ~/scripts/sync-vault.sh` → 55 коммитов уедут в bare repo (launchd возобновит); проверить `git log nas/main..main` = 0.
|
||||
- **Arr-стек**: `cd /mnt/RED_2TB/docker/arr && docker compose up -d` → проверить `docker compose ps` + что jellyfin видит библиотеки (пути `/storage/*`).
|
||||
### ⚠️ Текущий статус после второго прохода (актуально)
|
||||
- **Push на маке БЛОКИРОВАН** NFS4 ACL `DENY READ_DATA` на ~1946 loose git-объектах — см. секцию «Найден БЛОКЕР PUSH» выше. Фикс `filesystem.setacl ... stripacl:true` ГОТОВ, Alex должен подтвердить.
|
||||
- **Arr-стек**: после снятия DENY-блокера на git и починки прав медиа — `cd /mnt/RED_2TB/docker/arr && docker compose up -d` → проверить `docker compose ps` + что jellyfin видит библиотеки (пути `/storage/*`). PUID/PGID=950 уже прописаны во всех 4 сервисах докер-стека.
|
||||
|
||||
### Точное содержание transmission compose (оригинал, важно для пересоздания)
|
||||
```yaml
|
||||
|
||||
@@ -15,13 +15,13 @@ Secondary arr stack on Taiga (TrueNAS), added 2026-05-20.
|
||||
|
||||
> **STATE 2026-09-02:** Стек **выключен** — в `docker ps -a` нет ни radarr/sonarr/prowlarr/jellyfin контейнеров (стек не пересоздавался). Compose-структура живёт в `/mnt/RED_2TB/docker/arr/` (`docker-compose.yml` + подпапки `prowlarr/ radarr/ sonarr/ jellyfin/ media-pipeline/`). Работает только `transmission` (отдельный compose `/mnt/RED_2TB/docker/transmission/`).
|
||||
>
|
||||
> **Почему не запускается просто так — медиа-права сломаны** (тот же restore-инцидент uid 921/0000): `/mnt/RED_2TB/storage/{Movies,Cartoons,Downloads,Music,series,shared}` → `d---------`/`drwx------`, owner `transmission` (uid 921). radarr/sonarr монтируют `/storage` (rw), jellyfin `:ro` — со сломанными правами не прочитают библиотеку. Фикс + запуск: см. `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`.
|
||||
> **Почему стек изначально не запускался — медиа-права были сломаны** (тот же restore-инцидент uid 921/0000): `/mnt/RED_2TB/storage/{Movies,Cartoons,Downloads,Music,series,shared}` были `d---------`/`drwx------`, owner `transmission` (uid 921). radarr/sonarr монтируют `/storage` (rw), jellyfin `:ro` — со сломанными правами не прочитали бы библиотеку. ⚠️ **Сейчас (2026-09-02, конец сессии) права медиа ИСПРАВЛЕНЫ** до `950:950 drwxrwx---` (см. PROGRESS ниже) — но контейнеры arr/jellyfin всё ещё не созданы/не запущены. Полный контекст: `family/documents/vault-sync/2026-09-02-restore-privilege-scope.md`.
|
||||
|
||||
> **Docker-image facts (2026-09-02):** All 5 media images **loaded locally** on TrueNAS (`docker images`): `lscr.io/linuxserver/{radarr,sonarr,jellyfin,transmission,prowlarr}:latest`. Only **transmission** container exists (running). **jellyfin/radarr/sonarr/prowlarr containers are NOT yet created** — they never get launched until perms fixed.
|
||||
> **Transmission runs as ROOT** (not 911/950): its compose `/mnt/RED_2TB/docker/transmission/docker-compose.yml` has **no `PUID`/`PGID`**, so linuxserver `/init` (s6-overlay) leaves it root (`docker exec transmission id` → uid 0). This is why it works on the 0000 media dirs. It mounts `storage` → `/mnt/storage`, download-dir = `/mnt/storage/Downloads`.
|
||||
> **Docker-image facts (2026-09-02):** All 5 media images **loaded locally** on TrueNAS (`docker images`): `lscr.io/linuxserver/{radarr,sonarr,jellyfin,transmission,prowlarr}:latest`. Only **transmission** container exists (now running as uid 950). **jellyfin/radarr/sonarr/prowlarr containers are NOT yet created** — their compose services have PUID/PGID=950 ready, but they have not been `up`'ed yet.
|
||||
> **Transmission originally ran as ROOT** (not 911/950): its compose had no `PUID`/`PGID`, so linuxserver `/init` (s6-overlay) left it root. ✅ **Fixed 2026-09-02:** `PUID=950 PGID=950` added and container force-recreated → now daemon under uid 950. It mounts `storage` → `/mnt/storage`, download-dir = `/mnt/storage/Downloads`.
|
||||
> **Fix direction (approved Variant A):** set `PUID=950 PGID=950` on transmission + all arr/jellyfin compose services so every service shares uid `950` and mutually reads files; then recursively fix perms in depth. Plan + commands: `2026-09-02-restore-privilege-scope.md` §5.
|
||||
>
|
||||
> **PROGRESS 2026-09-02:** Both compose files edited for PUID/PGID=950 (transmission at `/mnt/RED_2TB/docker/transmission/docker-compose.yml`, arr at `/mnt/RED_2TB/docker/arr/docker-compose.yml` incl. all 4 services). **transmission container force-recreated** from its proper folder and now runs its daemon as **uid 950** (was root) — env `PUID=950 PGID=950` confirmed, process under `abc`/950. Media perms in depth recursively fixed to `950:950` (Movies etc.). **STILL OPEN:** `storage/git/` and `storage/nas` perms not yet fixed (second root pass pending) → **do NOT start arr stack until git/nas done**; then `cd /mnt/RED_2TB/docker/arr && docker compose up -d`.
|
||||
> **PROGRESS 2026-09-02 (updated end-of-session):** Both compose files edited for PUID/PGID=950 (transmission at `/mnt/RED_2TB/docker/transmission/docker-compose.yml`, arr at `/mnt/RED_2TB/docker/arr/docker-compose.yml` incl. all 4 services). **transmission container force-recreated** from its proper folder (`cd /mnt/RED_2TB/docker/transmission && docker compose up -d --force-recreate`) and now runs its daemon as **uid 950** (was root) — env `PUID=950 PGID=950` confirmed, process under `abc`/950. Media perms in depth recursively fixed to `950:950 drwxrwx---` on all top storage folders (incl. git/nas 2nd root pass). **Still to do before arr stack is useful / to unblock git-sync:** (1) strip the broken NFS4 `DENY READ_DATA` ACL on ~1946 loose git objects in `obsidian-vault.git` (this breaks `git push` from Mac with fake "corrupt" error) — fix command and details in `2026-09-02-restore-privilege-scope.md`; (2) then `cd /mnt/RED_2TB/docker/arr && docker compose up -d` and verify jellyfin sees libraries (`/storage/*`).
|
||||
|
||||
## Notes from Setup (2026-05-20)
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ cd ~/Developer/vault-sync-test && bash test-sync.sh
|
||||
- `git add -A` in sparse worktree still stages deletions of out-of-cone files tracked in index — need to unstage them (fixed in old script; irrelevant with proper clone)
|
||||
- `core.quotePath=true` (default) escapes Cyrillic paths in `git ls-files` output — use `-c core.quotePath=false`
|
||||
- ZFS on TrueNAS blocks `chmod` — `git init` fails from host; must run from inside Docker container or create `.git` structure manually
|
||||
- **NFS4 `owner@ DENY READ_DATA` ACL breaks push (fake "corrupt" objects)** — see History 2026-09-02. Key: after a TrueNAS **pool restore**, a subset of loose git objects in the bare repo can carry an inverted NFS4 ACL `owner@ type=DENY READ_DATA=True`. In NFSv4 a DENY overlays ALLOW, so the owning uid (e.g. 950) can't mmap-read those objects → on receive, `git-receive-pack`/`index-pack` reports `loose object ... is corrupt` and rejects push, even though data is intact (`git fsck --full` under root is clean). Fix = `filesystem.setacl <repo> ... {stripacl:true}` (chmod/chown do NOT remove DENY ACEs). Tell-tale: POSIX file mode `40` (`r--------`) on loose objects vs normal `750`.
|
||||
|
||||
## History
|
||||
|
||||
|
||||
Reference in New Issue
Block a user