625 lines
30 KiB
Markdown
625 lines
30 KiB
Markdown
---
|
||
tags:
|
||
- raspberry-pi
|
||
- nas
|
||
- openmediavault
|
||
- how-to
|
||
created: '2026-05-11'
|
||
updated: '2026-07-03'
|
||
status: hermes-pending
|
||
ip: 192.168.1.15
|
||
---
|
||
# OpenMediaVault на Raspberry Pi 5
|
||
|
||
**Статус:** Контейнеры запущены, Time Machine pending (май 2026)
|
||
**Цель:** NAS на RPi 5 — OS на SD-карте, хранилище на USB 3.0 HDD
|
||
|
||
## Прогресс
|
||
|
||
| Шаг | Статус | Заметки |
|
||
|-----|--------|---------|
|
||
| 1 — Флашим SD | ✅ | Bookworm 2025-05-13, RPi Imager |
|
||
| 2 — Первый запуск + обновление | ✅ | apt upgrade выполнен |
|
||
| 3 — Установка OMV | ✅ | OMV 7 установлен |
|
||
| 4 — Первый вход в веб-интерфейс | ✅ | Пароль сменён |
|
||
| 5 — Сеть | ✅ | DHCP static lease `192.168.1.15` (eth0 MAC `2c:cf:67:64:03:f3`); WiFi включён (wlan0, ASUS5, 192.168.1.15, 2026-05-19) |
|
||
| 6 — USB HDD | ❌ — HDD удалён | 12TB Seagate ST12000NT001 перенесён на HTPC (2026-07-03). На Kraken осталась только SD-карта — см. комментарий ниже. |
|
||
| 7 — omv-extras + Docker | ✅ | omv-extras 7.0.6, Docker 29.4.3, kraken в группе docker |
|
||
| 8 — Контейнеры | ✅ | Все через отдельные docker compose, конфиги на HDD (см. ниже) |
|
||
| 9 — Time Machine share | ✅ | Samba на хосте (не Docker), шара TimeMachine, квота 2.8 TiB |
|
||
| 10 — Перенос данных | N/A | не входит в этот гайд |
|
||
| 11 — Hermes агент Кракен | ✅ | Запущен, Telegram @kraken_htpc_bot живой, mcpvault ✅, obsidian RW, SOUL.md, browser/Playwright ✅, Spotify ✅ |
|
||
| 11а — Docker на HDD | ✅ | data-root + containerd перенесены на HDD через symlink, SD освободилась до 22% |
|
||
| 12 — Obsidian sync (Taiga↔Kraken↔Eagle) | ✅ | Все 3 узла работают, кроны активны, двусторонний sync протестирован |
|
||
| 13 — Vault wiki (llm-wiki) | ✅ | Eagle: scheduled wiki-curation job, Karpathy-style. Active 2026-05-13. |
|
||
| 14 — SMB media share | ✅ | Samba вручную, шара `media` read-only guest. smbd enabled. |
|
||
|| 15 — HDD перенесён на HTPC | ✅ 2026-07-03 | 12TB Seagate ST12000NT001 физически переставлен на HTPC (SATA внутри корпуса). Kraken теперь работает только с SD-карты. |
|
||
|| 16 — Toshiba 1.8TB добавлен на Kraken | ✅ 2026-07-03 | Toshiba MQ01UBB200 (USB, sda, ext4, UUID 6194539b) подключён вместо Seagate. Данные скопированы с HTPC storage без timemachine. Cимлинк со старого UUID на новый. |
|
||
|
||
> **2026-07-03:** HDD удалён с Kraken и подключён к HTPC. См. `family/how-to/htpc-system.md` → раздел «Диски».
|
||
|
||
> **2026-07-03 (позже):** Toshiba 1.8TB (бывший Backup HTPC) перенесён обратно на Kraken. Данные скопированы с Seagate 12TB (без timemachine) — см. `family/how-to/htpc-system.md#перенос-storage-seagate-12tb--backup-toshiba-18tb--2026-07-03`. Для обеспечения обратной совместимости создан симлинк: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade → /srv/dev-disk-by-uuid-6194539b-03e0-4f33-986b-4da09834e82f`. Все сервисы, smb.conf, docker-compose и bind-mounts используют старый путь — с симлинком работают без изменений.
|
||
|
||
---
|
||
|
||
## Железо
|
||
|
||
- Raspberry Pi 5 (4 или 8 GB RAM)
|
||
- SD-карта ≥16 GB (Samsung/SanDisk A1 Class 10+)
|
||
- USB 3.0 HDD для хранения данных
|
||
- Проводной Ethernet (обязателен)
|
||
|
||
---
|
||
|
||
## Шаг 1 — Флашим SD-карту
|
||
|
||
**Образ:** Raspberry Pi OS Lite **64-bit (Bookworm / Debian 12)**
|
||
> ⚠️ Брать именно Bookworm, не Trixie (Debian 13) — OMV не поддерживается на Trixie!
|
||
|
||
- Последний Bookworm: **2025-05-13**
|
||
- Прямая ссылка: https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2025-05-13/2025-05-13-raspios-bookworm-arm64-lite.img.xz
|
||
|
||
**Инструмент:** Raspberry Pi Imager (https://www.raspberrypi.com/software/)
|
||
|
||
> ⚠️ Не Balena Etcher — только RPi Imager поддерживает OS Customisation!
|
||
> При выборе образа из каталога (не custom file) появляется кнопка "Edit Settings"
|
||
|
||
**Настройки (Edit Settings → шестерёнка):**
|
||
- Hostname: `kraken`
|
||
- Username: `kraken` (не `admin` — зарезервировано для OMV!)
|
||
- Password: сохранён в 1Password (запись "Kraken RPi")
|
||
- SSH: Enable → Allow public-key authentication → вставить `~/.ssh/id_rsa.pub`
|
||
|
||
После флаша вставить карту в Pi и включить.
|
||
|
||
---
|
||
|
||
## Шаг 2 — Первый запуск, обновление и настройка сети
|
||
|
||
SSH подключение (пока через WiFi/роутер):
|
||
```bash
|
||
ssh -i ~/.ssh/id_rsa kraken@kraken
|
||
```
|
||
|
||
Обновление системы:
|
||
```bash
|
||
sudo apt-get update && sudo apt-get upgrade -y
|
||
```
|
||
|
||
Static IP на eth0 (прямой кабель Mac ↔ Pi для установки):
|
||
```bash
|
||
sudo nmcli con add type ethernet ifname eth0 con-name eth0-static \
|
||
ipv4.method manual \
|
||
ipv4.addresses 192.168.100.2/24 \
|
||
ipv4.gateway 192.168.100.1 \
|
||
ipv4.never-default yes \
|
||
connection.autoconnect yes
|
||
sudo nmcli con up eth0-static
|
||
```
|
||
|
||
> ⚠️ `ipv4.never-default yes` — обязательно! Иначе интернет пойдёт через Mac, а не WiFi, и установка зависнет.
|
||
|
||
---
|
||
|
||
## Шаг 3 — Установка OMV
|
||
|
||
```bash
|
||
# Pre-install
|
||
wget -qO- https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/preinstall | sudo bash
|
||
sudo reboot
|
||
|
||
# После перезагрузки — основная установка (~30 мин)
|
||
wget -qO- https://github.com/OpenMediaVault-Plugin-Developers/installScript/raw/master/install | sudo bash
|
||
```
|
||
|
||
Pi перезагрузится автоматически по окончании.
|
||
|
||
---
|
||
|
||
## Шаг 4 — Первый вход в веб-интерфейс
|
||
|
||
- URL: `http://192.168.100.2` (или `http://kraken` через LAN)
|
||
- Логин: `admin`
|
||
- Пароль: `openmediavault`
|
||
- **Сразу сменить пароль!** (System → General Settings → Web Administrator Password)
|
||
|
||
---
|
||
|
||
## Шаг 5 — Сеть: DHCP + static lease, отключить WiFi
|
||
|
||
Переключить кабель Pi → роутер. Настроить DHCP через netplan (OMV управляет `/etc/netplan/20-openmediavault-eth0.yaml`):
|
||
|
||
```yaml
|
||
network:
|
||
ethernets:
|
||
eth0:
|
||
match:
|
||
macaddress: "2c:cf:67:64:03:f3"
|
||
dhcp4: yes
|
||
dhcp6: no
|
||
link-local: []
|
||
```
|
||
|
||
В роутере (ASUS): добавить static lease в `dhcp_staticlist` через nvram:
|
||
```bash
|
||
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 \
|
||
"nvram set dhcp_staticlist='...<2C:CF:67:64:03:F3>192.168.1.15>kraken>' && nvram commit && service restart_dnsmasq"
|
||
```
|
||
|
||
Отключить WiFi навсегда (modprobe blacklist):
|
||
```bash
|
||
sudo sh -c 'echo blacklist brcmfmac > /etc/modprobe.d/disable-wifi.conf' < /dev/null
|
||
sudo sh -c 'echo blacklist brcmutil >> /etc/modprobe.d/disable-wifi.conf' < /dev/null
|
||
sudo update-initramfs -u -k all < /dev/null
|
||
```
|
||
|
||
> ⚠️ Все sudo команды через SSH требуют `< /dev/null` — иначе sudo ждёт stdin и зависает
|
||
|
||
---
|
||
|
||
## Шаг 6 — USB HDD
|
||
|
||
1. Подключить HDD к синему (USB 3.0) порту Pi
|
||
2. Проверить скорость: `sudo apt install hdparm && sudo hdparm -t --direct /dev/sda` → должно быть ~200-250 MB/s
|
||
3. Разметить: `sudo parted -s /dev/sda mklabel gpt mkpart primary 0% 100%`
|
||
4. Форматировать (агент не может — только вручную или через скрипт):
|
||
```bash
|
||
sudo bash /tmp/fmt.sh # скрипт с mkfs.ext4 -L storage /dev/sda1
|
||
```
|
||
5. OMV Web UI → Storage → File Systems → выбрать `/dev/sda1` → Mount
|
||
6. OMV монтирует в: `/srv/dev-disk-by-uuid-<UUID>/`
|
||
|
||
> ⚠️ Не монтировать вручную через fstab — OMV должен управлять монтированием сам
|
||
|
||
---
|
||
|
||
## Шаг 7 — omv-extras + Docker
|
||
|
||
```bash
|
||
# omv-extras
|
||
wget -qO- https://github.com/OpenMediaVault-Plugin-Developers/packages/raw/master/install | sudo bash < /dev/null
|
||
|
||
# Docker
|
||
curl -fsSL https://get.docker.com -o /tmp/get-docker.sh && sudo sh /tmp/get-docker.sh < /dev/null
|
||
sudo usermod -aG docker kraken < /dev/null
|
||
```
|
||
|
||
---
|
||
|
||
## Шаг 8 — Docker контейнеры
|
||
|
||
Каждый сервис — отдельный `docker-compose.yml` в `/home/kraken/<name>/`.
|
||
Все конфиги на HDD: `/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/<name>/`
|
||
|
||
| Сервис | Compose | URL | Данные |
|
||
|--------|---------|-----|--------|
|
||
| Portainer | `/home/kraken/portainer/` | :9000 | HDD/docker/portainer |
|
||
| Watchtower | `/home/kraken/watchtower/` | — | stateless |
|
||
| Home Assistant | `/home/kraken/homeassistant/` | :8123 | HDD/docker/homeassistant |
|
||
| Jellyfin | `/home/kraken/media/` | :8096 | HDD/docker/jellyfin, media:ro |
|
||
| Transmission | `/home/kraken/media/` | :9091 | HDD/docker/transmission, HDD/media/downloads |
|
||
| Prowlarr | `/home/kraken/radarr/` | :9696 | HDD/docker/prowlarr |
|
||
| Radarr | `/home/kraken/radarr/` | :7878 | HDD/docker/radarr, media:rw |
|
||
| Sonarr | `/home/kraken/radarr/` | :8989 | HDD/docker/sonarr, media:rw |
|
||
| Rclone | `/home/kraken/rclone/` | — | cron воскр. 03:00 → mailru-crypt:kraken/docker |
|
||
|
||
Управление:
|
||
```bash
|
||
cd /home/kraken/<name> && sudo docker compose up -d # запустить
|
||
cd /home/kraken/<name> && sudo docker compose restart # рестарт
|
||
cd /home/kraken/<name> && sudo docker compose pull && sudo docker compose up -d # обновить
|
||
```
|
||
|
||
> ⚠️ Watchtower: нужна переменная `DOCKER_API_VERSION=1.54` — иначе крашится (API mismatch)
|
||
> ⚠️ sudo через SSH требует `< /dev/null` для каждой команды с tee/pipe
|
||
|
||
---
|
||
|
||
## Media pipeline — Transmission hook + PGS→SRT
|
||
|
||
**Статус: ✅ (2026-05-18)**
|
||
|
||
### Схема
|
||
```
|
||
Transmission → on-download-complete.sh → media-pipeline:kraken sync (NFO, библиотека)
|
||
→ pgs-to-srt.sh (PGS субтитры → SRT)
|
||
```
|
||
|
||
### Файлы
|
||
```
|
||
HDD/docker/media-pipeline/
|
||
on-download-complete.sh — монтирован в Transmission как /config/on-download-complete.sh (ro)
|
||
pgs-to-srt.sh — конвертация PGS→SRT через pgsrip
|
||
config.json — конфиг media-pipeline
|
||
download-complete.log — лог загрузок
|
||
pgs-to-srt.log — лог конвертации
|
||
```
|
||
|
||
### on-download-complete.sh
|
||
Запускается Transmission синхронно при завершении загрузки (`script-torrent-done-filename`).
|
||
Получает `TR_TORRENT_DIR` и `TR_TORRENT_NAME` — пути **внутри контейнера** (`/downloads/...`).
|
||
|
||
Вызывает `pgs-to-srt.sh` с путём `/downloads/complete/radarr/...` — скрипт сам переводит в хостовый путь.
|
||
|
||
> ⚠️ Скрипт выполняется **внутри контейнера Transmission** — хостовые пути недоступны напрямую.
|
||
> `/downloads` → `HDD/media/downloads`, `/media` → `HDD/media` смонтированы в контейнере.
|
||
> Не вызывать бинарники с хостовых путей (`$HDD/...`) — они недоступны внутри контейнера.
|
||
|
||
### pgs-to-srt.sh
|
||
- Живёт на **хосте** (`HDD/docker/media-pipeline/`), вызывается из `on-download-complete.sh`
|
||
- Использует `mkvmerge -i` для детекции PGS/VobSub (быстрее `mkvinfo`)
|
||
- PGS → `~/.local/bin/pgsrip -l ru -l en`
|
||
- VobSub → `SKIP` (не реализовано)
|
||
- Маркер `.sub-checked` рядом с mkv — пропускать уже проверенные файлы при bulk-скане
|
||
- Флаг `-l ru -l en` (два отдельных флага, не через запятую!)
|
||
|
||
### Библиотека субтитров (итог скана 2026-05-18)
|
||
| Папка | Тип | Статус |
|
||
|-------|-----|--------|
|
||
| documentaries-series/пингвины. шпион в толпе (3 файла) | HDMV PGS | ✅ .ru.srt + .en.srt |
|
||
| documentaries-series/жизнь птиц 1998 (10 файлов) | VobSub | ❌ не конвертированы (SKIP) |
|
||
| Всё остальное | SRT внутри mkv | ✅ транскода нет |
|
||
|
||
### Remote path mapping (Radarr/Sonarr)
|
||
Transmission пишет в `/downloads/complete/{radarr,sonarr}/...` (внутри контейнера).
|
||
Radarr/Sonarr видят файлы через `/media/downloads/...`.
|
||
Маппинг добавлен: `host=transmission, remotePath=/downloads/, localPath=/media/downloads/`.
|
||
|
||
---
|
||
|
||
## Шаг 9 — Time Machine share
|
||
|
||
Time Machine работает через **хостовый smbd** (не через Docker). Документ переписан 2026-06-06 — раньше здесь ошибочно описывался Docker-контейнер `mbentley/timemachine:smb`, но он не используется.
|
||
|
||
**Конфигурация в `/etc/samba/smb.conf`:**
|
||
```ini
|
||
[TimeMachine]
|
||
path = /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/timemachine
|
||
comment = Time Machine
|
||
valid users = timemachine
|
||
browseable = yes
|
||
read only = no
|
||
inherit acls = yes
|
||
fruit:time machine = yes
|
||
vfs objects = catia fruit streams_xattr
|
||
fruit:time machine max size = 3000000000000 # квота ~2.8 TiB
|
||
```
|
||
|
||
> **TM квота:** установлена 2026-06-24 — `3000000000000` байт (~2.8 TiB). Раньше было `0` (безлимит), из-за чего TM занял 2.2T из 11T HDD. При достижении квоты Mac начнёт удалять старые снепшоты.
|
||
|
||
**Credentials:**
|
||
- Пользователь: `timemachine`
|
||
- Пароль: `timemachine`
|
||
|
||
**Подключение с Mac:**
|
||
1. Finder → `⌘K` → `smb://kraken`
|
||
2. Логин: `timemachine` / пароль
|
||
3. System Preferences → Time Machine → Add Disk → выбрать `kraken`
|
||
|
||
---
|
||
|
||
## Шаг 14 — SMB share
|
||
|
||
**Статус: ✅ (2026-06-06)** — шара `media` добавлена обратно, smbd работает.
|
||
|
||
Samba установлена как часть OMV, но плагин `openmediavault-samba` не используется — конфиг управляется вручную.
|
||
|
||
`/etc/samba/smb.conf` (шара добавлена в конец файла):
|
||
```ini
|
||
[media]
|
||
path = /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/media
|
||
comment = Kraken Media
|
||
browseable = yes
|
||
read only = yes
|
||
guest ok = yes
|
||
force user = kraken
|
||
```
|
||
|
||
**Подключение с Mac:** Finder → `⌘K` → `smb://kraken` → шары `TimeMachine` и `media`.
|
||
|
||
> ⚠️ OMV не управляет smb.conf (плагин не установлен) — правки не слетают при `omv-salt deploy run`, но слетели в прошлый раз при обновлении/перезаписи. Если шара пропадёт — перепроверить `/etc/samba/smb.conf`.
|
||
|
||
Плагин `openmediavault-samba` не используется. smb.conf управляется вручную или через OMV salt — при развёртывании OMV-конфигурации ручные правки слетают.
|
||
|
||
---
|
||
|
||
## Шаг 10 — Перенос данных
|
||
|
||
### Фильмы с Mac на NAS
|
||
```bash
|
||
rsync -avh --progress /path/to/movies/ kraken@kraken:/srv/.../media/movies/
|
||
```
|
||
|
||
### Time Machine
|
||
> ⚠️ Старый TM-бэкап перенести нельзя напрямую — TM привязывает бэкап к конкретному диску/хосту.
|
||
> Начать новый бэкап на NAS, старый HDD хранить как архив или отформатировать после нескольких успешных новых бэкапов.
|
||
|
||
---
|
||
|
||
## Hermes агент — ограничения и архитектура
|
||
|
||
> Важно знать при отладке поведения агента.
|
||
|
||
Агент работает **внутри** контейнера `hermes-kraken`. Это означает:
|
||
|
||
| Возможность | Статус | Способ |
|
||
|---|---|---|
|
||
| Читать/писать vault | ✅ | `/vault/` через mcpvault MCP |
|
||
| Писать файлы на хост | ✅ только через alpine+bind `/:/host` | Portainer API |
|
||
| docker / docker cp | ❌ нет в контейнере | только Portainer API |
|
||
| SSH на хост | ✅ через loopback | `ssh kraken-host` (алиас: 127.0.0.1, ключ `/opt/data/.ssh/id_ed25519`) |
|
||
| apt install | ⚠️ слетает при rebuild | не использовать |
|
||
| Portainer endpoint ID | **3** (не 1!) | проверять: `GET /api/endpoints` |
|
||
|
||
### Передача файлов на хост
|
||
|
||
**Предпочтительно — через SSH:**
|
||
```bash
|
||
# Из контейнера hermes-kraken:
|
||
ssh kraken-host "cat > /path/on/host" < local_file
|
||
# или
|
||
scp local_file kraken-host:/path/on/host
|
||
```
|
||
|
||
**Резервный вариант — через base64 (alpine-контейнер + bind `/:/host`):**
|
||
```bash
|
||
# Контент → base64 → Cmd alpine-контейнера → decode на хосте
|
||
B64=$(printf '%s' 'content' | base64 | tr -d '\n')
|
||
# Cmd: ["sh", "-c", "echo <B64> | base64 -d > /host/path && echo DONE"]
|
||
# HostConfig.Binds: ["/:/host"]
|
||
```
|
||
|
||
**Никогда не использовать:** echo с кавычками, printf escaping, heredoc — все они ломаются при передаче через Docker Cmd array.
|
||
|
||
### Токены в Portainer API — не через shell-переменные
|
||
|
||
Hermes маскирует секреты как `***` в terminal output. `$TOKEN` в JSON передаётся буквально.
|
||
Правильно: интерполировать значение ДО построения JSON (через Python), не в shell-строке curl.
|
||
|
||
### Правило трёх попыток
|
||
|
||
Если действие не удаётся 3 раза — агент должен остановиться и сообщить пользователю.
|
||
|
||
---
|
||
|
||
## Шаг 11 — Hermes агент Кракен
|
||
|
||
**Статус: ✅ запущен (2026-05-12), mcpvault ✅ (2026-05-13)**
|
||
|
||
### Файлы
|
||
```
|
||
/home/kraken/hermes/
|
||
Dockerfile — образ hermes-kraken:latest
|
||
docker-compose.yml — restart: unless-stopped, network_mode: host
|
||
.env — API ключи
|
||
```
|
||
|
||
Конфиги и данные на HDD:
|
||
```
|
||
/srv/dev-disk-by-uuid-49e8f586.../docker/hermes/config/
|
||
config.yaml — основной конфиг Hermes
|
||
.local/bin/mcpvault — symlink → ../lib/node_modules/@bitbonsai/mcpvault/dist/server.js
|
||
.local/lib/node_modules/@bitbonsai/mcpvault/ — persistent, не слетает при rebuild
|
||
```
|
||
|
||
### Toolsets (актуально 2026-05-13)
|
||
| Toolset | Статус |
|
||
|---------|--------|
|
||
| hermes-cli | ✅ |
|
||
| terminal | ✅ |
|
||
| file | ✅ |
|
||
| web (web_search + web_extract) | ✅ Tavily |
|
||
| browser (Playwright/Chromium) | ✅ (добавлен 2026-05-13) |
|
||
| memory | ✅ |
|
||
| spotify | ✅ токен скопирован с Eagle (PKCE, client_secret не нужен) |
|
||
| cronjob | ✅ |
|
||
|
||
> ⚠️ При сборке Кракена: `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` убран, `npx playwright install --with-deps chromium --only-shell` добавлен в Dockerfile
|
||
|
||
> ⚠️ Spotify — plugin toolset. Нужно: 1) `spotify` в `toolsets:` в config.yaml, 2) `known_plugin_toolsets.telegram: [spotify]` в config.yaml, 3) `auth.json` скопирован с Eagle (содержит refresh_token, PKCE). `client_secret` не нужен.
|
||
|
||
> ⚠️ SOUL.md не должен содержать `curl ... $TOKEN/KEY/SECRET` — Hermes блокирует файл по паттерну `exfil_curl`. Заменять на псевдокод (`# GET /api/...`).
|
||
|
||
### Модели (актуально 2026-05-13)
|
||
| Модель | Статус |
|
||
|--------|--------|
|
||
| `gemini-2.5-flash` | ✅ primary |
|
||
| openrouter fallbacks | ✅ |
|
||
|
||
> ⚠️ **Gemini prepaid кредиты исчерпаны (2026-05-14)** — HTTP 429 RESOURCE_EXHAUSTED. Пока не пополнено, Кракен работает на OpenRouter free fallback (не поддерживает vision — изображения из Telegram не обрабатываются). Пополнить: https://aistudio.google.com/projects
|
||
|
||
### Telegram бот
|
||
- Имя: Кракен / Bot: [@kraken_htpc_bot](https://t.me/kraken_htpc_bot)
|
||
|
||
### MCP серверы
|
||
| Server | Команда | Vault |
|
||
|--------|---------|-------|
|
||
| obsidian | `/opt/data/.local/bin/mcpvault /vault` | `/home/kraken/obsidian` → `/vault:rw` |
|
||
|
||
> ⚠️ mcpvault установлен через `npm install -g --prefix /opt/data/.local` — живёт на HDD, переживает rebuild образа
|
||
> ⚠️ Vault монтируется как `/vault:rw` (не `:ro`!) — иначе mcpvault не может писать заметки
|
||
> ⚠️ config.yaml: указывать **полный путь** `/opt/data/.local/bin/mcpvault` — PATH в контейнере его не включает
|
||
> ⚠️ args: `/vault` (путь внутри контейнера), не `/home/kraken/obsidian`
|
||
|
||
### Деплой / пересборка
|
||
```bash
|
||
# Сборка (осторожно — npm install съедает место на SD!)
|
||
cd /home/kraken/hermes && docker build -t hermes-kraken:latest .
|
||
|
||
# Если ENOSPC при сборке — сначала почистить build cache:
|
||
docker builder prune -af
|
||
|
||
# Запуск (docker compose не работает через SSH из-за long-lived process detection)
|
||
docker stop hermes-kraken && docker rm hermes-kraken
|
||
docker run -d --name hermes-kraken --restart unless-stopped --network host \
|
||
-v /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker/hermes/config:/opt/data \
|
||
-v /home/kraken/obsidian:/vault:rw \
|
||
-e HERMES_UID=1000 -e HERMES_GID=1000 -e HERMES_ALLOW_ROOT_GATEWAY=1 \
|
||
--env-file /home/kraken/hermes/.env hermes-kraken:latest
|
||
|
||
# Проверка
|
||
docker logs hermes-kraken --tail 20
|
||
docker inspect hermes-kraken --format 'Status={{.State.Status}} Restarts={{.RestartCount}}'
|
||
```
|
||
|
||
### TODO
|
||
- [ ] Настроить HA → создать Long-Lived token → вписать в HASS_TOKEN в .env
|
||
- [x] ~~Перенести Spotify auth~~ ✅ скопирован с Eagle
|
||
- [ ] Проверить SD backup cron (ручной запуск ✅ 6.3G/12мин; автозапуск — первое воскресенье 03:00)
|
||
|
||
> Запуск контейнера: `docker run ... hermes-kraken:latest gateway run` — `gateway run` уже в команде, compose не используется.
|
||
|
||
---
|
||
|
||
## Перенаправление записи с SD на HDD (2026-06-24)
|
||
|
||
**Проблема (2026-06-24):** Kraken крашился — SD-карта забита под 99% (14G/14G, 40MB свободно). folder2ram держит `/var/log` в tmpfs, но при ребуте/shutdown OMV сбрасывает tmpfs на SD.
|
||
|
||
**Решение:** bind-mount всех пишущихся каталогов на HDD.
|
||
|
||
| Каталог | Цель на HDD | Метод |
|
||
|---------|-------------|-------|
|
||
| `/var/folder2ram/var/log` | `.../var-log` | fstab bind |
|
||
| `/var/cache/apt` | `.../apt-cache` | fstab bind |
|
||
| `/var/log/journal` | `.../journal` | fstab bind |
|
||
| Docker data-root | `.../docker-data` | daemon.json |
|
||
| containerd | `.../containerd` | symlink |
|
||
|
||
### Команды
|
||
|
||
```bash
|
||
HDD="/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade"
|
||
|
||
# folder2ram/var/log
|
||
sudo mkdir -p "$HDD/var-log"
|
||
sudo rsync -a /var/folder2ram/var/log/ "$HDD/var-log/"
|
||
sudo mount --bind "$HDD/var-log" /var/folder2ram/var/log
|
||
echo "$HDD/var-log /var/folder2ram/var/log none bind,nofail 0 0" | sudo tee -a /etc/fstab
|
||
|
||
# Apt-кэш
|
||
sudo mkdir -p "$HDD/apt-cache"
|
||
sudo rsync -a /var/cache/apt/ "$HDD/apt-cache/"
|
||
sudo mount --bind "$HDD/apt-cache" /var/cache/apt
|
||
echo "$HDD/apt-cache /var/cache/apt none bind,nofail 0 0" | sudo tee -a /etc/fstab
|
||
|
||
# Journald
|
||
sudo mkdir -p "$HDD/journal"
|
||
sudo rsync -a /var/log/journal/ "$HDD/journal/" 2>/dev/null
|
||
sudo mount --bind "$HDD/journal" /var/log/journal
|
||
echo "$HDD/journal /var/log/journal none bind,nofail 0 0" | sudo tee -a /etc/fstab
|
||
sudo systemctl restart systemd-journald
|
||
```
|
||
|
||
Проверка:
|
||
```bash
|
||
df -h /var/folder2ram/var/log /var/log/journal /var/cache/apt
|
||
# Все должны показывать /dev/sda1 (HDD), не mmcblk0 (SD)
|
||
```
|
||
|
||
> ⚠️ OMV может перезаписывать `/etc/fstab` при `omv-salt deploy run`. Если bind пропадёт — перепроверить.
|
||
|
||
### df vs du — расхождение на SD
|
||
|
||
`df` = 13G/14G, `du -shx /` = 3.6G. Разница ~10G — **блоки ext4, занятые физически на NAND но не привязанные к файлам** (эффект отсутствия TRIM). На SD это норма.
|
||
|
||
Остаточная запись на SD после переносов: `/etc`, `/var/lib/samba` (8 MB), `/home/kraken` (uv кэш), dpkg — стабильно.
|
||
|
||
### SD backup
|
||
|
||
Скрипт: `/usr/local/bin/sd-backup.sh` — образ SD на HDD, хранит 3 последних копии.
|
||
```bash
|
||
sudo /usr/local/bin/sd-backup.sh # ~11G, ~11 мин
|
||
```
|
||
Хранится: `$HDD/backup/sd-card/kraken-sd-*.img.gz`. Ротация: auto-removes oldest.
|
||
|
||
## Шаг 11а — Docker и containerd на HDD
|
||
|
||
**Статус: ✅ (2026-05-13)**
|
||
|
||
SD карта 14GB быстро заполняется Docker образами. Всё перенесено на HDD.
|
||
|
||
### Docker data-root
|
||
```bash
|
||
# /etc/docker/daemon.json
|
||
{"data-root": "/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker-data"}
|
||
```
|
||
|
||
### containerd → symlink на HDD
|
||
```bash
|
||
sudo systemctl stop docker docker.socket containerd
|
||
sudo rsync -a /var/lib/containerd/ /srv/.../containerd/
|
||
sudo mv /var/lib/containerd /var/lib/containerd.bak
|
||
sudo ln -s /srv/.../containerd /var/lib/containerd
|
||
sudo systemctl start containerd docker
|
||
sudo rm -rf /var/lib/containerd.bak
|
||
```
|
||
|
||
### Build cache (buildkit) — живёт на SD!
|
||
Buildkit cache НЕ управляется data-root — растёт на SD. Cron очистки:
|
||
```
|
||
# /etc/cron.d/docker-buildcache-cleanup
|
||
0 4 * * * root docker builder prune -af --filter until=24h > /dev/null 2>&1
|
||
```
|
||
|
||
При ручной сборке перед build: `docker builder prune -af`
|
||
|
||
### Текущее состояние SD (после всех переносов)
|
||
- SD: ~22% используется (2.9GB из 14GB), 11GB свободно
|
||
- HDD: docker-data + containerd + build cache → не мусорят SD
|
||
|
||
---
|
||
|
||
## Шаг 12 — Obsidian sync (Eagle ↔ Taiga ↔ Kraken)
|
||
|
||
**Статус: ✅ работает на всех 3 узлах (протестировано 2026-05-13)**
|
||
|
||
Подробная документация: [[obsidian-sync]]
|
||
|
||
**Схема:**
|
||
```
|
||
Eagle (полный vault ~/obsidian) ──push/pull──┐
|
||
Taiga (sparse: personal/ family/) ────────────├── TrueNAS bare repo
|
||
Kraken (sparse: personal/ family/) ───────────┘ mallexxx.duckdns.org:/mnt/RED_2TB/storage/git/obsidian-vault.git
|
||
```
|
||
|
||
**Скрипты и кроны:**
|
||
| Узел | Скрипт | Крон | Vault |
|
||
|------|--------|------|-------|
|
||
| Eagle | `~/scripts/sync-vault.sh` | `0 * * * *` | `~/obsidian` (full) |
|
||
| Kraken | `~/scripts/sync-vault.sh` | `0 * * * *` | `~/obsidian` (sparse) |
|
||
| Taiga | `~/sync-vault.sh` (на хосте!) | Hermes cron `0 * * * *` | `/mnt/RED_2TB/docker/hermes/vault` (sparse) |
|
||
|
||
> ⚠️ Тайга: скрипт запускается на **хосте TrueNAS** (не внутри контейнера) — только truenas_admin имеет ZFS ACL доступ к bare repo.
|
||
|
||
## Шаг 13 — Vault wiki (llm-wiki / Karpathy approach)
|
||
|
||
Eagle-only: scheduled Hermes job раз в сутки запускает wiki-curation:
|
||
- Упорядочивает `wiki/` папку по SCHEMA.md
|
||
- Строит cross-references между страницами
|
||
- Резолвит git-конфликты вручную (semantic merge)
|
||
- Lint: orphans, broken links, stale content
|
||
|
||
**TODO:**
|
||
- [x] ~~Создать `wiki/SCHEMA.md`, `wiki/index.md`, `wiki/log.md`~~ ✅ 2026-05-13
|
||
- [x] ~~Добавить cron job на Eagle: ежедневно 02:00, skill `llm-wiki`~~ ✅ 2026-05-13
|
||
- [x] ~~Настроить `WIKI_PATH=~/obsidian/wiki` в Eagle `.env`~~ ✅ 2026-05-13
|
||
|
||
---
|
||
|
||
## Уроки (что пошло не так при установке)
|
||
|
||
- **Balena Etcher** не поддерживает OS Customisation — использовать только **RPi Imager**
|
||
- **`userconf.txt`** deprecated на Bookworm — правильный способ через RPi Imager (он пишет `custom.toml`)
|
||
- **`systemd.run=` в cmdline.txt** нужно указывать `/usr/lib/raspberrypi-sys-mods/firstboot`, а не свой скрипт
|
||
- **`ipv4.never-default yes`** при настройке static IP на eth0 — обязательно, иначе интернет идёт через Mac и установка зависает
|
||
- **OMV install script** при зависании — скорее всего нет интернета, проверить маршруты (`ip route`)
|
||
|
||
---
|
||
|
||
## Полезные ссылки
|
||
|
||
- Официальный вики OMV: https://wiki.omv-extras.org/
|
||
- Install script: https://github.com/OpenMediaVault-Plugin-Developers/installScript
|
||
- RPi Imager: https://www.raspberrypi.com/software/
|
||
- RPi Downloads: https://www.raspberrypi.com/software/operating-systems/
|