Files
obsidian-vault/family/how-to/openmediavault-rpi5.md
T
2026-05-29 09:01:25 +00:00

26 KiB
Executable File
Raw Blame History

tags, created, updated, status, ip
tags created updated status ip
raspberry-pi
nas
openmediavault
how-to
2026-05-11 2026-05-12 hermes-pending 192.168.1.14

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.14 (eth0 MAC 2c:cf:67:64:03:f3); WiFi включён (wlan0, ASUS5, 192.168.1.15, 2026-05-19)
6 — USB HDD 12TB Seagate ST12000NT001, EXT4, UUID 49e8f586-3839-4c5d-a1e1-58bfc3579ade, смонтирован через OMV в /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade
7 — omv-extras + Docker omv-extras 7.0.6, Docker 29.4.3, kraken в группе docker
8 — Контейнеры Все через отдельные docker compose, конфиги на HDD (см. ниже)
9 — Time Machine share mbentley/timemachine:smb, расписание 10:00-22:00 GMT+6, HDD/timemachine
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)
14 — SMB media share Samba вручную, шара media read-only guest. smbd enabled.

Железо

  • 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!

Инструмент: 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/роутер):

ssh -i ~/.ssh/id_rsa kraken@kraken

Обновление системы:

sudo apt-get update && sudo apt-get upgrade -y

Static IP на eth0 (прямой кабель Mac ↔ Pi для установки):

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

# 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):

network:
  ethernets:
    eth0:
      match:
        macaddress: "2c:cf:67:64:03:f3"
      dhcp4: yes
      dhcp6: no
      link-local: []

В роутере (ASUS): добавить static lease в dhcp_staticlist через nvram:

ssh -i ~/.ssh/id_rsa admin@192.168.1.1 \
  "nvram set dhcp_staticlist='...<2C:CF:67:64:03:F3>192.168.1.14>kraken>' && nvram commit && service restart_dnsmasq"

Отключить WiFi навсегда (modprobe blacklist):

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. Форматировать (агент не может — только вручную или через скрипт):
    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

# 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

Управление:

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 — хостовые пути недоступны напрямую. /downloadsHDD/media/downloads, /mediaHDD/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

Контейнер: mbentley/timemachine:smb Compose: /home/kraken/timemachine/docker-compose.yml Данные: /srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/timemachine/

Режим работы: restart: unless-stopped — контейнер стартует автоматически при загрузке и работает постоянно.

Credentials:

  • Пользователь: timemachine
  • Пароль: timemachine ⚠️ сменить позже

Подключение с Mac:

  1. Finder → ⌘Ksmb://kraken
  2. Логин: timemachine / timemachine
  3. System Preferences → Time Machine → Add Disk → выбрать kraken

⚠️ Не останавливать контейнер резко (docker stop) пока TM пишет бэкап — Samba оставляет stale lock на mbp-black.sparsebundle/lock. При следующем запуске TM не может смонтировать образ. Фикс: рестарт контейнера (docker restart timemachine).

Changelog — Time Machine

  • 2026-05-14 — добавлен cron-контроль: запуск 04:00 UTC / остановка 16:00 UTC
  • 2026-05-22 — cron убран, restart: unless-stopped. Причина: резкая остановка через cron оставляла stale Samba lock → TM не мог смонтировать образ при следующем запуске

Шаг 14 — SMB media share

Статус: (2026-05-16)

Samba установлена как часть OMV, но плагин openmediavault-samba не используется — конфиг управляется вручную.

/etc/samba/smb.conf (шара добавлена в конец файла):

[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

smbd включён в автозапуск: sudo systemctl enable smbd

Подключение с Mac: Finder → ⌘Ksmb://kraken → шара media → гостевой доступ.

⚠️ OMV не управляет smb.conf (плагин не установлен) — правки не слетают при omv-salt deploy run. ⚠️ nmbd не нужен (disable netbios = yes в глобальных настройках OMV).


Шаг 10 — Перенос данных

Фильмы с Mac на NAS

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 на хост нет ключей
apt install ⚠️ слетает при rebuild не использовать
Portainer endpoint ID 3 (не 1!) проверять: GET /api/endpoints

Передача файлов на хост — только base64

# Контент → 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 бот

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

Деплой / пересборка

# Сборка (осторожно — 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
  • Перенести Spotify auth скопирован с Eagle
  • Проверить SD backup cron (ручной запуск 6.3G/12мин; автозапуск — первое воскресенье 03:00)

Запуск контейнера: docker run ... hermes-kraken:latest gateway rungateway run уже в команде, compose не используется.


Шаг 11а — Docker и containerd на HDD

Статус: (2026-05-13)

SD карта 14GB быстро заполняется Docker образами. Всё перенесено на HDD.

Docker data-root

# /etc/docker/daemon.json
{"data-root": "/srv/dev-disk-by-uuid-49e8f586-3839-4c5d-a1e1-58bfc3579ade/docker-data"}
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:

  • Создать wiki/SCHEMA.md, wiki/index.md, wiki/log.md 2026-05-13
  • Добавить cron job на Eagle: ежедневно 02:00, skill llm-wiki 2026-05-13
  • Настроить 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)

Полезные ссылки