--- tags: [truenas, restore, incident, git, media, arr, permission] created: 2026-09-02 updated: 2026-09-02 status: fully resolved 2026-09-02 — Git-sync (NFS4 ACL DENY сняты полной dacl-заменой, push ОК, ahead=0/behind=0), Arr-стек ПОЛНОСТЬЮ рабочий (prowlarr/radarr/sonarr/jellyfin/transmission Up, все uid 950, сети персистентны в compose). ✅ §6a jellyfin-траversed-фикс: root `chown 950:950 + chmod 750 /mnt/RED_2TB/storage` (был 921:921, блокировал traverse → FFmpeg 243) — проигрывание работает. ✅ §6b transmission: `docker restart` → 254/255 чисты. Незначительные остатки: торрент #1 требует Verify в UI; скрытые файлы корня storage; несвязанный library-app restart-loop --- # Incident 2026-09-02: Поломка прав uid 921/0000 после restore — масштаб и влияния **Сводный инцидент-документ.** Родитель: `2026-08-31-syncthing-truenas-incident.md` (Syncthing). Здесь документируем подтверждённый масштаб той же поломки прав и её воздействие на git-sync (мак/Eagle) и медиа/arr-стек на TrueNAS. **Корень (общий для всех):** после восстановления из бэкапа `/mnt/RED_2TB/storage/*` стал принадлежать **uid 921 = `transmission`** с правами `----------`/`d---------` (0000), вместо `truenas_admin` (950). Контейнеры, пользователи и git, работающие под другими uid, теряют доступ. --- ## 1. Git-sync obsidian на маке (Eagle) — СТОИТ (ahead 55) **Симптом на `~/obsidian`:** ``` git status → ## main...nas/main [ahead 55] git fetch/push → fatal: '/mnt/RED_2TB/storage/git/obsidian-vault.git' does not appear to be a git repository ``` **Причина (read-only проверка TrueNAS):** ``` /mnt/RED_2TB/storage/git d--------- 4 921 921 /mnt/RED_2TB/storage/git/obsidian-vault.git (permission denied — вложено в storage/git) ``` Папка `storage/git/` (внутри — bare repo `obsidian-vault.git`) с правами 0000 / owner 921. Git на маке (SSH-ключ жив, `CONN_OK` ✅) не может открыть bare repo → fetch/push падают → локальные 55 коммитов не уходят. **Важно про механизм cron — НЕ Hermes cron, а launchd:** - Агент: `~/Library/LaunchAgents/com.sync-vault.plist` - Программа: `/Users/admin/scripts/sync-vault.sh`, `StartInterval = 300` сек (5 мин) - Состояние: **активен** (`launchctl list` → `com.sync-vault`), `runs = 3762`, `last exit code = 0` - `sync-vault-lib.sh` **умышленно глушит** недоступность remote: если `git fetch` падает → логирует и `exit 0`. Поэтому launchd показывает exit code 0 при фактически сломанном sync (`ahead 55`). Это **не** сбой cron — это корректное поведение скрипта, скрывающее dead remote. - Системный crontab на маке пуст (`crontab -l` нет), `/etc/crontab` нет. Запуск — только через launchd `${LABEL}`. **Связанные доки:** `family/how-to/vault-git-sync.md`, `family/how-to/obsidian-sync.md`. --- ## 2. Медиа-папки TrueNAS — сломаны (uid 921, d---------/drwx------) Read-only проверка `ls -ld /mnt/RED_2TB/storage/`: ``` d--------- transmission transmission storage/Cartoons d--------- transmission transmission storage/Downloads d--------- transmission transmission storage/Movies d--------- transmission transmission storage/Music drwx------ transmission transmission storage/series d--------- transmission transmission storage/shared ``` (отображается как `transmission` = uid 921 — тот же, что и в инциденте; права 0000/700 сломаны для внешних сервисов.) `Movies-Radarr`, `Series-Sonarr` — не существуют (старая схема, на TrueNAS актуальны только `storage/`-медиа). Медиа-папки починки не проходили (в отличие от `obsidian`/`obsidian-syncthing`). --- ## 3. Arr/Jellyfin-стек на TrueNAS — выключен + не сможет работать из-за прав **Факты:** - В `docker ps -a` НЕТ ни radarr/sonarr/prowlarr/jellyfin контейнеров (ни запущенных, ни остановленных). Стек не пересоздавался после проблемного периода. - Composes живут в `/mnt/RED_2TB/docker/arr/`: `docker-compose.yml` (prowlarr/radarr/sonarr/jellyfin), подпапки `prowlarr/ radarr/ sonarr/ jellyfin/ media-pipeline/`. - `docker/arr/docker-compose.yml` монтирует `/mnt/RED_2TB/storage` в radarr/sonarr (rw) и jellyfin (`:ro`). При сломанных правах медиа-папок контейнеры не смогут читать/импортировать → пустая библиотека. - **Работает только `transmission`** (Up 8 days), его compose отдельный: `/mnt/RED_2TB/docker/transmission/`. config владелец `transdamon`/911. RPC `transmission-remote` вернул `403 Forbidden` — auth вкл., статус торрентов извне без токена не читается. **Чтобы запустить стек:** восстановить права медиа-папок `storage/` (150 и выше 950/нужный сервисный uid, rwX) → `cd /mnt/RED_2TB/docker/arr && docker compose up -d`. **Дексо стек** — разделение ролей (см. `family/how-to/arr-stack-taiga.md`): - Taiga (TrueNAS) = acquisition (transmission качает, arr добавляет) - Kraken = serving (jellyfin на план-сервире). Jellyfin на TrueNAS — acquisition-side media storage, не primary serving. --- ## 4. Несвязанные находки (не трогала диагностика, для контекста) - Контейнер `library-app` (`library`) в restart-loop: `FileNotFoundError: '/library/flibusta_fb2_local.inpx'` — это приложение полки книг Flibusta, монтирует `/mnt/RED_2TB/storage/Downloads/fb2.Flibusta.Net → /library`; INPX-файла на пути нет. Не связано с поломкой прав; ручной фикс только по запросу. --- ## Общий план (ИСПРАВЛЕН — актуальный рабочий статус в §5 ниже; здесь технические применения) > **Практическое уточнение 2026-09-02 (Важно для будущего):** несмотря на утверждение в § «НЕ ПОСIX», на практике **root-`chown -R`/`chmod` на хосте TrueNAS СРАБОТАЛИ** и привели медиа-папки к `950:950 drwxrwx---` (это под LTS-смонтированным zfs с `acltype=nfsv4`, где POSIX-биты отображаются из NFS4 owner@/group@/ACL). Реальная поломка была **двухслойная**: (1) uid владельца файла сбит на 921 (правит `chown`), (2) биты owner@ обнулены (правит `chmod`/ACL). Вывод: у этих простых zfs-датасетов `chown`/`chmod` под root **достаточны и быстрее**, чем полный `filesystem.setacl`. `midclt setacl` нужен, когда ACL не-тривиальный (произвольные ACE entries поверх базовых) — здесь их не было (ACL тривиальны, `trivial:true` в getacl). Для будущего: пробовать POSIX chown/chmod первым, setacl — только если chmod не влияет на ACE и остаётся `d---------` у владельца с правильным uid. ### Диагноз по NFS4 ACL (что именно сломано) Реальные ACL через `midclt call filesystem.getacl` у `storage`, `git`, `Downloads`, `Movies`, `Cartoons` **структурно ИДЕНТИЧНЫ рабочему `obsidian`**, но: 1. владелец **uid/gid = 921** (`transmission`) вместо правильного **950** (`truenas_admin`); 2. у записи `owner@` **обнулены `READ_DATA / WRITE_DATA / EXECUTE / APPEND_DATA / DELETE_CHILD`** (все в `false`) → POSIX-маска `d---------`. Рабочий эталон (`obsidian`): uid/gid **950:950**, `owner@` полный, `group@` rwX (без WRITE_ATTRS/ACL/OWNER), `everyone@` — только attrs. ### Проверенная сигнатура midclt ```bash # Filesystem-методы существуют (40, подтверждены 2026-09-02): # filesystem.getacl / filesystem.setacl / filesystem.chown / filesystem.setperm # setacl(schema): {path, uid, gid, dacl, nfs41_flags, acltype, options} # options: {stripacl:bool, recursive:bool, traverse:bool, canonicalize:bool(default true), # validate_effective_acl:bool(default true)} # dacl: массив ACE {tag: owner@|group@|everyone@|USER|GROUP, id, type: ALLOW|DENY, perms, flags} ``` ### Применение (скрипт готов на маке: `~/fix-storage-nfs4-acl.sh`) Скрипт делает 3 этапа; применяется через `filesystem.setacl` с uid/gid + dacl + options.recursive/traverse: ```bash # скопировать на TrueNAS и запустить (sudo не нужен): scp ~/fix-storage-nfs4-acl.sh truenas_admin@mallexxx.duckdns.org:/tmp/ ssh truenas_admin@mallexxx.duckdns.org 'bash /tmp/fix-storage-nfs4-acl.sh' ``` Внутри: 1. **Бэкап ACL** каждой папки → `/mnt/RED_2TB/backup/facl_fix_<дата>/.acl.json` (откат — применить сохранённые через `filesystem.setacl`). 2. **Применение** к каждой папке списка (`Cartoons Downloads Edu Movies Music ada3s1 art books cartoons-series documentaries documentaries-series git nas photo_dedup_test seafile series shared singularity sonarr work`): ```bash midclt call filesystem.setacl \ '{"uid":950,"gid":950,"dacl":[<эталон-ACE obsidian>],"options":{"recursive":true,"traverse":true,"stripacl":false}}' ``` 3. **Verify**: все каталоги → uid 950; тест `git --git-dir=/git/obsidian-vault.git log`. > `obsidian` / `obsidian-syncthing` в список **НЕ включены** — уже рабочие 950:950. ### После фикса прав - **На маке**: `bash ~/scripts/sync-vault.sh` → 55 коммитов уедут в bare repo (launchd возобновит нормальную работу; см. раздел 1). - **Arr-стек**: `cd /mnt/RED_2TB/docker/arr && docker compose up -d` → проверить `docker compose ps`. ### Открытые вопросы перед запуском (подтверждение Alex) - Transmission-контейнер работает **как root** (`docker exec transmission id` → uid 0), поэтому права медиа для него некритичны; но данные Transmission (downloadDir `/mnt/storage/Downloads`) док описывал под `transdamon`/911. Решено ставить единообразно **950** (нужно для git/arr/serving). Если нужен и доступ transdamon/911 — добавить явный ACE `GROUP` на 911. - Альтернатива владельцу 950 — общая группа `nas_users` (3000, члены: truenas_admin, transmission, nas и др.). Эталон obsidian = 950. --- ## 5. ⭐ РЕШЕНИЕ от 2026-09-02: ВАРИАНТ А — единый PUID/PGID=950 + рекурсивный фикс прав **Контекст:** вопрос «будут ли файлы, созданные transmission, читаться jellyfin?» вскрыл, что простой смены владельца верхних папок на 950 **НЕДОСТАТОЧНО** — нужно согласовать межсервисную читаемость контента + фикс вглубь файлов. Выбран **Вариант A** (одобрен Alex, стоп-правило: root-команды выполняет Alex, обязательный бэкап перед изменениями). ### Факты, на которых строится решение - **Все linuxserver-образы загружены локально на TrueNAS** (проверено `docker images`): `radarr`, `sonarr`, `jellyfin`, `transmission`, `prowlarr`. Контейнеры (кроме transmission) **ещё не созданы** из них. - **Проверен механизм PUID/PGID** в linuxserver: Entrypoint=`[/init]`, есть `/etc/s6-overlay` (s6-based). → `PUID`/`PGID` обрабатываются штатно s6-stage2-hook. Нативный механизм. - **Дефолт без PUID:** у текущего transmission `PUID` не задан → контейнер работает **root** (подтверждено `docker exec transmission id` → root). Медиа-образы без явного PUID разъехались бы по разным uid → не видят файлы друг друга. - **Масштаб поломки вглубь** (подсчёт через transmission-root, `find -printf '%u'`): - `Movies`: **257 908** файлов, из них **257 751 → uid 921** (+157 → 950). - `Downloads`: mix 518→911, 380→921, 7→1001. - `series`: 94 → 921; `Music`: 8484; `git`(bare): 3430; `work`: 26180; `Cartoons`: 1009. - Глубокие `.mkv`/`.avi`/`.iso` тоже `921:921 mode 0000` — поломка НЕ только каталоги, а каждый inode. ### Целевая модель Варианта А Все медиа/arr/jellyfin контейнеры работают под **единым uid 950:950** (`truenas_admin`, как obsidian-эталон), тогда transmission→(radarr→jellyfin) взаимно читают: - transmission (станет 950) качает → файлы 950 - radarr/sonarr (950) импортируют → 950 - jellyfin (950) читает → ✅ ### Этапы (рабочий статус на 2026-09-02) - ✅ **Этап 0 — БЭКАП выполнен** → `/home/truenas_admin/variantA_bk/`: `transmission.docker-compose.yml` (оригинал), `arr.docker-compose.yml` (оригинал), `transmission_settings.json` (2982 б), ACL топ-папок (Cartoons Downloads Movies Music git work series books shared) + README.txt. > ⚠️ **Питфолл бэкапа:** `/mnt/RED_2TB/backup` — root-owned (`drwxrwxr-x root root`), `truenas_admin` туда **писать не может** → бэкап сделан в домашку `~truenas_admin`. Файл `docker/transmission/docker-compose.yml` на хосте владеет uid 911 (`drwx------ 911 911`) → прочитан/скопирован **через root-контейнер** `docker exec transmission cat /config/docker-compose.yml`. - ✅ **Этап 1 — правка compose на PUID/PGID=950 ВЫПОЛНЕНА (2026-09-02):** - **transmission compose:** `/config/docker-compose.yml` перезаписан через `docker cp /tmp/transmission-new-compose.yml transmission:/config/docker-compose.yml`. Добавлено `PUID=950` + `PGID=950`. Оригинал в `variantA_bk`. (Скрипт-источник на маке: `~/transmission-new-compose.yml`.) - **arr compose:** `/mnt/RED_2TB/docker/arr/docker-compose.yml` перезаписан (владелец truenas_admin → запись прошла без root): во всех 4 сервисах (prowlarr/radarr/sonarr/jellyfin) добавлено `PUID=950` + `PGID=950` (у всех уже был `TZ`). Проверено `docker compose config --quiet` → `COMPOSE_VALID`. Источник: `~/arr-new-compose.yml`. Оригинал в `variantA_bk`. - **Arr compose НЕ имеет секции `networks` у сервисов** → при подъёме будет дефолт-сеть `_default`. Consciously оставлено (оригинал не задавал networks у radarr/sonarr/jellyfin явно, только глобально `media_net`/`caddy_default`; НЕ переопределено чтобы не менять поведение без надобности). - ✅ **Этап 2 — ПЕРЕСОЗДАНИЕ transmission под PUID=950 ВЫПОЛНЕНО (2026-09-02).** НЕ понадобился `docker rm -f`. Решено штатно: - **Питфолл про compose-проект:** у контейнера НЕТ compose-лейблов (`com.docker.compose.project = `) → `docker compose up` в папке 911 его не распознаёт и даёт name-conflict. Причина 911-папки ушла сама: **после пересоздания владелец `/mnt/RED_2TB/docker/transmission` стал `950:950`** → папка доступна. - **Способ:** `cd /mnt/RED_2TB/docker/transmission && docker compose up -d --force-recreate` — применил PUID, контейнер `Recreated/Started`, проект `transmission`. - **Проверено:** `docker exec transmission printenv PUID PGID` → `950 950`; процесс `transmission-daemon` работает под `abc` (uid 950), НЕ root. - **Ключевой урок (наш ошибка):** временные compose-файлы в `/tmp` и `docker cp` — костыль. Использовать только штатный запуск из правильной папки compose. Временные файлы `/tmp/transmission-new-compose.yml` и `/tmp/arr-new-compose.yml` удалены (почищены 2026-09-02). - (В /tmp остались чужие/ранее существовавшие `compose_new.yml`, `reverse-portal-compose.yml` — НЕ наши, не трогали.) - ✅ **Этап 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---`). ✅ - ✅ **Второй 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 догнаны вторым проходом. ### ✅ RESOLVED 2026-09-02: Блокер push снят — полной dacl-заменой, НЕ stripacl **Симптом (после починки прав):** на маке 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`. **Фикс РАБОЧИЙ (RESOLVED 2026-09-02, Alex выполнил из root-шелла):** ⚠️ **`stripacl:true` с пустым `dacl:[]` НЕ работает** — джоба при `filesystem.setacl /path ` вываливалась `Too many arguments (expected 1, found 2)` (path передавался как отдельный аргумент — палево), а точечный `stripacl:true` на объекте дал `SUCCESS`, но DENY-ACL **остался**. Решило только **полная dacl-замена** (передача полного массива ACE без DENY, где owner@/group@ = ALLOW), т.е. setacl воспринимает полный dacl как *.replace* всего ACL, а не merge. Проверенная рабочая команда (root-шелл для truenas_admin, job асинхронный — вернёт id, потом `SUCCESS`): ```bash # точечно на один объект (проверка метода): midclt call filesystem.setacl '{"path":"/mnt/RED_2TB/storage/git/obsidian-vault.git/objects/ac/d1b45542e82aa40f345da3b8ac9f721633b138","uid":950,"gid":950,"acltype":"NFS4","dacl":[, ],"options":{"recursive":false}}' # затем рекурсивно на весь репозиторий (dacl тот же, recursive:true): midclt call filesystem.setacl '{"path":"/mnt/RED_2TB/storage/git/obsidian-vault.git","uid":950,"gid":950,"acltype":"NFS4","dacl":[{"tag":"owner@","id":-1,"type":"ALLOW","perms":{"READ_DATA":true,"WRITE_DATA":true,"EXECUTE":false,"APPEND_DATA":true,"DELETE_CHILD":false,"DELETE":false,"READ_ATTRIBUTES":true,"WRITE_ATTRIBUTES":true,"READ_NAMED_ATTRS":true,"WRITE_NAMED_ATTRS":true,"READ_ACL":true,"WRITE_ACL":true,"WRITE_OWNER":true,"SYNCHRONIZE":true},"flags":{"BASIC":"INHERIT"}},{"tag":"group@","id":-1,"type":"ALLOW","perms":{"READ_DATA":true,"WRITE_DATA":false,"EXECUTE":true,"APPEND_DATA":false,"DELETE_CHILD":false,"DELETE":false,"READ_ATTRIBUTES":true,"WRITE_ATTRIBUTES":false,"READ_NAMED_ATTRS":true,"WRITE_NAMED_ATTRS":false,"READ_ACL":true,"WRITE_ACL":false,"WRITE_OWNER":false,"SYNCHRONIZE":true},"flags":{"BASIC":"INHERIT"}}],"options":{"recursive":true,"traverse":true}}' ``` **Ключевое правило midclt:** `filesystem.setacl` принимает **ОДИН JSON-аргумент со всеми полями** (`path`, `uid`, `gid`, `acltype`, `dacl`, `options`) — НЕ path отдельно. Job вернёт id и выполнится асинхронно; проверять `midclt call core.get_jobs` (state `SUCCESS`/error). Проверка после (для владельца 950, НЕ root): ```bash git --git-dir=/mnt/RED_2TB/storage/git/obsidian-vault.git cat-file -t acd1b45542e82aa40f345da3b8ac9f721633b138 # → tree git --git-dir=/mnt/RED_2TB/storage/git/obsidian-vault.git fsck # → 0 corrupt/missing/permission denied ``` **Результат (проверено 2026-09-02):** объект читается (`tree`), `git fsck` под 950 → **0 ошибок**, и с мака `git push nas main` **прошёл** (`a2c7279..2b6c181 main -> main`, exit=0). Локально/remote **ahead=0 behind=0** — полностью синхронизировано. launchd-крона (коммиты каждые 5 мин) теперь реально пушит. Бэкап ACL репо снят до фикса: `~/variantA_bk/git_ACL_backup_2026-09-01_232328/` (root ACL + mode-map 3402 файлов). **Куда попадают 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 chown -R 950:950 "$S/git" "$S/nas" "$S/ada3s1" "$S/photo_dedup_test" \ "$S/seafile" "$S/singularity" "$S/radarr" "$S/sonarr" 2>/dev/null find "$S/git" "$S/nas" "$S/ada3s1" "$S/photo_dedup_test" "$S/seafile" \ "$S/singularity" "$S/radarr" "$S/sonarr" \ -type d -exec chmod u+rwX,g+rwX,o-rwx {} + 2>/dev/null find "$S" -maxdepth 1 -type f \( -name "._*" -o -name ".DS_Store" -o -name ".bash*" -o -name ".profile" \ -o -name ".com.apple*" \) -exec rm -f {} + 2>/dev/null chmod -R g+rX "$S/git" 2>/dev/null git --git-dir="$S/git/obsidian-vault.git" log --oneline -2 2>&1 | head # проверка ``` > ⚠️ `rm -f` скрытых файлов корня — mac-мусор/остатки старого владельца 921, безопасно. Если `.profile`/`.bashrc` рабочие — убрать их из rm по решению. ### ⚠️ Текущий статус после вторго прохода + RESOLUTION (актуально на 2026-09-02) - ✅ **Push на маке ПОЧИНЕН** — NFS4 ACL `DENY` на ~1946 loose git-объектах сняты через **полную dacl-замену** (не stripacl). См. секцию «✅ RESOLVED … dacl-заменой». Git-sync работает: fetch+push проходят, ahead=0 behind=0. - ✅ **Arr-стек ПОДНЯТ и РАБОТАЕТ (2026-09-02).** Контейнеры созданы и запущены штатно из `/mnt/RED_2TB/docker/arr`: - `docker compose up -d` в `/docker/arr` создал и запустил `prowlarr`, `radarr`, `sonarr`, `jellyfin` (все в проекте `arr`). Проверено: процессы работают под **uid 950** (`Prowlarr/Radarr/Sonarr/jellyfin` pid утилиты uid=950, не root). - **Сети (персистентность):** для запуска потребовалось воссоздать отст. `media_net` (external): `docker network create media_net` (она была утеряна с `.ix-apps` при пересоздании пула; в compose объявлена только `external: true`, НЕ создаётся compose-ом → теряется при полном демонтаже docker, шаг восстановления: `docker network create media_net`). transmission подключён к `media_net` (для radarr/sonarr). - **Пересозданный transmission compose/сети:** папка `docker/transmission` стала `950:950` после пересоздания (была 911:911, поэтому изначально не давала `cd`). В `docker/transmission/docker-compose.yml` **добавлена networks секция**: `media_net` + `transmission_default` (обе external), чтобы подключение transmission к media_net было перманентным (не живым `docker network connect`). Проверено `docker compose up -d` пересоздал — обе сети на месте. **Порты:** caddy резолвит transmission через `transmission_default` (Web UI `transmission.mallexxx.duckdns.org` работает); radarr достаёт `transmission:9091` через `media_net` (TR_OK). - **Связка работает:** jellyfin читает `/storage/Movies` (READ_OK), radarr↔transmission по media_net OK (172.16.17.2:9091), все UI-порты слушают (prowlarr 9696, radarr 7878, sonarr 8989, jellyfin 8096, transmission 9091). radarr/sonarr/jellyfin монтируют `/mnt/RED_2TB/storage` → `/storage` (root folder у radarr на TrueNAS = `/storage/...`, не `/media` как Kraken). - **Осталось по стеку:** настройка самих сервисов через их Web UI (radarr root-folder `/storage`, indexers в prowlarr, библиотеки в jellyfin) — вне времени запуска; я не вмешиваюсь в конфиги. - 🔜 **Скрытые файлы корня storage** (`.DS_Store`, `.bash_*`, `.profile`, `.com.apple*`) остаются `921:921 mode 0000` (не добиты — в root-шаге B rm для них предлагался, но решение не подтверждено). Сам корень `storage/` → `drwxrwx--- 921:921` (owner 921, хотя group 950 есть). Проверить, нужен ли корню chown 950. - 🔜 **`books`** — владелец `950:921` (не 950:950) — оставлен как был (служебный, не критично для saga). ### Точное содержание transmission compose (оригинал, важно для пересоздания) ```yaml services: transmission: image: lscr.io/linuxserver/transmission:latest container_name: transmission restart: unless-stopped environment: - TZ=Asia/Novosibirsk - USER=transmission_admin - PASS=E$%p3En4a%R6 - WHITELIST=172.16.*.* volumes: - /mnt/RED_2TB/storage:/mnt/storage - /mnt/RED_2TB/docker/transmission:/config ports: - 9091:9091 - 51413:51413 - 51413:51413/udp ``` (в compose НЕ было PUID/PGID → контейнер root; transmission монтирует `storage` → `/mnt/storage`, download-dir `/mnt/storage/Downloads`) ## 6. Пост-запуск arr-стека: 2 блокера — ОБА РЕШЕНЫ (2026-09-02, конец сессии) После успешного запуска стека (все контейнеры Up под 950) выявлены два REFAIL. **Общий скрытый корень обоих + случайно та же причина, что у jellyfin-транскодинга:** **сам корень `/mnt/RED_2TB/storage` (верх датасета) остался `921:921`**, ACL `owner@/group@ ALLOW` но `everyone@ EXECUTE=False` → uid 950 (jellyfin/transmission как не-owner group truenas_admin...) фактически **не мог traverse вглубь** `/storage/Movies/...`, ХОТЯ ACL самих файлов/каталогов были корректными (`trivial:true`, owner@ READ/EXEC, 950:950). Это даёт клинический кейс «ACL файла чистый, владелец 950, но чтение = Permission denied». ### ✅ 6a. Jellyfin: FFmpeg exit 243 при проигрывании — РЕШЕНО **Симптом:** веб-UI jellyfin (Setup завершён, `StartupWizardCompleted:true`) открылся, библиотеки видят `/storage/Movies`, но проигрывание падало `FFmpeg exited with code 243` (на чтении входа `/storage/Movies/Snatch.x264/...`, НЕ на записи transcode — transcodes/`/config/cache` уже стали 950 после первого chown). **Двойной корень:** (1) конфиг jellyfin вглубь `/config/data` был 911:911 (11 441 файл; jellyfin под 950) → первый `chown -R 950:950 /mnt/RED_2TB/docker/arr/jellyfin` открыл UI (этот chown Alex уже выполнил ранее); (2) НО даже после него чтение файла `/storage/Movies/Snatch.x264/...` из uid 950 давало **`Permission denied`** при чистом ACL файла+каталога. Причина — **корень `/mnt/RED_2TB/storage` остался 921:921 и блокировал traverse** (см. выше). **Фикс ЖЕЛЕЗНО (root, Alex выполнил — заработало):** ```bash chown 950:950 /mnt/RED_2TB/storage chmod 750 /mnt/RED_2TB/storage # rwxr-x--- → owner u950 / group(g950=truenas_admin) r-x → traverse для jellyfin ``` > linuxserver контейнеры (jellyfin/transmission) под PUID/PGID=950 имеют gid=950 → члены `truenas_admin`. После chmod 750 group r-x открывает traverse. Результат: jellyfin проигрывает (direct play / transcod по необходимости). **Отключение транскодинга** (если не нужен): Dashboard → Playback → снять галку «Allow media playback that requires transcoding» (тогда только Direct Play); транскодиг включается лишь когда клиент не поддерживает исходный кодек. UI на `jellyfin.mallexxx.duckdns.org`. ### ✅ 6b. Transmission: 255 торрентов "no data found" — РЕШЕНО `docker restart` **Симптом:** transmission-UI (9091) открывался, но все 255 торрентов показывали **`error 3: No Data Found`**. **Уточнённый диагноз (проверено RPC изнутри, whitelist `172.16.*.*`):** downloadDir у каждого торрента УЖЕ корректно указывал не на Downloads, а на **`/mnt/storage/Movies`** (или `/storage/documentaries`), и файлы там физически ЕСТЬ (164 single `.mkv` прямо в Movies; `Thursday.1998_BDRip_cw.mkv` 3.1G и т.д.), владелец 950 `-rw-r-----`, читаются под uid 950 (`docker exec -u 950` → READ_OK). **НЕ** проблема download-dir и НЕ права — файл доступен демону. `torrent-verify` поодиночке НЕ снимал ошибку. **Настоящий корень:** ошибка `No Data Found` была **закеширована при старте**, когда транзит через корень `/storage` был ещё заблокирован (до `chmod 750` на корень). transmission не перевалидировал данные после разблокировки traverse. **Фикс (НЕ root):** простая перезагрузка демона заново валидирует все торренты при доступном traverse: ```bash docker restart transmission ``` **Результат:** **254 из 255 торрентов СРАЗУ чисты** (было 0). Остался только id=1 (`Thursday.1998_BDRip_cw.mkv`) — ранее ему крутили `torrent-verify`, но он всё ещё `error 3`; добить: в Web UI transmission на торренте → **Verify Local Data**, либо ещё один verify. > Вывод для будущего: «No Data Found» у всех торрентов в transmission после пересоздания/миграции данных чаще всего = **старт демона при недоступном traverse к данным**. Решение — починить traverse (root каталога/путь) и `docker restart`. Данные при этом НЕ трогаются. --- ## Связанные заметки - [[2026-08-31-syncthing-truenas-incident]] — вызвавший инцидент + фикс syncthing - [[arr-stack-taiga]] — acquisition-стек на TrueNAS - [[arr-stack-kraken]] — serving-стек (Kraken) - [[vault-git-sync]] — git-sync алгоритм и скрипты - [[obsidian-sync]] — общая схема Eagle↔Taiga↔Kraken - [[syncthing-truenas-android]] — syncthing схема (требует обновления volumes → `obsidian-syncthing`)