diff --git a/family/how-to/red2tb-dataset-map.md b/family/how-to/red2tb-dataset-map.md index 8d597fcd..68c6002e 100644 --- a/family/how-to/red2tb-dataset-map.md +++ b/family/how-to/red2tb-dataset-map.md @@ -70,3 +70,38 @@ ## Ссылки - Связанные: [[truenas-sata-ports-and-zfs-pools]] (план спасения/пересоздания), [[truenas-access]] (общие данные доступа). + +## 🔑 Кто «владелец» Edu — группы и uid на TrueNAS (2026-09-23) + +**Датасет `Edu` (214 ГБ) НЕ имеет единого владельца** — внутри лежат файлы разных uid, и ACL наследует `uid 0 / gid 0`: + +| Путь | Владелец | Режим | `everyone@` | +|---|---|---|---| +| `Edu` | `root:root` | `drwxrwxr-x` | `READ_DATA`+`EXECUTE` | +| `Edu/Маскелиаде` | `root:root` | `drwxrwx---` | только аттрибуты | +| `Edu/Книги, учебники`, `Edu/sponsr.ru-uroki-istorii` | `nas:nas` / `nas:nas_users` | `drwxrwx---` | — | +| `Edu/*.mp4` (Маскелиаде) | `root:root` | `-rwxrwx---` | — | +| `Edu/PointFree`, `Edu/library`, `Edu/mallexxx` | `mallexxx:root` | `drwxrwx---` | — | + +> ⚠️ ACL у датасета `trivial: true` (это чистый POSIX-эквивалент, без DENY-ACE) — но `group@` = **gid 0**, +> поэтому он не даёт доступа никому, кроме root. **Это и есть причина «нет доступа» у любых не-root юзеров.** + +**Группы (факт, `id truenas_admin` + `getent group`):** +``` +truenas_admin uid=950 gid=950 groups=950,544(builtin_administrators),921(transmission),999(docker),1000(nas),3000(nas_users) +root uid=0 gid=0 groups=0(root) +nas uid=? gid=1000 (группа nas:x:1000:truenas_admin) +mallexxx uid=? gid=1001 +nas_users gid=3000 → root, truenas_admin, mallexxx, nas, transmission +builtin_administrators gid=544 → root, truenas_admin +``` + +> 🔑 **Для ACL-фиксов на `Edu` (и вообще на этом пуле) использовать группу `nas_users` (gid 3000)** — +> одна ACE покрывает админа, `nas`, `mallexxx` и transmission сразу. Вариант-альтернатива — `builtin_administrators` (gid 544). +> +> 🔴 **`truenas_admin` НЕ root и НЕ в группе 0.** Любой файл/каталог `root:root` + `rwxrwx---` для него закрыт. +> Это НЕ поломка ФС и НЕ повод лезть в ACL — сначала посчитать `owner/group/other` против его groups. +> +> **Применённый план (2026-09-23, согласован, не выполнен):** рекурсивно по `Edu` — владелец-группа `nas_users`, +> ACE `group@` с `flags.BASIC: INHERIT` (read-modify-write, сохраняя `id`; `stripacl` НЕ использовать). +> Детали и подводные камни — [[truenas-infrastructure]] § «WebDAV — устройство и разбор … Edu/Маскелиаде». diff --git a/family/how-to/truenas-infrastructure.md b/family/how-to/truenas-infrastructure.md index 6aac4cec..db52ef42 100644 --- a/family/how-to/truenas-infrastructure.md +++ b/family/how-to/truenas-infrastructure.md @@ -262,7 +262,63 @@ arr, caddy, cups, filebrowser, gitea, hermes, immich, inpx-web, inpxer, library, **⚠️ НЕТ compose-файла — только конфиг (восстанавливать вручную, параметры из доки ниже):** - ~~**ha** — Home Assistant: `/mnt/RED_2TB/docker/ha/` (automations.yaml)~~ → 🔴 **ПОГАШЕН 2026-09-14.** Папка **сохранена как ЭТАЛОН конфига** (`configuration.yaml`, modbus-блок построчно идентичен t610, 32 заслонки) — **не удалять**. -- **webdav** — `/mnt/RED_2TB/docker/webdav/` (config.yml). Образ `hacdias/webdav:latest`, домен webdav.mallexxx.duckdns.org. ✅ активен (compose на самом деле есть, см. строку выше). +- **webdav** — `/mnt/RED_2TB/docker/webdav/` (`config.yml` + `docker-compose.yml`). Образ `hacdias/webdav:latest`, домен `webdav.mallexxx.duckdns.org`. ✅ активен. + +### 🌐 WebDAV — устройство и разбор «нет доступа к Edu/Маскелиаде» (2026-09-23) + +**Устройство (проверено live):** + +| Параметр | Значение | +|---|---| +| Образ | `hacdias/webdav:latest` | +| `docker-compose.yml` | `/mnt/RED_2TB/docker/webdav/docker-compose.yml` (`root:root`) | +| bind-mount | `/mnt/RED_2TB:/data` (rw) + `./config.yml:/config.yml` | +| сеть | `caddy_default` (**external: true**) | +| процесс | **UID 0 (root)** — `docker top webdav` → `root … webdav --config /config.yml`. `Config.User` пустой. | +| auth | `auth: true`, юзер `webdav` / пароль в `config.yml`, `permissions: CRUD` | +| `directory` | `/data` (то есть весь пул) | +| вход | Caddy `webdav.mallexxx.duckdns.org` → `reverse_proxy webdav:80` (`transport http { versions 1.1 }`) | + +> 🔴 **ГЛАВНЫЙ ВЫВОД: WebDAV работает под root, поэтому NFSv4 ACL его НЕ блокирует.** +> Root + `owner@ ALLOW` → контейнер читает/пишет весь `/data`. **«Нет доступа к папке через WebDAV» ≠ «ACL мешает WebDAV»** — сначала проверить uid процесса (`docker top`), а не ACL. + +**Симптом (2026-09-23):** нет доступа к `Edu/Маскелиаде` — и через WebDAV, и по ssh от `truenas_admin`. + +**Разбор по сырью (`ls -la` + `midclt filesystem.getacl`):** + +1. `/mnt/RED_2TB/Edu` = `root:root`, `drwxrwxr-x`, ACL `trivial: true`, `uid 0 / gid 0`. +2. `/mnt/RED_2TB/Edu/Маскелиаде` — `root:root`, `drwxrwx---`, ACL `trivial: true`. `owner@ ALLOW` полный, `group@ ALLOW` полный, но **`everyone@` = только `READ_ATTRIBUTES`/`READ_ACL`** (нет `READ_DATA`, нет `EXECUTE`). +3. **`Маскелиаде` — ПУСТАЯ папка** с 31.05.2026 (внутри только `.`/`..`). `find -iname "*askeli*"` по пулу → пусто. +4. Реальный объект, к которому нужен доступ — **файл в `Edu`, не в `Маскелиаде`**: `Антон Маскелиаде - Первый набросок Ableton.mp4`, 136 МБ, `root:root`, `-rwxrwx---`, 26.05.2026. +5. `Edu` держит файлы **разных владельцев** (`root`, `mallexxx`, `nas:nas_users`) — единого «владельца Edu» нет. То же и по ACL: `group@` = **gid 0**, а группы, в которой реально есть все нужные юзеры, там нет вовсе. + +**Почему `truenas_admin` не имеет доступа (арифметика прав):** +`truenas_admin` = `uid 950, gid 950, groups=950,544(l builtin_administrators),921(transmission),999(docker),1000(nas),3000(nas_users)`. +Для файла `root:root` `rwxrwx---`: owner = root → не он; group = **gid 0** → его в группе 0 **нет**; `everyone@` = только атрибуты. ⇒ **доступ закрыт**. Симметрично и для папки. +> ⚠️ Поэтому «файл не читается от `truenas_admin`» — это **нормальное следствие gid 0**, а не поломка FS. + +**🔑 Ключевое открытие для ACL-фикса: группа `nas_users` (gid 3000).** +``` +nas_users:x:3000:root,truenas_admin,mallexxx,nas,transmission +``` +Одна ACE на эту группу покрывает сразу всех потребителей (админ, `nas`, `mallexxx`, transmission) — вместо россыпи персональных ACE. Альтернатива: `builtin_administrators` (gid 544, `root,truenas_admin`). + +**План фикса (согласован, НЕ выполнен на 2026-09-23) — из 3 шагов:** +1. Бэкап ACL (ничего не меняет): + ```bash + midclt call filesystem.getacl /mnt/RED_2TB/Edu > /mnt/RED_2TB/storage/acl-edu-before-$(date +%Y%m%d-%H%M%S).json + ``` +2. Рекурсивно: владелец-группа = `nas_users`, ACE `group@` с **`flags.BASIC: INHERIT`** — через **read-modify-write** (`getacl` → правим `perms`/`flags` → `setacl`), **сохраняя `id`** каждого ACE. Строить `dacl` с нуля **нельзя** → `[EINVAL] ACL entry is missing required keys(s): {'id'}`. `stripacl:true` **не** использовать (не сносит DENY, ломает наследование). `options: {recursive: true, traverse: true}`. +3. Проверка: `touch` в `Edu/Маскелиаде` от `truenas_admin` + создать новый каталог → `getacl` должен показать `INHERITED: true`. + `setacl` **асинхронен** — поллить `core.get_jobs` до `SUCCESS`, иначе читаешь старые флаги и получаешь ложный «failure». + +**Развилка, которую нужно подтвердить перед выполнением:** `nas_users` (gid 3000) vs `builtin_administrators` (gid 544); и подтверждение рекурсии по всему `Edu` (~214 ГБ). + +> ⚠️ **Побочный вывод (применим не только к Edu):** кириллица в путях (`Edu/Маскелиаде`) валит `tirith` как `confusable_text` (**HIGH**, MITRE T1036.005) → команда блокируется, апрув не помогает. Предложено переименовать `Маскелиаде` → `Maskeliade`. При работе с такими путями — передавать путь как **один shell-quoted аргумент**, не разбивать по строкам. +> +> ⚠️ `curl`/`wget`-проверка WebDAV **с Mac не проходит** — сеть `caddy_default` живёт только внутри Docker на TrueNAS (`docker network ls` её видит, хост-macOS — нет). Проверять из контейнера на TrueNAS: `docker run --rm --network caddy_default curlimages/curl … PROPFIND -u webdav:… http://webdav:80/Edu/`. +> +> ⚠️ Контейнер `hacdias/webdav` — **distroless**: внутри нет `ls`, `ps`, `cat`, `id` (все `exec` валятся с `executable file not found in $PATH`). Диагностику делать снаружи (`docker inspect`, `docker top`, `ls` на хосте). - ~~**modbus-bridge** — `/mnt/RED_2TB/docker/modbus-bridge/`~~ → 🔴 **ПОГАШЕН 2026-09-14** (`Exited (0)` с 14.09 01:59 — узел `/dev/ttyZONT` исчез). Папка цела. - ~~**zigbee2mqtt** — `/mnt/RED_2TB/docker/zigbee2mqtt/`~~ → 🔴 **ПОГАШЕН 2026-09-14** (`Exited (2)` — координатор на t610). - ~~**homeassistant** — папка `docker/homeassistant/`~~ → **ПУСТАЯ и не использовалась**; рабочая была `ha/` (см. выше).