[2026-09-26] eagle: family/how-to/truenas-infrastructure.md personal/plans/music-tags-review/1-needs-decision.md personal/plans/music-tags-review/2-medium-confidence.md personal/plans/music-tags-review/3-high-confidence.md personal/plans/music-tags-review/music-tags-review.md personal/tech/music-tags-repair-truenas.md
This commit is contained in:
1 parent
1bf8320446
commit
7564ae26ac
6 files changed
+22581
-22429
No files matched your search
@@ -116,6 +116,7 @@
|
||||
> - **Актуальная гонка udev живёт на t610** — см. [[family/how-to/zont-modbus-bridge-udev-race-protection]].
|
||||
> - ⚠️ **Историческая справка (если когда-нибудь откатывать):** `restart: unless-stopped` НЕ перезапускает контейнер, упавший на `start` из-за отсутствующего device-узла (отказ до старта процесса, ExitCode 128/255, RestartCount=0); лечилось ручным `docker start modbus-bridge mbusd` после готовности симлинков.
|
||||
> **⚠️ ПОСЛЕДСТВИЕ, ПОДТВЕРЖДЁННОЕ 2026-09-26 (File Browser):** потеря `.ix-apps` = потеря **всех docker NAMED VOLUMES**, а не только образов. Образы = кеш, перекачаются; **тома = данные, не восстанавливаются**. Первый пострадавший — `filebrowser`: его БД пользователей жила в томах `filebrowser_filebrowser_db` / `filebrowser_filebrowser_config` → при первом старте тома создались с нуля (`2026-08-24T02:04:12`), File Browser сгенерировал нового `admin`, прежние пользователи (`file_admin` в т.ч.) утрачены.
|
||||
> ✅ **ЗАКРЫТО для `filebrowser` 2026-09-26:** переведён с named volumes на **bind-mount в `/mnt/RED_2TB/docker/filebrowser/`** — БД больше не в `.ix-apps`, попадает в обычный бэкап. Рецепт миграции и 5 питфоллов — §«File Browser» ниже. Остальные сервисы с томами (см. `docker volume ls`) — **не проверены, кандидаты на ту же процедуру**.
|
||||
>
|
||||
> 🔴 **Правило для будущих переносов:** перед `zpool destroy`/пересозданием всегда выгружать **`/mnt/.ix-apps/docker/volumes/`** отдельным шагом — `rsync -aHAX /mnt/.ix-apps/docker/volumes/ /mnt/<TARGET>/ix-apps-volumes/`. Одного `/mnt/RED_2TB/*` НЕДОСТАТОЧНО: `.ix-apps` — **отдельный ZFS-датасет**, смонтированный поверх одноимённой папки, в глоб пула не попадает.
|
||||
>
|
||||
@@ -220,7 +221,7 @@ TrueNAS использует **NFSv4 ACL**, а не стандартный POSIX
|
||||
| transmission | linuxserver/transmission:latest | 9091, 51413 | transmission.mallexxx.duckdns.org |
|
||||
| hermes-taiga | hermes-taiga:latest | — | — |
|
||||
| vless-proxy | teddysun/xray:latest | — | — |
|
||||
| filebrowser | filebrowser/filebrowser:latest | 8000 | (через Caddy `192.168.2.197:8000`) — см. раздел «File Browser» |
|
||||
| filebrowser | filebrowser/filebrowser:latest (v2.63.23) | 8000 | (через Caddy → `192.168.2.197:8000`) — см. раздел «File Browser»; **данные в папке, bind-mount (2026-09-26)**, пользователь `file_admin` |
|
||||
| webdav | hacdias/webdav:latest | — | webdav.mallexxx.duckdns.org |
|
||||
| ~~homeassistant~~ ⛔ | home-assistant:stable | ~~8123~~ | **ПОГАШЕН 2026-09-14** — переехал на t610 |
|
||||
| immich-server | immich-app/immich-server:release | 2283 | immich.mallexxx.duckdns.org |
|
||||
@@ -397,12 +398,14 @@ nas_users:x:3000:root,truenas_admin,mallexxx,nas,transmission
|
||||
- **Web:** https://transmission.mallexxx.duckdns.org
|
||||
- **Порты:** 9091 (RPC/web), 51413 (TCP/UDP peers)
|
||||
|
||||
### File Browser — детали (разобрано 2026-09-26)
|
||||
### File Browser — детали (разобрано и ПЕРЕВЕДЕНО НА ПАПКУ 2026-09-26)
|
||||
|
||||
**Папка:** `/mnt/RED_2TB/docker/filebrowser/` (только `docker-compose.yml`).
|
||||
**Папка:** `/mnt/RED_2TB/docker/filebrowser/`.
|
||||
**Порт:** `8000:80` (хост `0.0.0.0:8000`). Проверка: `nc -z 127.0.0.1 8000`.
|
||||
**Образ:** `filebrowser/filebrowser:latest` → **v2.63.23** (проект заархивирован 2026-09-01, обновлений не будет).
|
||||
|
||||
**Состояние ПОСЛЕ миграции (актуальный compose):**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
filebrowser:
|
||||
@@ -415,22 +418,37 @@ services:
|
||||
volumes:
|
||||
- /mnt/RED_2TB/storage:/srv
|
||||
- /mnt/RED_2TB/Edu:/srv/Edu
|
||||
- filebrowser_db:/database # ← NAMED VOLUME, не bind-mount!
|
||||
- filebrowser_config:/config # ← NAMED VOLUME, не bind-mount!
|
||||
volumes:
|
||||
filebrowser_db:
|
||||
filebrowser_config:
|
||||
- /mnt/RED_2TB/docker/filebrowser/database:/database # ← BIND-MOUNT
|
||||
- /mnt/RED_2TB/docker/filebrowser/settings.json:/config/settings.json # ← BIND-MOUNT (файл)
|
||||
```
|
||||
|
||||
> 🔴 **ДАННЫЕ ЖИВУТ В DOCKER NAMED VOLUMES, А НЕ В ПАПКЕ `/mnt/RED_2TB/docker/filebrowser/`.**
|
||||
> В папке контейнера лежат только `docker-compose.yml` + `settings.json` (130 б, дата `Jul 27 20:00`).
|
||||
> Реальные данные:
|
||||
> ```
|
||||
> filebrowser_filebrowser_db → /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_db/_data/filebrowser.db
|
||||
> filebrowser_filebrowser_config → /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_config/_data/settings.json
|
||||
> ```
|
||||
> Физически это **внутри `.ix-apps`** (`DockerRootDir=/mnt/.ix-apps/docker`). Оба тома созданы
|
||||
> `2026-08-24T02:04:12` — то есть **с нуля**, в день пересоздания пула.
|
||||
> ✅ **2026-09-26: named volumes УБРАНЫ, данные переехали в папку.** Причина — они жили
|
||||
> внутри `.ix-apps` и утратились при пересоздании пула (см. пифолл 0 ниже). Теперь
|
||||
> `filebrowser.db` лежит в `/mnt/RED_2TB/docker/filebrowser/database/` и попадает в
|
||||
> обычный бэкап `mailru-crypt:`. Проверка живьём: `docker inspect filebrowser` →
|
||||
> `/database` = `/mnt/RED_2TB/docker/filebrowser/database`, `/config/settings.json` = путь на пуле.
|
||||
|
||||
**Пользователи (после миграции):** остался **только `file_admin`** (id=2, `perm.admin=true`,
|
||||
`scope: /`). Прежний `admin` (id=1) **удалён** 2026-09-26 по указанию Alex.
|
||||
|
||||
#### 🔴 Пифолл 0 (ИСТОРИЧЕСКИЙ, причина всей истории): данные в named volumes внутри `.ix-apps` → потеряны при переносе пула
|
||||
|
||||
**Было:** БД жила в томах
|
||||
```
|
||||
filebrowser_filebrowser_db → /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_db/_data/filebrowser.db
|
||||
filebrowser_filebrowser_config → /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_config/_data/settings.json
|
||||
```
|
||||
Физически внутри `.ix-apps` (`DockerRootDir=/mnt/.ix-apps/docker`). Оба тома созданы **с нуля**
|
||||
`2026-08-24T02:04:12` — в день пересоздания пула. rsync шёл из `/mnt/RED_2TB/*` и `.ix-apps`
|
||||
(отдельный датасет поверх `/mnt/.ix-apps`) не включал → тома погибли, File Browser сгенерировал
|
||||
нового `admin`, все прежние пользователи (в т.ч. `file_admin`) исчезли.
|
||||
|
||||
**Почему это НЕ косяк конфигурации:** `docker-compose.yml` до и после переноса **идентичен**
|
||||
(`/mnt/RED_2TB/docker.bak/filebrowser/docker-compose.yml` == прежний). `settings.json` тоже тот же
|
||||
(130 б, `Jul 27 20:00`) — он пережил перенос, потому что лежал на пуле. Потерялись **данные**, не конфиг.
|
||||
|
||||
> 📌 **Общее правило:** любой сервис с docker NAMED VOLUMES теряет состояние при пересоздании пула,
|
||||
> пока тома лежат в `.ix-apps`. Либо bind-mount на пул, либо включать `.ix-apps` в бэкап.
|
||||
|
||||
#### 🔴 Пифолл 1: логин не работает, потому что пользователя нет / `hideLoginButton: true`
|
||||
|
||||
@@ -469,7 +487,82 @@ docker exec filebrowser cat /config/settings.json
|
||||
docker exec filebrowser cat /database/filebrowser.db # бинарь, читать strings
|
||||
```
|
||||
|
||||
**Состояние на 2026-09-26:** решено НЕ менять (ждёт решения Alex по вариантам A/B/C из отчёта). Данные `admin`-пользователя утрачены при переносе пула; `file_admin` отсутствует.
|
||||
#### 🔴 Пифолл 4: `docker compose up -d` → `permission denied` на compose-файл (права после записи из root-контейнера)
|
||||
|
||||
Файл, записанный через `docker run --rm -v ...:/dst alpine cp ...`, получает `-rw------- root root`.
|
||||
`truenas_admin` (uid 950) не может его прочитать → compose падает:
|
||||
```
|
||||
open /mnt/RED_2TB/docker/filebrowser/docker-compose.yml: permission denied
|
||||
```
|
||||
Фикс (в root-контейнере): `chmod 644` + `chown 950:950` на compose и бэкап.
|
||||
> Папка `/mnt/RED_2TB/docker/filebrowser/` = `root:root` — `truenas_admin` в неё писать не может,
|
||||
> поэтому **любая** запись туда идёт через `docker run --rm -v <пул>:/dst alpine ...`, а не через `cp`/`scp` напрямую.
|
||||
> Безопасный порядок для bind-mount-файлов: изнутри root-контейнера `chown` в `1000:1000` (для данных
|
||||
> File Browser) или `950:950` (для файлов, которые читает `truenas_admin` как compose).
|
||||
|
||||
#### 🔧 Рецепт миграции named volume → папка (выполнен 2026-09-26, воспроизводим)
|
||||
|
||||
```bash
|
||||
# 1. STOP (обязательно: bolt-БД залочена)
|
||||
docker stop filebrowser
|
||||
|
||||
# 2. Бэкап тома на пул (root-контейнер, пул примонтирован целиком)
|
||||
docker run --rm \
|
||||
-v /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_db/_data:/src/db:ro \
|
||||
-v /mnt/.ix-apps/docker/volumes/filebrowser_filebrowser_config/_data:/src/cfg:ro \
|
||||
-v /mnt/RED_2TB/docker/filebrowser:/dst \
|
||||
alpine sh -c 'mkdir -p /dst/_vol_backup_$(date +%Y%m%d)/db /dst/_vol_backup_$(date +%Y%m%d)/cfg
|
||||
cp -av /src/db/. /dst/_vol_backup_$(date +%Y%m%d)/db/
|
||||
cp -av /src/cfg/. /dst/_vol_backup_$(date +%Y%m%d)/cfg/'
|
||||
|
||||
# 3. Данные в рабочую папку
|
||||
docker run --rm -v /mnt/RED_2TB/docker/filebrowser:/dst alpine sh -c '
|
||||
mkdir -p /dst/database
|
||||
cp -av /dst/_vol_backup_*/db/filebrowser.db /dst/database/filebrowser.db
|
||||
cp -av /dst/_vol_backup_*/cfg/settings.json /dst/settings.json
|
||||
chown -R 1000:1000 /dst/database /dst/settings.json'
|
||||
|
||||
# 4. Правка compose на bind-mount (см. блок выше) + chmod 644 / chown 950:950
|
||||
# 5. Правки пользователей/паролей — ТОЛЬКО при остановленном контейнере (см. пифолл 2)
|
||||
# 6. Старт
|
||||
cd /mnt/RED_2TB/docker/filebrowser && docker compose up -d
|
||||
```
|
||||
|
||||
#### 🔴 Пифолл 5: образ `filebrowser` — distroless, `sh`/`bash` НЕТ
|
||||
|
||||
`docker run --rm filebrowser/filebrowser:latest sh -c "..."` → `unknown command "sh" for "filebrowser"`.
|
||||
Бинарь вызывается **напрямую с аргументами**:
|
||||
```bash
|
||||
# список пользователей
|
||||
docker run --rm -v <db-dir>:/database filebrowser/filebrowser:latest users ls -d /database/filebrowser.db
|
||||
# добавить пользователя-админа
|
||||
docker run --rm -v <db-dir>:/database filebrowser/filebrowser:latest users add file_admin 'ПАРОЛЬ' --perm.admin -d /database/filebrowser.db
|
||||
# удалить пользователя
|
||||
docker run --rm -v <db-dir>:/database filebrowser/filebrowser:latest users rm admin -d /database/filebrowser.db
|
||||
# снять скрытие кнопки логина (флаг deprecated: --hide-login-button → --hideLoginButton)
|
||||
docker run --rm -v <db-dir>:/database filebrowser/filebrowser:latest config set --hide-login-button=false -d /database/filebrowser.db
|
||||
```
|
||||
> ⚠️ Правки из этих команд требуют **остановленного** контейнера (bolt-лок, пифолл 2).
|
||||
|
||||
#### ✅ Приёмка 2026-09-26 (проверено живьём)
|
||||
|
||||
| Проверка | Результат |
|
||||
|---|---|
|
||||
| `POST /api/login` с `file_admin` + верный пароль | **HTTP 200** + JWT ✅ |
|
||||
| `POST /api/login` неверный пароль | HTTP 403 ✅ |
|
||||
| `POST /api/login` старый `admin` | HTTP 403 (**удалён**) ✅ |
|
||||
| `GET /login` | HTTP 200 ✅ |
|
||||
| `docker ps` | `Up (healthy)` ✅ |
|
||||
| `docker inspect` монтирование | `/database` = `/mnt/RED_2TB/docker/filebrowser/database` ✅ |
|
||||
|
||||
**Артефакты миграции в `/mnt/RED_2TB/docker/filebrowser/:**
|
||||
`database/filebrowser.db`, `settings.json`, `docker-compose.yml`, `docker-compose.yml.bak-20260926`,
|
||||
`_vol_backup_20260926/{db,cfg}/`.
|
||||
|
||||
**Открытые вопросы (решает Alex):**
|
||||
1. `file_admin` имеет `scope: /` — видит весь корень включая `/srv/Edu` (у прежнего `admin` было `.`). Ограничить при необходимости.
|
||||
2. Пароль `FileAdmin2026!` прошёл через логи чата/ssh — **сменить после первого входа**.
|
||||
3. Стоит ли тем же приёмом перевести на bind-mount **другие** сервисы с named volumes (см. `docker volume ls` — там десятки хеш-имён от прежних compose-проектов).
|
||||
|
||||
> ⚠️ **`/mnt/RED_2TB/docker.bak/filebrowser/` — это НЕ бэкап данных.** Там те же два файла (`docker-compose.yml` + `settings.json`, дата `Apr 29`), которые пережили перенос, потому что лежали на пуле. Томов там нет.
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,20 +1,33 @@
|
||||
---
|
||||
title: Music Tags — Review
|
||||
type: task
|
||||
namespace: personal
|
||||
tags: [music, jellyfin, tags, review, truenas]
|
||||
status: awaiting-approval
|
||||
---
|
||||
|
||||
# Music Tags — проверка тегов
|
||||
|
||||
**К правке:** 4774 файлов · **без изменений:** 3132
|
||||
**К правке:** 4777 файлов · **без изменений:** 3129
|
||||
|
||||
> [!warning] Ничего не изменено
|
||||
> Это план. Ставь галочки, что одобряешь. После «go» — бэкап в `Music/backup/` и применение.
|
||||
|
||||
| Блок | Файлов |
|
||||
|---|---:|
|
||||
| [[1-needs-decision\|Требует решения]] | 296 |
|
||||
| [[2-medium-confidence\|Средняя уверенность]] | 2031 |
|
||||
| [[3-high-confidence\|Высокая уверенность]] | 2447 |
|
||||
## Что в каком блоке
|
||||
|
||||
| Блок | Файлов | Что это значит |
|
||||
|---|---:|---|
|
||||
| [[1-needs-decision\|Требует решения]] | 28 | Нет ни исполнителя, ни альбома. Взять неоткуда — только имя файла. |
|
||||
| [[2-medium-confidence\|Средняя уверенность]] | 2144 | Восстановлено из имён файлов и структуры папок. |
|
||||
| [[3-high-confidence\|Высокая уверенность]] | 2605 | Точная перекодировка CP1251 → UTF-8, обратимая без потерь. |
|
||||
|
||||
## Важное про блок 1
|
||||
|
||||
Попали только 28 файлов, где **нечего показать вообще**. Сборники и аудиосказки
|
||||
(`!Детские/Детский хит`, `Сказки/*`) сюда **не входят** — у них есть альбом
|
||||
(название сборника или сказки), а исполнителя у такого материала и не бывает.
|
||||
|
||||
Если подставить туда имя папки, получится мусор вида `artist = Сказки`
|
||||
(238 треков одним «исполнителем») — от этого отказались.
|
||||
|
||||
## Формат
|
||||
|
||||
Каждый файл — чекбокс `- [ ]`. Под ним: поле, старое значение → **новое**, и источник
|
||||
(`из имени файла`, `из структуры папок`, `кодировка` и т.д.).
|
||||
|
||||
`⟨повреждено⟩` = байты уничтожены (U+FFFD), восстановить нельзя — берётся из имени.
|
||||
|
||||
[[../tech/music-tags-repair-truenas|Техническая сторона →]]
|
||||
@@ -22,6 +22,63 @@ related:
|
||||
> Следующий шаг — апрув Alex по нотам ревью, затем бэкап + применение.
|
||||
> Перед выдачей проведён **полный аудит всех 4774 строк** (`audit_plan.py` + `final_gate.py`) — найдено и исправлено 6 багов.
|
||||
|
||||
## 📌 ПЛАН ТРЕТЬЕЙ ВОЛНЫ (2026-09-26, апрув Alex) — «сам проставь, потом на апрув»
|
||||
|
||||
Alex: **«Давай ка дорогой пройди по файлу и сам проставь нормально все, а только потом мне на апрув,
|
||||
я не собираюсь очевидные вещи руками лопать.»** + указал 2 конкретных дефекта.
|
||||
|
||||
| # | Замечание Alex | Причина | Что делаю |
|
||||
|---|---|---|---|
|
||||
| 1 | «не распознаются как чекбокс, убери треугольные скобки» | `render_grouped_doc.py` оборачивал блок в цитату `> [!info]`, чекбоксы получили префикс `> ` → Obsidian читает как цитату | ✅ убрано `> ` с чекбоксов и подпунктов, выноски оставлены |
|
||||
| 2 | «`DJ Ivan Scratchin' – Welcome To China` — очевидно артист + название, почему склеено в title?» | `split_artist_title()` искал только `" - "` (ASCII-дефис). En-dash `–` / em-dash `—` не матчились | ✅ `SEP_RE` + `DASH_GLUE_RE`, `find_separator()` |
|
||||
| 3 | «куча подобных» | скрытый баг: `any(w in norm(left) for w in EVENT_WORDS)` — **подстроковый** поиск. `"va" in "Ivan"` → True, и `DJ Ivan Scratchin'` отбрасывался | ✅ `has_word()` — токенный поиск |
|
||||
|
||||
### 🔴 КОРНЕВОЙ БАГ ТРЕТЬЕЙ ВОЛНЫ: подстроковый поиск стоп-слов
|
||||
|
||||
`EVENT_WORDS` и `RELEASE_WORDS` проверялись через `any(w in text for w in WORDS)`.
|
||||
Это **подстрока**, не слово. Последствия:
|
||||
|
||||
| Слово из списка | Ложное срабатывание | Кого теряли |
|
||||
|---|---|---|
|
||||
| `va` | `"va" in "dj ivan scratchin'"` → True | `DJ Ivan Scratchin'` |
|
||||
| `set` | `"set" in "sunset"` → True | `Sunset`-исполнители |
|
||||
| `mix` | `"mix" in "mixes"` → True | папки `Remixes, Mixes` |
|
||||
| `live` | `"live" in "delivery"` → True | — |
|
||||
|
||||
**Фикс:** `has_word(text, words)` — токенизация `re.split(r"[^0-9a-zа-яё]+", norm(text))`
|
||||
и сравнение множеств. `Ivan` больше не матчит `va`, `Settle` не матчит `set`.
|
||||
|
||||
> 🔴 **ПИТФОЛЛ НА БУДУЩЕЕ: стоп-слова проверять ТОЛЬКО по токенам.**
|
||||
> `"in" string` на списке коротких слов даёт ложные срабатывания на каждом втором имени.
|
||||
|
||||
### Три формы разделителя artist/title в библиотеке
|
||||
|
||||
| Форма | Пример | Регекс |
|
||||
|---|---|---|
|
||||
| пробелы с двух сторон | `Matisse – Back To Sensation` | `SEP_RE = \s+[-\u2013\u2014]\s+` |
|
||||
| дефис приклеен слева | `Arno Cost & Norman Doray- Apocalypse` | `DASH_GLUE_RE`, только если слева >1 слова |
|
||||
| дефис внутри слова (не сплит) | `Рок-н-ролл`, `БИ-2` | отвергается |
|
||||
|
||||
### 📊 Третья волна: цифры
|
||||
|
||||
| Метрика | v3 | **v4 (финал)** |
|
||||
|---|---:|---:|
|
||||
| `fix` | 4774 | **4777** |
|
||||
| `no_change` | 3132 | 3129 |
|
||||
| Ноты: «требует решения» | 296 | **28** ↓ в 10 раз |
|
||||
| Ноты: средняя | 2031 | 2144 |
|
||||
| Ноты: высокая | 2447 | 2605 |
|
||||
| mojibake в выводе | 0 | **0** |
|
||||
| Тесты | 65 | **65 + 15 новых = 80** |
|
||||
|
||||
**Почему «требует решения» упало 296 → 28:** в блок 1 попадали все файлы с пустым artist,
|
||||
включая 155 сборников `Детский хит` и ~80 аудиосказок. У них **нет исполнителя по природе
|
||||
материала**, но есть альбом. Критерий блока 1 изменён на
|
||||
`not new_artist and not new_album` — «показать нечего вообще».
|
||||
Осталось 28 файлов, где действительно пусто всё.
|
||||
|
||||
---
|
||||
|
||||
## 🔴 ВТОРАЯ ВОЛНА ИСПРАВЛЕНИЙ (2026-09-26, «Сам проверил весь файл на адекватность?»)
|
||||
|
||||
Alex: **«Сам проверил весь файл на адекватность? Чтобы я в очевидные вещи тебя не тыкал.»**
|
||||
|
||||
Reference in new issue
Block a user