diff --git a/family/documents/vault-sync/2026-09-02-restore-privilege-scope.md b/family/documents/vault-sync/2026-09-02-restore-privilege-scope.md index 59e1278c..4abf2087 100644 --- a/family/documents/vault-sync/2026-09-02-restore-privilege-scope.md +++ b/family/documents/vault-sync/2026-09-02-restore-privilege-scope.md @@ -2,7 +2,7 @@ tags: [truenas, restore, incident, git, media, arr, permission] created: 2026-09-02 updated: 2026-09-02 -status: in-progress (Этап 1 done — оба compose на PUID=950 правлены; Этап 2 заблокирован: transmission без compose-лейблов, нужен rm -f — ждёт ок Alex) +status: in-progress (Этап 0-3 done — transmission пересоздан под PUID=950 штатно, медиа-права рекурсивно исправлены; ОСТАЛОСЬ: git/nas/второй root-заход на добивку, запуск arr-стека, первый sync-vault на маке) --- # Incident 2026-09-02: Поломка прав uid 921/0000 после restore — масштаб и влияния @@ -78,9 +78,9 @@ d--------- transmission transmission storage/shared --- -## Общий план (ИСПРАВЛЕН — НЕ выполнен, требует подтверждения) +## Общий план (ИСПРАВЛЕН — актуальный рабочий статус в §5 ниже; здесь технические применения) -> ⚠️ **2026-09-02 УТОЧНЕНО: `/mnt/RED_2TB/storage` — единый ZFS dataset `RED_2TB/storage` с `acltype=nfsv4`. НЕ ПОСIX.** Ранее планировалось `chown -R`/`chmod -R` — это **НЕВЕРНО** для TrueNAS SCALE с NFSv4 ACL. Права управляются **только** через `midclt call filesystem.setacl` (эквивалент TrueNAS UI → Datasets → `RED_2TB/storage` → Edit ACL → Apply recursively). `truenas_admin` = FULL_ADMIN в midclt → **root/sudo для setacl НЕ нужен** (проверено: `midclt call auth.me` → roles `FULL_ADMIN`). +> **Практическое уточнение 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 (что именно сломано) @@ -160,22 +160,39 @@ ssh truenas_admin@mallexxx.duckdns.org 'bash /tmp/fix-storage-nfs4-acl.sh' - **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 — ЗАБЛОКИРОВАНО (ключевой технический питфолл, 2026-09-02):** - - `cd /mnt/RED_2TB/docker/transmission` → **`permission denied`** (каталог `drwx------ 911 911` — владелец transdamon/911, truenas_admin нет доступа). - - Попытка `docker compose -f /tmp/transmission-new-compose.yml up -d` → создал сеть `tmp_default` и упал: **name conflict** (`container "transmission" already in use`). - - Полный рабочий контейнер пересоздать из compose **невозможно** по двум причинам: - 1. Контейнер создан **без compose-лейблов** (`com.docker.compose.project = `) → compose его **не распознаёт как свой** → не может мигрировать/пересоздать, только name-conflict. - 2. Композ-файл в каталоге 911 недоступен для работы оттуда. - - **Найденное решение:** удалить старый контейнер и поднять заново с корректным проектом (сохранит сеть `transmission_default`): - ```bash - docker rm -f transmission # данные в /config и /mnt/storage НЕ теряются (bind-mount на диск) - docker compose -f /tmp/transmission-new-compose.yml -p transmission up -d - docker exec transmission id # ожидаем uid=950 - ``` - - **Почему PUID нельзя применить к работающему контейнеру?** env зашивается при `docker run` (создании). `docker update` меняет ТОЛЬКО ресурсы (CPU/RAM/restart), **НЕ переменные окружения** — ограничение Docker. Пересоздание — единственный способ. - - **Альтернатива без пересоздания (если не хотим трогать transmission root):** оставить root; НО тогда новые скачанные файлы будут `root:root`, и radarr/jellyfin (под 950) их не прочитают. → PUID=950 у transmission всё же нужен для цепочки. (Обход с setgid-битом на dir + group 950 возможен как fallback, не выбран.) - - **Статус:** ждёт ок Alex на `docker rm -f transmission`. -- ⬜ **Этап 3 — рекурсивный фикс прав вглубь** (root → выполняет Alex, масштаб ~257k+ файлов): рекурсивно вернуть владельца 950:950 + снять 0000 на файлах/папках (`find ... -exec chown -R 950:950 {} +`, `chmod u+rw,g+r` для файлов, `u+rwX,g+rwX` для каталогов). Или через UI `Apply recursively`. +- ✅ **Этап 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---`). ✅ + - **ЕЩЁ НЕ ДОБИТО (остаточек):** `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 + прочее + +Команда подготовлена в сессии, Alex ещё не запускал: + +```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 по решению. + +### После остаточного фикса +- **На маке**: `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/*`). ### Точное содержание transmission compose (оригинал, важно для пересоздания) ```yaml diff --git a/family/how-to/arr-stack-taiga.md b/family/how-to/arr-stack-taiga.md index ad4a3b04..3688baa9 100644 --- a/family/how-to/arr-stack-taiga.md +++ b/family/how-to/arr-stack-taiga.md @@ -20,6 +20,8 @@ Secondary arr stack on Taiga (TrueNAS), added 2026-05-20. > **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`. > **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`. ## Notes from Setup (2026-05-20)