139 lines
11 KiB
Markdown
139 lines
11 KiB
Markdown
---
|
||
tags: [truenas, restore, incident, git, media, arr, permission]
|
||
created: 2026-09-02
|
||
status: 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 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-файла на пути нет. Не связано с поломкой прав; ручной фикс только по запросу.
|
||
|
||
---
|
||
|
||
## Общий план (ИСПРАВЛЕН — НЕ выполнен, требует подтверждения)
|
||
|
||
> ⚠️ **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
|
||
|
||
```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_<дата>/<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`):
|
||
```bash
|
||
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.
|
||
|
||
## Связанные заметки
|
||
- [[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`)
|