[2026-09-26] eagle: family/documents/vault-sync/2026-09-26-syncthing-clone-root-objects-acl-confusion.md family/how-to/vault-git-sync.md personal/plans/balda-mm-phase4-agents.md personal/tech/docker_colima_setup.md personal/tech/macos-docker-virtiofs-mount-limits.md personal/tech/truenas-nfs4-acl-and-arrmultiuser.md
This commit is contained in:
1 parent
8efe5c8970
commit
f482778257
6 files changed
+330
-25
No files matched your search
@@ -0,0 +1,144 @@
|
||||
---
|
||||
title: obsidian-syncthing — root-owned objects + битый remote + путаница ACL/chown
|
||||
type: log
|
||||
namespace: family
|
||||
tags: [vault, sync, syncthing, git, permissions, acl, nfsv4, root]
|
||||
date: 2026-09-26
|
||||
---
|
||||
|
||||
# `obsidian-syncthing`: 4031 root-объект, битый remote, ACL/chown не стоит
|
||||
|
||||
**Когда:** 2026-09-26, разбор по запросу Alex «почему документ не доехал до телефона».
|
||||
**Статус:** диагностика завершена, **фиксы НЕ применены** — ждём решения Alex.
|
||||
|
||||
## Симптом
|
||||
|
||||
Нота `personal/plans/music-tags-review/1-needs-decision.md` закоммичена и запушена с Mac
|
||||
(`66d4d62..f2501dc main -> main`), но в клон `/obsidian-syncthing` на TrueNAS **не попала**.
|
||||
`git pull` в клоне падает, а `sync-vault.sh` глушит ошибку (`2>/dev/null`) — синк выглядит
|
||||
успешным.
|
||||
|
||||
## Две независимые поломки
|
||||
|
||||
### 1. Битый remote в клоне (починено в этой сессии)
|
||||
|
||||
```
|
||||
было: origin /vault.git ← потерян префикс пути
|
||||
стало: origin /mnt/RED_2TB/storage/git/obsidian-vault.git
|
||||
```
|
||||
|
||||
`git fetch` при этом падал с `fatal: '/vault.git' does not appear to be a git repository`.
|
||||
Remote переписан через `git remote set-url`. **Это не связано с правами** — отдельный дефект.
|
||||
|
||||
### 2. Права: новые объекты пишет root (НЕ починено)
|
||||
|
||||
```
|
||||
объекты от root: 4051 ← свежие, 2026-09-26 02:42
|
||||
объекты от truenas_admin: 4 ← только старые pack с 2026-07-06
|
||||
```
|
||||
|
||||
`git fetch` падает на записи:
|
||||
|
||||
```
|
||||
error: insufficient permission for adding an object to repository database .git/objects
|
||||
fatal: failed to write object
|
||||
fatal: unpack-objects failed
|
||||
```
|
||||
|
||||
**Причина:** контейнер `hermes-taiga` работает **от root** (`docker inspect` → `Config.User`
|
||||
пусто, `docker exec ... id` → `uid=0(root)`). Именно он делает `git pull` в
|
||||
`/obsidian-syncthing` — значит каждый новый loose-объект рождается `root:root`, а git под
|
||||
`truenas_admin` (uid 950) писать в них не может.
|
||||
|
||||
## ACL на `obsidian-syncthing` НЕ СТОИТ — `trivial_acl: true`
|
||||
|
||||
```
|
||||
nfs4xdr_getfacl /mnt/RED_2TB/storage/obsidian-syncthing
|
||||
# owner: 950 # group: 950 # mode: 0o40770
|
||||
# trivial_acl: true ← расширенного ACL нет
|
||||
owner@:rwxpD-aARWcCos:-------:allow
|
||||
group@:rwxpD-a-R-c--s:-------:allow
|
||||
everyone@:------a-R-c--s:-------:allow
|
||||
```
|
||||
|
||||
Только дефолтный набор TrueNAS (`owner@` / `group@` / `everyone@`), **ни одной именованной
|
||||
записи**. POSIX-вид (`getfacl`) показывает `user::rwx group::rwx other::---` и **скрывает**
|
||||
отсутствие расширенного ACL — поэтому диагностировать надо `nfs4xdr_getfacl`, а не `getfacl`.
|
||||
|
||||
## 🔴 Путаница: ACL ставился на `Edu`, не на `obsidian-syncthing`
|
||||
|
||||
Alex помнил, что фикс ACL уже делался («ты вроде ставил рекурсивный acl а не chown»).
|
||||
Проверка по базе Hermes (`state.db`, таблица `messages`) нашла сессию
|
||||
**`20260923_124118_9e70782e` (2026-09-23)** — там рекурсивный ACL **действительно ставился**,
|
||||
но на **`/mnt/RED_2TB/Edu`**, по прямой просьбе Alex: «ты можешь просто группу под acl
|
||||
сделать с inherit чтобы весь edu был доступен группе включающей truenas_admin?»
|
||||
|
||||
Что тогда было сделано (и сработало — на `Edu`):
|
||||
|
||||
```bash
|
||||
# 1. бэкап ACL
|
||||
midclt call filesystem.getacl /mnt/RED_2TB/Edu > .../acl-edu-before-YYYYmmdd-HHMMSS.json
|
||||
# 2. setacl recursive: gid -> 3000 (nas_users) + INHERIT на всех ACE → job SUCCESS
|
||||
# 3. chgrp -R nas_users → FAILED (Operation not permitted)
|
||||
# 4. повтор через midclt setacl с uid/gid=3000 → job 15393 SUCCESS
|
||||
```
|
||||
|
||||
Результат на `Edu`: `drwxrwxr-x root:nas_users`, `gid=3000`, все ACE `INHERITED: True`,
|
||||
`touch` → WRITE_OK. **Группа `nas_users` (gid 3000)** — рабочая: в ней `truenas_admin`,
|
||||
`mallexxx`, `nas`, `root`, `transmission`.
|
||||
|
||||
> ⚠️ **Урок: «ACL уже ставили» ≠ «ACL стоит на этой папке».** Правка была на `Edu`.
|
||||
> На `obsidian-syncthing` расширенного ACL **не было никогда** (`trivial_acl: true` доказывает).
|
||||
> Прежде чем повторять «известный фикс» — проверить, что он на **той самой** папке.
|
||||
|
||||
> 🔴 **`chgrp` от `truenas_admin` даёт `Operation not permitted`.** В NFSv4 `group@` — это
|
||||
> POSIX-gid файла, а не ACE. Без смены gid группа не получает ничего. Менять gid надо через
|
||||
> `midclt filesystem.setacl` (root-контекст), а не `chgrp`/`chown` из шелла.
|
||||
|
||||
## Почему однократный `chown` не лечил
|
||||
|
||||
Прошлый разовый `chown` объектов на `truenas_admin` чинил только **уже существующие** объекты.
|
||||
Следующий `git pull` от root снова рождал root-owned объекты — и `chown` приходилось повторять.
|
||||
**Это лечение симптома.** Перманентный фикс — либо `ACL + INHERIT` (новые объекты наследуют
|
||||
права группы), либо запуск синка **не от root** (`user: "950:950"` в taiga service).
|
||||
|
||||
## Что предлагается (решение за Alex)
|
||||
|
||||
| Вариант | Как | Плюс / минус |
|
||||
|---|---|---|
|
||||
| **A. ACL + INHERIT** | `setfacl`/`midclt setacl` с `g:truenas_admin:rwx` + `d:` (default) + `chmod g+s` | root и uid 950 пишут одновременно; нужен контроль, что TrueNAS не сбросит ACL при операциях датасета |
|
||||
| **B. Контейнер не от root** | `user: "950:950"` в taiga service `/mnt/RED_2TB/docker/hermes/docker-compose.yml` | устраняет корень; риск — образ может требовать root для `/opt/data` |
|
||||
| **C. Повторный `chown`** | перед каждым pull | НЕ рекомендуется — лечит симптом |
|
||||
|
||||
## Сопутствующий дефект: скрипт глушит ошибки
|
||||
|
||||
`sync-vault.sh` / `sync-vault-lib.sh` вызывают `git fetch` и `git merge` с `2>/dev/null`.
|
||||
При падении синк рапортует **«Pushed ✓» / exit 0**, хотя pull не прошёл. Это и скрывало
|
||||
поломку. Предложение — убрать `2>/dev/null` с `fetch`/`merge`, чтобы падение было видно в логе
|
||||
(та же логика, что уже описана для launchd: `exit code 0` ≠ «синк прошёл»).
|
||||
|
||||
## Диагностика (воспроизвести)
|
||||
|
||||
```bash
|
||||
# владельцы объектов в клоне
|
||||
ssh truenas_admin@mallexxx.duckdns.org \
|
||||
"cd /mnt/RED_2TB/storage/obsidian-syncthing && find .git/objects -type f -printf '%u\n' | sort | uniq -c"
|
||||
|
||||
# реальный ACL (NFSv4, не POSIX!)
|
||||
nfs4xdr_getfacl /mnt/RED_2TB/storage/obsidian-syncthing # trivial_acl: true?
|
||||
|
||||
# под кем реально работает контейнер
|
||||
docker inspect hermes-taiga --format '{{.Config.User}}' # пусто => root
|
||||
docker exec hermes-taiga id # uid=0(root)
|
||||
|
||||
# remote клона
|
||||
cd /mnt/RED_2TB/storage/obsidian-syncthing && git remote -v
|
||||
```
|
||||
|
||||
## Связанные документы
|
||||
|
||||
- `family/how-to/vault-git-sync.md` — архитектура и питфоллы синка
|
||||
- `family/documents/vault-sync/2026-09-21-bare-repo-push-permission-denied.md` — тот же
|
||||
root-инстанс Hermes, но на **bare repo**
|
||||
- `family/documents/vault-sync/2026-09-26-mode-flip-644-755.md` — шум прав от Syncthing
|
||||
- `personal/tech/truenas-administration` (skill) — NFSv4 ACL через `midclt`
|
||||
@@ -25,6 +25,21 @@ tags:
|
||||
> реальная доставка до телефона — в пределах тика. Перезапись `schedule_display` через
|
||||
> `hermes cron edit 29851c413903 --schedule '*/5 * * * *'` — на решение Алексея (косметика, на исполнение не влияет).
|
||||
|
||||
> **🔴 STATE 2026-09-26 (later) — `obsidian-syncthing` НЕ получает обновления: root-owned objects + битый remote.**
|
||||
> Нота `1-needs-decision.md` была запушена с Mac (`66d4d62..f2501dc`), но в клон
|
||||
> `/obsidian-syncthing` **не доехала**. Два независимых дефекта:
|
||||
> **(1)** `origin` в клоне был **`/vault.git`** (потерян префикс пути) → `git fetch` падал
|
||||
> `does not appear to be a git repository`. Переписан на полный путь `git remote set-url`.
|
||||
> **(2)** **4051 из 4055 объектов принадлежат `root`** — контейнер `hermes-taiga` работает от
|
||||
> root (`Config.User` пусто, `id` → `uid=0`), он и делает pull → новые объекты root-owned,
|
||||
> git под uid 950 не может писать (`insufficient permission for adding an object`).
|
||||
> **ACL на `obsidian-syncthing` НЕ СТОИТ** — `nfs4xdr_getfacl` показывает `trivial_acl: true`
|
||||
> (только `owner@`/`group@`/`everyone@`, ни одной именованной записи). Рекурсивный ACL с группой
|
||||
> ставился ранее (2026-09-23), но на **`/mnt/RED_2TB/Edu`**, не на эту папку.
|
||||
> 🔴 **Урок: «ACL уже ставили» ≠ «ACL стоит на этой папке» — проверять фактом.**
|
||||
> Разовый `chown` лечит только уже существующие объекты; следующий pull от root возвращает дефект.
|
||||
> Фиксы НЕ применены. Подробно: `family/documents/vault-sync/2026-09-26-syncthing-clone-root-objects-acl-confusion.md`.
|
||||
>
|
||||
> **🔴 STATE 2026-09-26 — РАСХОЖДЕНИЕ РАСПИСАНИЯ: Taiga-сервер синкается РАЗ В ЧАС, не 5 минут.**
|
||||
> Job `sync-vault` внутри контейнера `hermes-taiga` (Hermes cron, id `29851c413903`) расписан
|
||||
> **`0 * * * *`** — то есть раз в час, **хотя таблица ниже (и `family/how-to/obsidian-sync`)
|
||||
@@ -200,6 +215,12 @@ cd ~/Developer/vault-sync-test && bash test-sync.sh
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **`nfs4xdr_getfacl`, а НЕ `getfacl`, если проверяешь наличие расширенного ACL** (2026-09-26). POSIX-вид (`getfacl`, `ls -l`) показывает `user::rwx group::rwx` и **скрывает** отсутствие именованных ACE. Только `nfs4xdr_getfacl` печатает `trivial_acl: true` — что значит «кастомного ACL нет». Все диагностики прав на TrueNAS начинать с него.
|
||||
- **`chgrp` / `chown` от `truenas_admin` → `Operation not permitted`** (2026-09-26). В NFSv4 `group@` — это POSIX-gid файла, а не ACE: без смены gid группа не получает доступа. Менять gid/uid только через `midclt filesystem.setacl` (root-контекст). TrueNAS `sudo` требует пароль (в отличие от Kraken, где `sudo -n` работает).
|
||||
- **Разовый `chown` — лечение симптома, не фикс** (2026-09-26). Если root-процесс продолжает писать в папку, root-owned объекты вернутся на следующем же запуске. Перманентно лечит только `ACL`+`INHERIT` (наследование новыми объектами) либо запуск процесса **не от root**.
|
||||
- **«Этот фикс уже делали» — проверить, что он на ТОЙ САМОЙ папке** (2026-09-26). Рекурсивный ACL с группой `nas_users` ставился 2026-09-23, но на `/mnt/RED_2TB/Edu`. На `obsidian-syncthing` ACL не было никогда. Каждый «известный фикс» верифицировать фактом на целевом объекте, а не памятью. Искать прошлые сессии: `sqlite3 ~/.hermes/hermes-whale/state.db "SELECT session_id, substr(content,1,300) FROM messages WHERE content LIKE '%setfacl%' ORDER BY id DESC LIMIT 40;"`.
|
||||
- **Клон может иметь битый `origin`** (2026-09-26). `obsidian-syncthing` имел `origin = /vault.git` (потерян префикс пути) → `fatal: does not appear to be a git repository`. Проверять `git remote -v` в клоне до диагностики прав — это независимый дефект, который выглядит как проблема доступа.
|
||||
- **`sync-vault-lib.sh` глушит ошибки (`2>/dev/null` на fetch/merge)** → «Pushed ✓» / `exit 0` при фактически упавшем pull. Это уже второй раз, когда поломка синка была не видна в логе. Диагностировать по `git status`/`git log` в клоне, не по exit-code.
|
||||
- `git add pathspec` fails with `fatal: pathspec did not match any files` when a directory doesn't exist on disk — use `git add -A` instead
|
||||
- `git add -A` in sparse worktree still stages deletions of out-of-cone files tracked in index — need to unstage them (fixed in old script; irrelevant with proper clone)
|
||||
- `core.quotePath=true` (default) escapes Cyrillic paths in `git ls-files` output — use `-c core.quotePath=false`
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Фаза 4 — исполнитель на Mac + `~/agents` + секция «Agents» в Eagle Dashboard
|
||||
|
||||
> План. **Работа НЕ начата** (образ не собран, контейнер не запущен).
|
||||
> План. **Шаг 1 выполнен** (2026-09-26): образ собран, контейнер `balda-executor` Up (healthy),
|
||||
> `claude 2.1.283` + `codex 0.157.1` внутри, монтирования проверены в обе стороны.
|
||||
> ⏳ Осталось в шаге 1: логин CLI (нужен апрув на копирование auth-файлов).
|
||||
> Часть [[personal/projects/balda/balda-mm-delegation-plan]] (Фазы 4-5).
|
||||
> Предыдущее: [[personal/projects/balda/balda-kraken-mm-deploy]] (Фаза 3 ✅ — бот отвечает Alex).
|
||||
|
||||
@@ -15,6 +17,7 @@
|
||||
| 3 | Управление линками в `~/agents` | Новая секция «Agents» в Eagle Dashboard |
|
||||
| 4 | Auth CLI (claude/codex) | на хосте, `~/cli-auth`, **вне** `~/agents` |
|
||||
| 5 | Сеть Kraken → Mac | Cloudflare Tunnel (существующий cloudflared на Mac) |
|
||||
| 6 | Провайдер исполнителя (открытый п.1) | `claude` — оба CLI стоят в образе, переключение через `EXECUTOR_PROVIDER` в `.env` |
|
||||
|
||||
---
|
||||
|
||||
@@ -68,6 +71,13 @@ diff + тесты + коммит → Балда → Mattermost
|
||||
| Codex auth | `~/cli-auth/codex` | `/root/.codex` | 0700 |
|
||||
| OAuth-токен Claude | `~/Docker/balda-executor/.env` | env | 0600 |
|
||||
|
||||
📌 **Основной путь авторизации — не `claude setup-token`, а копия auth-файлов** из
|
||||
`~/.claude`/`~/.codex`. Токен в `.env` — запасной вариант для headless без монтирования.
|
||||
Выбранный вариант: копируются `~/.claude/.credentials.json` + `~/.claude/.claude.json` и
|
||||
`~/.codex/auth.json` + `~/.codex/config.toml`. Полные каталоги **не** копируются:
|
||||
`~/.codex` содержит ~640 МБ sqlite-логов/состояний (`logs_2.sqlite`, `state_5.sqlite`,
|
||||
`memories_1.sqlite`, `queue_1.sqlite`) — исполнителю не нужны, а вес и шум дают.
|
||||
|
||||
Пересборка образа и обновление CLI auth не сбрасывают. Токены вне `/agents` → агент их не видит.
|
||||
|
||||
---
|
||||
@@ -111,26 +121,77 @@ GET /api/agents/{name}/usage → размер
|
||||
|
||||
## 6. Шаги
|
||||
|
||||
### Артефакты, уже созданные на диске (2026-09-26)
|
||||
### ✅ Шаг 1 ВЫПОЛНЕН (2026-09-26)
|
||||
|
||||
Созданы **до** подтверждения плана — статус «черновик», при старте сверить и доделать:
|
||||
Артефакты на диске (все сверены и рабочие; черновики от 15:36 доведены до состояния «собрано и запущено»):
|
||||
|
||||
| Путь | Что |
|
||||
|---|---|
|
||||
| `~/agents` | рабочая область (drwxr-xr-x, `admin:staff`) |
|
||||
| `~/cli-auth/{claude,codex}` | auth CLI, 0700, **вне** `~/agents` |
|
||||
| `~/Docker/balda-executor/Dockerfile` | Node 24 + claude + codex + git, HEALTHCHECK |
|
||||
| `~/Docker/balda-executor/docker-compose.yml` | 4 тома, сеть `executor-net`, лимит 8G |
|
||||
| `~/Docker/balda-executor/.env` | ⏳ не создан (токен) |
|
||||
| Путь | Что | Состояние |
|
||||
|---|---|---|
|
||||
| `~/agents` | рабочая область (`admin:staff`) | ✅ монтируется в `/agents`, запись в обе стороны проверена |
|
||||
| `~/cli-auth/{claude,codex}` | auth CLI, 0700, **вне** `~/agents` | ✅ монтируются в `/root/.claude`, `/root/.codex` |
|
||||
| `~/Docker/balda-executor/Dockerfile` | `node:24-bookworm` + claude + codex + git + `tini` | ✅ исправлен (см. ниже) |
|
||||
| `~/Docker/balda-executor/docker-compose.yml` | 3 тома, сеть `executor-net`, `build:` | ✅ исправлен (см. ниже) |
|
||||
| `~/Docker/balda-executor/agents-mounts.yaml` | манифест внешних проектов (пустой список) | ✅ создан |
|
||||
| `~/Docker/balda-executor/tools/render-mounts.py` | генератор `compose.override.yaml` | ✅ создан, `--check` работает |
|
||||
| `~/Docker/balda-executor/compose.override.yaml` | **генерируется**, руками не править | ✅ сгенерирован |
|
||||
| `~/Docker/balda-executor/.env` | 0600, `EXECUTOR_PROVIDER=claude` | ✅ создан (без секретов) |
|
||||
|
||||
`docker-compose.yml` ссылается на `compose.override.yaml`, который генерирует
|
||||
`tools/render-mounts.py` из `agents-mounts.yaml` — **override вручную не править**.
|
||||
Ни образ не собран, ни контейнер не запущен.
|
||||
**Что уже работает (проверено):**
|
||||
```
|
||||
balda-executor Up (healthy) balda-executor:0.1.0
|
||||
claude → 2.1.283 (Claude Code)
|
||||
codex → codex-cli 0.157.1
|
||||
```
|
||||
`~/agents` ↔ `/agents` пишется в обе стороны; рестарт контейнера состояние сохраняет;
|
||||
auth-каталоги хоста видны внутри.
|
||||
|
||||
**1. `~/agents` + `~/cli-auth` + контейнер (~2 ч)**
|
||||
`mkdir ~/agents`, `~/cli-auth/{claude,codex}` 0700 → `~/Docker/balda-executor/Dockerfile`
|
||||
(Node 24 + claude + codex + git) → `docker-compose.yml` с 4 томами → `claude setup-token` в `.env` 0600 →
|
||||
проверка `claude --version`, `codex --version`, повторный `up -d` остаётся залогинен.
|
||||
#### 🔴 Три исправленных дефекта черновика (не повторять)
|
||||
|
||||
| Дефект | Симптом | Фикс |
|
||||
|---|---|---|
|
||||
| `env_file: .env` без файла | `docker compose up` падает на старте | `.env` создаётся **первым** шагом, 0600 |
|
||||
| Нет `compose.override.yaml` | `up` падает на монтировании несуществующего пути | `tools/render-mounts.py` запускается **до** `up` |
|
||||
| `FROM node:24-bookworm` без явных CA | — | `ca-certificates` + `update-ca-certificates` в Dockerfile (условие работы HTTPS у CLI) |
|
||||
|
||||
#### ⚠️ На macOS этой машины — `docker-compose`, НЕ `docker compose`
|
||||
|
||||
Docker CLI 29.4.1 + buildx как плагин (`~/.docker/cli-plugins/`), а compose — **отдельный бинарь**
|
||||
`/opt/homebrew/bin/docker-compose` (v5.1.3) с симлинком в `/opt/homebrew/lib/docker/cli-plugins/`.
|
||||
`docker compose` → `docker: unknown command: docker compose`; `docker compose config --quiet` →
|
||||
`unknown flag: --quiet`.
|
||||
|
||||
📌 **Все команды в этом проекте — через `docker-compose`**, включая `docker-compose config` (без `--quiet`).
|
||||
|
||||
#### Сборка образа (сработавшая команда)
|
||||
|
||||
```bash
|
||||
cd ~/Docker/balda-executor
|
||||
python3 tools/render-mounts.py --check # 0 записей, ошибок нет
|
||||
python3 tools/render-mounts.py # → compose.override.yaml
|
||||
docker-compose config --services # → executor (валидация)
|
||||
docker buildx build --builder arm64builder --platform linux/arm64 \
|
||||
--provenance=false --load -t balda-executor:0.1.0 .
|
||||
docker-compose up -d
|
||||
docker-compose restart # проверка переживания рестарта
|
||||
```
|
||||
|
||||
⚠️ Билдер — `arm64builder` (colima, `docker-container` driver). Дефолтный билдер
|
||||
(`default` → `/var/run/docker.sock`) в статусе `error` — не использовать.
|
||||
⚠️ `deploy.resources.limits.memory: 8G` из черновика **убран**: в не-swarm compose
|
||||
эта секция молча игнорируется, лимит создавал ложное ощущение защиты.
|
||||
|
||||
#### ⏳ Осталось в шаге 1: логин CLI (ждёт апрува)
|
||||
|
||||
`~/cli-auth/claude` пуст, в `~/cli-auth/codex` только `tmp/`. Копировать **только auth-файлы**,
|
||||
не целые каталоги (`~/.codex` ≈ 640 МБ служебных sqlite — агенту не нужны):
|
||||
|
||||
| CLI | Хост | Куда |
|
||||
|---|---|---|
|
||||
| claude | `~/.claude/.credentials.json`, `~/.claude/.claude.json` | `~/cli-auth/claude/` |
|
||||
| codex | `~/.codex/auth.json`, `~/.codex/config.toml` | `~/cli-auth/codex/` |
|
||||
|
||||
📌 В `~/cli-auth` кладётся **копия** (оригиналы на месте, `~/.claude` не переезжает):
|
||||
у агента-исполнителя свои токены, изолированные от рабочих. Права `~/cli-auth` = 0700.
|
||||
|
||||
**2. Мост (~3-4 ч)**
|
||||
`~/Developer/agents-bridge/`, FastAPI :8790, `POST /task` (idempotency), `GET /task/{id}`, `GET /healthz`;
|
||||
@@ -167,9 +228,11 @@ MCP-инструмент в Балде → `POST /task`; проба `echo ok > /
|
||||
|
||||
## 8. Открыто
|
||||
|
||||
1. Провайдер исполнителя — claude или codex
|
||||
2. Нужен ли `ask`-апрув в будущем
|
||||
3. Hostname для моста (`agents-bridge.qentra.top`?)
|
||||
1. ~~Провайдер исполнителя — claude или codex~~ → **claude** (оба в образе, переключение `EXECUTOR_PROVIDER`)
|
||||
2. ~~Нужен ли `ask`-апрув в будущем~~ → при `allow_all` не нужен; при потребности начинать с варианта B (апрув в мосте, ~0.5 дня)
|
||||
3. Hostname для моста (`agents-bridge.qentra.top`?) — ждёт шага 3
|
||||
4. ⏳ **Апрув на копирование auth-файлов CLI** в `~/cli-auth` — блокирует завершение шага 1
|
||||
5. Порт моста `8790` — проверено, свободен (`lsof -nP -i :8790`)
|
||||
|
||||
## Связанные заметки
|
||||
- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план (Фазы 4-5)
|
||||
|
||||
@@ -111,10 +111,21 @@ cat /tmp/colima.err
|
||||
|
||||
## 10. Docker usage
|
||||
|
||||
🔴 **Команда — `docker-compose`, а НЕ `docker compose`.** В homebrew-установке compose
|
||||
приезжает отдельным бинарём, не плагином, поэтому `docker compose …` падает с
|
||||
`docker: unknown command: docker compose` (выглядит как сломанный Docker — не сломан).
|
||||
Проверено 2026-09-26: CLI 29.4.1, compose 5.1.3.
|
||||
|
||||
``` bash
|
||||
docker-compose up -d # ✅
|
||||
docker-compose config # валидация (флага --quiet у этой версии НЕТ)
|
||||
docker compose up -d # ❌ unknown command
|
||||
```
|
||||
|
||||
Start containers:
|
||||
|
||||
``` bash
|
||||
docker compose up -d
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Check running containers:
|
||||
@@ -123,6 +134,9 @@ Check running containers:
|
||||
docker ps
|
||||
```
|
||||
|
||||
Подробнее про границы проброса путей в контейнер (virtiofs) и билдер arm64builder:
|
||||
[[tech/macos-docker-virtiofs-mount-limits]].
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
## Behavior
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
# macOS Docker Desktop — что НЕ проезжает в контейнер (virtiofs)
|
||||
|
||||
> Создан 2026-09-26. Статус: **проверено живыми тестами** (alpine:3.20, linux/arm64,
|
||||
> Docker Desktop на macOS 26.6.1, Apple Silicon).
|
||||
> **Colima** на macOS 26.6.1, Apple Silicon; `colima start --cpu 8 --memory 24 --disk 100`).
|
||||
> Тема: границы проброса путей из мира macOS в контейнер.
|
||||
> Все выводы получены прогонами, не по памяти. Команды воспроизведения — в §5.
|
||||
> Все выводы получены прогонами, не по памяти. Команды воспроизведения — в §6.
|
||||
|
||||
---
|
||||
|
||||
## 0. Главный вывод одной строкой
|
||||
|
||||
На macOS Docker Desktop отдаёт контейнеру файлы **не через Linux `mount`**, а через
|
||||
На macOS рантайм контейнеров (Colima, Docker Desktop) отдаёт контейнеру файлы
|
||||
**не через Linux `mount`**, а через
|
||||
**virtiofs** — демон, который строит маппинг путей **в момент старта контейнера**
|
||||
и знает только пути **мира macOS**, известные ему на старте.
|
||||
|
||||
@@ -160,6 +161,55 @@ ln /tmp/a /tmp/b # → Operation not permitt
|
||||
|
||||
---
|
||||
|
||||
## 8. ⚠️ Реализация на macOS: `docker-compose`, а не `docker compose`
|
||||
|
||||
Проверено 2026-09-26 на этой машине (Docker CLI 29.4.1, macOS 26.6.1, Apple Silicon).
|
||||
Compose здесь — **отдельный бинарь**, не подкоманда `docker`:
|
||||
|
||||
| Что | Значение |
|
||||
|---|---|
|
||||
| CLI | `/opt/homebrew/bin/docker` (v29.4.1) |
|
||||
| buildx | плагин, симлинк в `~/.docker/cli-plugins/docker-buildx` |
|
||||
| compose | `/opt/homebrew/bin/docker-compose` (**v5.1.3**), симлинк в `/opt/homebrew/lib/docker/cli-plugins/` |
|
||||
|
||||
```bash
|
||||
docker compose config # → docker: unknown command: docker compose
|
||||
docker compose config --quiet # → unknown flag: --quiet
|
||||
docker-compose config # ✅ работает
|
||||
docker-compose config --services
|
||||
```
|
||||
|
||||
📌 **Всегда `docker-compose` (с дефисом) в этом окружении.** Сообщение об ошибке
|
||||
выглядит как «docker не знает такой команды», а не «compose не установлен» — легко
|
||||
принять за сломанный Docker.
|
||||
|
||||
⚠️ Дефолтный билдер (`default` → `/var/run/docker.sock`) в статусе **`error`**.
|
||||
Для arm64-сборок использовать именованный билдер:
|
||||
```bash
|
||||
docker buildx build --builder arm64builder --platform linux/arm64 \
|
||||
--provenance=false --load -t <tag> .
|
||||
```
|
||||
|
||||
### Порядок файлов при генерации override
|
||||
|
||||
`compose.override.yaml` подхватывается compose **автоматически**, но если он ссылается на
|
||||
несуществующий путь на хосте, `up` падает на монтировании. Поэтому порядок строго такой:
|
||||
|
||||
```
|
||||
1. .env ← env_file, иначе up падает сразу
|
||||
2. agents-mounts.yaml ← манифест (можно пустой: mounts: [])
|
||||
3. tools/render-mounts.py ← → compose.override.yaml
|
||||
4. docker-compose up -d
|
||||
```
|
||||
|
||||
### Ловушка: `deploy.resources.limits` в не-swarm compose
|
||||
|
||||
Секция `deploy.resources.limits.memory` **молча игнорируется** запуском через
|
||||
`docker-compose up` (это формат swarm). Лимит создаёт ложное ощущение защиты —
|
||||
что-то ограничивать нужно иначе (cgroups напрямую или `mem_limit`, зависят от версии).
|
||||
|
||||
---
|
||||
|
||||
## Связанные заметки
|
||||
- [[personal/plans/balda-mm-phase4-agents]] — применение этих выводов (Фаза 4)
|
||||
- [[personal/projects/balda/balda-mm-delegation-plan]] — общий план проекта
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: TrueNAS NFS4 ACL repair + cross-container media PUID
|
||||
created: 2026-09-02
|
||||
updated: 2026-09-23
|
||||
updated: 2026-09-26
|
||||
type: tech
|
||||
namespace: personal
|
||||
tags: [truenas, nfs4, acl, midclt, arr, radarr, sonarr, jellyfin, transmission, docker, git]
|
||||
@@ -10,6 +10,7 @@ related:
|
||||
- "[[arr-stack-taiga]]"
|
||||
- "[[watchlist-disk-overflow-fix]]"
|
||||
- "[[2026-09-21-bare-repo-push-permission-denied]]"
|
||||
- "[[2026-09-26-syncthing-clone-root-objects-acl-confusion]]"
|
||||
---
|
||||
|
||||
# TrueNAS NFS4 ACL repair + cross-container media PUID
|
||||
@@ -33,6 +34,18 @@ Any "permission denied" / file not readable / git `loose object ... corrupt` / e
|
||||
## Core facts
|
||||
- TrueNAS SCALE uses **NFSv4 ACL**, not plain POSIX. `ls -la` shows a POSIX mask that can mislead.
|
||||
- Read real ACL: `midclt call filesystem.getacl <path>`; write: `midclt call filesystem.setacl`.
|
||||
- 🔴 **`getfacl` (POSIX view) HIDES the absence of a custom ACL — use `nfs4xdr_getfacl`** (2026-09-26).
|
||||
`getfacl` prints `user::rwx / group::rwx / other::---` whether or not named ACEs exist.
|
||||
`nfs4xdr_getfacl <path>` prints `trivial_acl: true` (only `owner@`/`group@`/`everyone@`) — the
|
||||
definitive "no custom ACL here". Start every permission diagnosis with it, not `getfacl`.
|
||||
- 🔴 **"We already fixed this with ACL" ≠ "the ACL is set on THIS path"** (2026-09-26). A recursive
|
||||
group ACL had been applied to `/mnt/RED_2TB/Edu` and was remembered as "done" — but the failing
|
||||
path was a **different** folder with `trivial_acl: true` (never touched). Verify by fact on the
|
||||
target object before repeating or ruling out a fix. Find past sessions:
|
||||
`sqlite3 ~/.hermes/hermes-whale/state.db "SELECT session_id, substr(content,1,300) FROM messages WHERE content LIKE '%setfacl%' ORDER BY id DESC LIMIT 40;"`
|
||||
- 🔴 **A one-off `chown` is symptom-treatment** (2026-09-26). If a **root** process keeps writing
|
||||
into the folder, root-owned files/objects reappear on the very next run. Permanent fixes only:
|
||||
`ACL` + inherit, OR run the writer **not as root** (`user: "950:950"` in compose).
|
||||
- **`truenas_admin` is FULL_ADMIN in midclt** → can chown/setacl without passwordless root.
|
||||
- Web UI ACL editing only works on zfs **datasets**, not arbitrary subdirs under one dataset → use midclt/CLI.
|
||||
- Post-restore a tree may be owned by wrong uid (e.g. 921 `transmission`) with files `mode 0000`.
|
||||
|
||||
Reference in new issue
Block a user