[2026-09-22] eagle: family/documents/vault-sync/2026-09-21-bare-repo-push-permission-denied.md personal/tech/lampac-torrserver.md personal/tech/truenas-nfs4-acl-and-arrmultiuser.md
This commit is contained in:
1 parent
067ba8cf82
commit
2ee754f1a9
3 files changed
+92
-5
No files matched your search
@@ -3,7 +3,7 @@ title: "2026-09-21 — bare repo push Permission denied (root-owned objects/XX)"
|
||||
aliases: [2026-09-21-vault-bare-repo-acl, push permission denied objects]
|
||||
tags: [family, vault-sync, incident, truenas, acl, git, midclt]
|
||||
created: 2026-09-21
|
||||
updated: 2026-09-21
|
||||
updated: 2026-09-22
|
||||
type: incident
|
||||
namespace: family
|
||||
---
|
||||
@@ -11,6 +11,11 @@ namespace: family
|
||||
# 2026-09-21 — bare repo push: `Permission denied` на `objects/XX`
|
||||
|
||||
> **Итог:** push починен, **права поставлены с наследованием** (`FILE_INHERIT`+`DIRECTORY_INHERIT`), чтобы дефект не возвращался. Root-пароль на TrueNAS не потребовался — всё через `midclt` API. Полный рецепт: `personal/tech/truenas-nfs4-acl-and-arrmultiuser.md` §«Durable fix with INHERITANCE».
|
||||
>
|
||||
> 🔴 **РЕЦИДИВ 2026-09-22** — дефект вернулся (35 root-каталогов), наследование не защитило.
|
||||
> Плюс важный урок: **собирать dacl «с нуля» нельзя** — TrueNAS требует поле `id` в
|
||||
> каждой ACE, работает только read-modify-write. См. раздел «РЕЦИДИВ 2026-09-22» ниже.
|
||||
> **Статус: ОТКРЫТ** (синк сломан, фикс v2 готов но не применён).
|
||||
|
||||
## Симптом
|
||||
|
||||
@@ -86,9 +91,73 @@ git rev-parse HEAD; git rev-parse nas/main # оба 3b923d3
|
||||
> `git push` доказал, что *текущее* дерево синхронно, но **не** что свежий root-владельческий объект реально записывается.
|
||||
> Определяющий тест остаётся открытым — см. «Remaining» ниже.
|
||||
|
||||
## 🔴 РЕЦИДИВ 2026-09-22: дефект вернулся + моя первая починка упала
|
||||
|
||||
**Симптом тот же** (push 4 коммитов с Mac):
|
||||
```
|
||||
error: unable to write file ./objects/28/fe1cb94d…: Permission denied
|
||||
error: unable to write file ./objects/d1/cb38b336…: Permission denied
|
||||
! [remote rejected] main -> main (unable to migrate objects to permanent storage)
|
||||
```
|
||||
|
||||
**Замер:**
|
||||
```
|
||||
root-owned записей в objects/ : 98 (35 каталогов objects/XX + объекты внутри)
|
||||
root-owned refs/heads/main : тоже root
|
||||
write-тест: touch objects/28/.wrtest → Permission denied
|
||||
write-тест: touch objects/d1/.wrtest → Permission denied
|
||||
```
|
||||
|
||||
→ **Наследование, поставленное 2026-09-21, НЕ защитило.** Причина та же: root-инстанс
|
||||
`mcpvault` продолжает писать от root и создавать новые `objects/XX/` от root. Даже
|
||||
если ACL родителя корректен, свежий root-owned каталог может прийти с режимом
|
||||
`drwxr-sr-x` (группа без `w`) — запись для uid 950 блокируется.
|
||||
|
||||
### 🔴 Что НЕ сработало (моя ошибка — стоила полного провала запуска)
|
||||
|
||||
Наивный dacl с нуля — собрать ACE заново `{tag, type, perms, flags}` **без поля `id`**:
|
||||
|
||||
```python
|
||||
{"tag": "owner@", "type": "ALLOW", "perms": {...}, "flags": {...}} # ← нет "id"
|
||||
```
|
||||
|
||||
→ TrueNAS отклонил **КАЖДЫЙ** каталог:
|
||||
|
||||
```
|
||||
[EINVAL] filesystem_acl.dacl.0: ACL entry is missing required keys(s): {'id'}
|
||||
[EINVAL] filesystem_acl.dacl.1: ACL entry is missing required keys(s): {'id'}
|
||||
... (245 каталогов, 0 успешных)
|
||||
```
|
||||
|
||||
🔴 **Вывод: `id` — обязательное поле ACE в TrueNAS.** Собирать dacl «с нуля» нельзя.
|
||||
Работает только **read-modify-write**: взять ACL через `getacl` (там `id` уже
|
||||
проставлен TrueNAS) и **править в нём только `perms`/`flags`**, сохраняя `id` как есть.
|
||||
|
||||
Сравнение с прошлым успехом (2026-09-21, 291 каталог, 0 ошибок): там
|
||||
`options.stripacl: false` + **`cur["acl"]` переданный обратно** — то есть именно
|
||||
read-modify-write. Мой «с нуля» вариант был отклонением от рабочего рецепта.
|
||||
|
||||
**Рабочая схема (v2, скрипт `fix_vault_acl2.py`):**
|
||||
```python
|
||||
cur = getacl(path) # голая строка пути
|
||||
dacl = patch_acl(cur) # правим ТОЛЬКО perms/flags, 'id' не трогаем
|
||||
setacl({"path": path, "dacl": dacl,
|
||||
"options": {"recursive": False, "traverse": True, "stripacl": False}})
|
||||
# затем поллить core.get_jobs до SUCCESS
|
||||
```
|
||||
|
||||
⚠️ Статус: скрипт v2 написан, но **не залит и не запущен** — Alex поставил
|
||||
задачу «сначала доки, потом чинить синк». Верификация записи (`touch`) не выполнялась.
|
||||
|
||||
## Remaining (открытые вопросы)
|
||||
|
||||
1. ~~**Наследование не проверено на практике**~~ — **проверено 2026-09-21 15:05 UTC** (read-only с Taiga), см. раздел «Верификация наследования» ниже. Наследование работает.
|
||||
0. 🔴 **2026-09-22 РЕЦИДИВ НЕ УСТРАНЁН.** Синк сломан, push с Mac падает. Кол-во root-каталогов
|
||||
вернулось (35). Фикс v2 (`/tmp/fix_vault_acl2.py` на Mac, read-modify-write) **написан, но не
|
||||
залит и не запущен** — Alex: «сначала доки, потом чинить синк».
|
||||
**Порядок возобновления:** `scp` скрипта на TrueNAS → запуск → проверка `touch` в
|
||||
`objects/XX` → `git push nas main`. Скрипт v1 (`fix_vault_acl_inherit.py`) **нерабочий**,
|
||||
удалить/не использовать (`[EINVAL] … missing required keys(s): {'id'}`).
|
||||
1. ~~**Наследование не проверено на практике**~~ — **проверено 2026-09-21 15:05 UTC** (read-only с Taiga), см. раздел «Верификация наследования» ниже. Наследование работает **на тот момент**; 2026-09-22 показал, что от рецидива оно НЕ спасает.
|
||||
2. **`mcpvault` продолжает работать от root** — пока он root, дефект может вернуться. Профилактика: перезапустить его под uid 950.
|
||||
3. **`cleanup` не видит `/media/movies`** — на Кра́кене удаляются только Radarr-файлы; просмотренное лежит в `/media/movies`, диск будет расти. Отдельная задача (см. `family/plans/watchlist-disk-overflow-fix.md`).
|
||||
|
||||
|
||||
Reference in new issue
Block a user