Files
obsidian-vault/family/documents/vault-sync/2026-09-02-restore-privilege-scope.md
T

11 KiB
Raw Blame History

tags, created, status
tags created status
truenas
restore
incident
git
media
arr
permission
2026-09-02 diagnosed

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 listcom.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-файла на пути нет. Не связано с поломкой прав; ручной фикс только по запросу.

Общий план (ИСПРАВЛЕН — НЕ выполнен, требует подтверждения)

⚠️ 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).

Диагноз по 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

# 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:

# скопировать на 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_<дата>/<name>.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):
    midclt call filesystem.setacl <path> \
      '{"uid":950,"gid":950,"dacl":[<эталон-ACE obsidian>],"options":{"recursive":true,"traverse":true,"stripacl":false}}'
    
  3. Verify: все каталоги → uid 950; тест git --git-dir=<base>/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.

Связанные заметки