[2026-05-12] taiga sync: family/.DS_Store family/_index.md family/how-to/htpc-access.md family/how-to/htpc-gaming-plans.md family/how-to/htpc-magic4pc.md family/how-to/htpc-migration-plan.md family/how-to/htpc-system.md family/how-to/htpc-webos-luna.md family/how-to/htpc.md family/how-to/magic4pc-webos.md
This commit is contained in:
BIN
Binary file not shown.
Executable
+3
@@ -0,0 +1,3 @@
|
||||
# Family
|
||||
|
||||
[[how-to/]] | [[documents/]] | [[contacts/]] | [[schedule/]]
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
# HTPC — Доступ и управление
|
||||
|
||||
## SSH
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_rsa bazzite@192.168.1.86
|
||||
```
|
||||
Пароль sudo: `bazzite`
|
||||
|
||||
## Go (на HTPC)
|
||||
Go установлен в `/usr/local/go/bin/go` (не в PATH по умолчанию).
|
||||
Сборка: `cd ~/magic4pc && /usr/local/go/bin/go build -o magic4pc_new .`
|
||||
|
||||
## Git workflow (magic4pc)
|
||||
- Mac: `~/Developer/magic4pc_altclient`, бранч `bazzite-linux`
|
||||
- Remote `linux` → `ssh://bazzite@192.168.1.86/var/home/bazzite/magic4pc.git` (bare repo)
|
||||
- Worktree на HTPC: `/home/bazzite/magic4pc`
|
||||
- Remote `origin` → `https://github.com/mallexxx/magic4pc_altclient.git`
|
||||
|
||||
Деплой:
|
||||
```bash
|
||||
# На Mac:
|
||||
git push linux bazzite-linux
|
||||
|
||||
# На HTPC:
|
||||
cd ~/magic4pc && git pull && /usr/local/go/bin/go build -o magic4pc_new .
|
||||
sudo systemctl stop magic4pc
|
||||
sudo rm /usr/local/bin/magic4pc
|
||||
sudo cp magic4pc_new /usr/local/bin/magic4pc
|
||||
sudo systemctl start magic4pc
|
||||
```
|
||||
|
||||
> ⚠️ Нельзя `cp` поверх работающего бинаря — "Text file busy". Всегда сначала `stop` → `rm` → `cp` → `start`.
|
||||
|
||||
## systemd сервис
|
||||
Файл: `/etc/systemd/system/magic4pc.service`
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Magic Remote client for LG TV
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=bazzite
|
||||
Group=bazzite
|
||||
ExecStart=/usr/local/bin/magic4pc-run.sh
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
StartLimitIntervalSec=0
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
`StartLimitIntervalSec=0` — без лимита рестартов (иначе при crash-loop убивается).
|
||||
|
||||
## Run script
|
||||
`/usr/local/bin/magic4pc-run.sh` — ждёт X display, делает `xhost +local:`, запускает бинарь.
|
||||
|
||||
## ydotoold
|
||||
User-юнит: `~/.config/systemd/user/ydotoold.service`
|
||||
Socket: `/run/user/1000/.ydotool_socket`
|
||||
Управление: `systemctl --user status ydotoold`
|
||||
|
||||
## Логи
|
||||
```bash
|
||||
journalctl -u magic4pc -n 50 --no-pager
|
||||
journalctl -u magic4pc -f # live
|
||||
```
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
# HTPC — Планы: Игры и Эмуляторы
|
||||
|
||||
## Статус системы
|
||||
- [x] Bazzite установлен, автологин в Gaming Mode
|
||||
- [x] 1080p@60Hz, аудио LPCM работает
|
||||
- [x] LG Magic Remote работает (magic4pc)
|
||||
- [x] Без пароля при входе
|
||||
- [ ] EmuDeck
|
||||
- [ ] Proton-GE
|
||||
- [ ] MangoHud
|
||||
- [ ] Эмуляторы
|
||||
|
||||
## Следующие шаги
|
||||
|
||||
### 1. EmuDeck
|
||||
Установка через официальный скрипт:
|
||||
```bash
|
||||
# В KDE Desktop Mode (не gamescope):
|
||||
curl -L https://raw.githubusercontent.com/dragoonDorise/EmuDeck/main/install.sh | bash
|
||||
```
|
||||
Настроит RetroArch, PCSX2, Yuzu/Ryujinx и др. автоматически.
|
||||
ROM-и класть в `~/Emulation/roms/<system>/`
|
||||
|
||||
### 2. Proton-GE
|
||||
Через ProtonUp-Qt (устанавливается из Discover или Flatpak):
|
||||
```bash
|
||||
flatpak install flathub net.davidotek.pupgui2
|
||||
```
|
||||
Или через EmuDeck — он включает ProtonUp-Qt.
|
||||
|
||||
### 3. MangoHud (FPS overlay)
|
||||
Уже есть в Bazzite. Включить для игры:
|
||||
- В Steam: Properties → Launch Options: `mangohud %command%`
|
||||
- Глобально: `MANGOHUD=1` в environment
|
||||
|
||||
### 4. Эмуляторы (план)
|
||||
|
||||
| Платформа | Эмулятор | Статус |
|
||||
|-----------|----------|--------|
|
||||
| NES | RetroArch (Nestopia) | Через EmuDeck |
|
||||
| SNES | RetroArch (bsnes/Snes9x) | Через EmuDeck |
|
||||
| Sega Mega Drive | RetroArch (Genesis Plus GX) | Через EmuDeck |
|
||||
| PS2 | PCSX2 | Через EmuDeck |
|
||||
| N64 | RetroArch (Mupen64Plus) | Через EmuDeck |
|
||||
| Switch | Ryujinx (или Suyu) | Через EmuDeck |
|
||||
|
||||
### 5. ROM-и
|
||||
Скопировать в `~/Emulation/roms/` по папкам после установки EmuDeck.
|
||||
EmuDeck сам создаст структуру директорий.
|
||||
|
||||
### 6. Steam ROM Manager
|
||||
Входит в EmuDeck — добавляет эмуляторные игры в Steam библиотеку с обложками.
|
||||
После добавления они появятся в Gaming Mode как обычные Steam игры.
|
||||
|
||||
## Железо — ограничения
|
||||
- RX 570: Switch эмуляция может быть медленной (Vulkan поддерживается)
|
||||
- i7-6800K (Broadwell-E): PS2 и Switch — проверить производительность
|
||||
- 32GB RAM: достаточно для всего
|
||||
|
||||
## Управление в эмуляторах
|
||||
Magic Remote (magic4pc) работает как мышь + клавиатура.
|
||||
Для эмуляторов нужен геймпад — варианты:
|
||||
- Bluetooth геймпад (PS4/PS5/Xbox)
|
||||
- USB геймпад
|
||||
- Настроить маппинг Magic Remote кнопок на gamepad через Steam Input (если эмулятор в Steam)
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
# magic4pc — LG Magic Remote для HTPC
|
||||
|
||||
## Что это
|
||||
Go-клиент для LG Magic Remote (webOS приложение на TV).
|
||||
Форк: https://github.com/mallexxx/magic4pc_altclient (бранч `bazzite-linux`)
|
||||
Оригинал: https://github.com/netham45/magic4pc_altclient
|
||||
|
||||
## Архитектура
|
||||
- **TV сервер**: webOS приложение на LG TV (192.168.1.75:42831), шлёт UDP
|
||||
- **HTPC клиент**: `/usr/local/bin/magic4pc`, UDP-клиент на фиксированном source port **9106**
|
||||
- **xdotool**: единый persistent процесс через stdin pipe — мышь и клавиши
|
||||
- **ydotool**: для gamescope-специфичных команд (Ctrl+1, Ctrl+2) через `/run/user/1000/.ydotool_socket`
|
||||
|
||||
## Ключевые фиксы (история)
|
||||
| Проблема | Решение |
|
||||
|----------|---------|
|
||||
| TV "service error" / не реконнектится | Фиксированный source UDP port 9106 (`ListenUDP(":9106")`) |
|
||||
| TV зависает в "waiting for client" | Server keepalive timeout 10s → auto-reconnect |
|
||||
| KDE XTest диалог при каждом клике | Единый xdotool процесс (не новый на каждую кнопку) |
|
||||
| KDE XTest диалог при рестарте xdotool | `XwaylandEisNoPrompt=true` в kwinrc |
|
||||
| Кривые координаты мыши | Динамический scale через `xdotool getdisplaygeometry` |
|
||||
| Крестик слал Ctrl/a/s/d | TV keycodes 37-40 → `Left/Up/Right/Down` keysym |
|
||||
| Цифры слали мусор | ASCII keycodes → `string(rune(key))` |
|
||||
|
||||
## Маппинг кнопок
|
||||
| Кнопка | Keycode | Gaming Mode (gamescope) | KDE Desktop |
|
||||
|--------|---------|------------------------|-------------|
|
||||
| Красная | 403 | Ctrl+1 (Steam меню) | Super (Win) |
|
||||
| Зелёная | 404 | Escape | Escape |
|
||||
| Жёлтая | 405 | Ctrl+2 (Steam QAM) | Средняя кнопка мыши |
|
||||
| Синяя | 406 | Правый клик | Правый клик |
|
||||
| Back | 461 | Mouse X1 (back) | Mouse X1 (back) |
|
||||
| Enter/OK | 13 | Return | Return |
|
||||
| Ch Up | 33 | PageUp | PageUp |
|
||||
| Ch Down | 34 | PageDown | PageDown |
|
||||
| D-pad Left | 37 | Left | Left |
|
||||
| D-pad Up | 38 | Up | Up |
|
||||
| D-pad Right | 39 | Right | Right |
|
||||
| D-pad Down | 40 | Down | Down |
|
||||
| Play | 415 | XF86AudioPlay | XF86AudioPlay |
|
||||
| Stop | 413 | XF86AudioStop | XF86AudioStop |
|
||||
| Pause | 19 | XF86AudioPause | XF86AudioPause |
|
||||
| Цифры 0-9 | 48-57 | 0-9 | 0-9 |
|
||||
| GUIDE | 458 | Правый клик | Правый клик |
|
||||
| Мышь (тач) | — | mousemove (scaled) | mousemove (scaled) |
|
||||
| Тап | mousedown/up | Left click | Left click |
|
||||
| Скролл | wheel | scroll 4/5 | scroll 4/5 |
|
||||
|
||||
## Определение сессии
|
||||
`isGamescopeSession()` — читает `/proc/*/cmdline`, ищет `kwin_wayland`. Если нет → gamescope.
|
||||
|
||||
## Koordinаты мыши
|
||||
TV шлёт координаты в пространстве 0–1920 × 0–1080.
|
||||
При старте xdotool запрашивается `xdotool getdisplaygeometry` → вычисляется scale.
|
||||
Работает корректно при любом разрешении экрана.
|
||||
|
||||
## Проблемы которые могут вернуться
|
||||
- **xdotool умирает** (write error) → KDE показывает XTest диалог. Разрешить и включить `XwaylandEisNoPrompt=true`.
|
||||
- **TV "service error"** — если висит намертво, cold reboot TV (выдернуть из розетки).
|
||||
- **Бинарь слетает** после `rpm-ostree upgrade` → пересобрать и скопировать.
|
||||
Executable
+171
@@ -0,0 +1,171 @@
|
||||
# HTPC Migration Plan
|
||||
|
||||
> Создано: 2026-05-08. Цель: перенести всё с Windows раздела, настроить эмуляторы, бэкап.
|
||||
|
||||
## Статус
|
||||
- [x] magic4pc установлен и работает (main)
|
||||
- [x] Кнопка назад → Esc в gamescope / x1 в KDE
|
||||
- [ ] EmuDeck установлен (в процессе)
|
||||
- [ ] Эмуляторы настроены
|
||||
- [ ] ROMs добавлены в Steam
|
||||
- [ ] Сейвы перенесены
|
||||
- [ ] Игры с Data/Windows добавлены в Steam
|
||||
- [ ] Бэкап системы
|
||||
- [ ] Удаление Windows раздела
|
||||
|
||||
---
|
||||
|
||||
## 1. EmuDeck — после установки визарда
|
||||
|
||||
### Симлинки ROMs (папки с пробелами → структура EmuDeck)
|
||||
```bash
|
||||
ln -s "/run/media/bazzite/Data/n64 roms" ~/Emulation/roms/n64
|
||||
ln -s "/run/media/bazzite/Data/snes roms" ~/Emulation/roms/snes
|
||||
ln -s "/run/media/bazzite/Data/gba roms" ~/Emulation/roms/gba
|
||||
ln -s "/run/media/bazzite/Data/3ds roms" ~/Emulation/roms/3ds
|
||||
ln -s "/run/media/bazzite/Data/ps2 roms" ~/Emulation/roms/ps2
|
||||
ln -s "/run/media/bazzite/Data/dolphin roms" ~/Emulation/roms/wii
|
||||
ln -s "/run/media/bazzite/Data/cemu roms" ~/Emulation/roms/wiiu
|
||||
ln -s "/run/media/bazzite/Data/mame roms" ~/Emulation/roms/mame
|
||||
ln -s "/run/media/bazzite/Data/sega roms" ~/Emulation/roms/genesis
|
||||
ln -s "/run/media/bazzite/Data/nes" ~/Emulation/roms/nes
|
||||
ln -s "/run/media/bazzite/Data/xbox" ~/Emulation/roms/xbox # Metal Slug 4
|
||||
```
|
||||
|
||||
- [ ] Разобрать дубли: `mame roms` + `mame_roms`, `n64` + `n64 roms`
|
||||
- [ ] Разобрать `Data/unsorted/` — есть PC игры (Skyrim, Portal 2, Rayman и др.) и PS2 (Odin Sphere)
|
||||
|
||||
---
|
||||
|
||||
## 2. Эмуляторы — настройка и конфигурация
|
||||
|
||||
### Уже установлено EmuDeck:
|
||||
- [x] RetroArch (`org.libretro.RetroArch`)
|
||||
- [x] Dolphin (`org.DolphinEmu.dolphin-emu`)
|
||||
- [x] PPSSPP (`org.ppsspp.PPSSPP`)
|
||||
- [x] melonDS (`net.kuribo64.melonDS`) — NDS
|
||||
|
||||
### Нужно установить/проверить:
|
||||
- [ ] **Ryujinx или Yuzu-fork** (Switch) — EmuDeck должен предложить, проверить после визарда
|
||||
- Switch ROMs: пока не найдены на Data (папки nsp/xci нет) — уточнить у Алекса есть ли ромы
|
||||
- [ ] **PCSX2** (PS2) — проверить установил ли EmuDeck
|
||||
- [ ] **Citra / Lime3DS** (3DS) — проверить
|
||||
- [ ] **CEMU** (Wii U) — проверить (есть cemu roms на Data: DKC Tropical Freeze и др.)
|
||||
|
||||
### Конфигурация по эмуляторам:
|
||||
- [ ] **Dolphin** — настроить контроллер (LG Magic Remote), проверить Wii Motion Plus
|
||||
- [ ] **RetroArch** — настроить cores для каждой платформы, hotkeys
|
||||
- [ ] **PPSSPP** — PSP, настроить разрешение upscale для TV
|
||||
- [ ] **CEMU** — Wii U, настроить графику (Vulkan для RX570)
|
||||
- [ ] **Ryujinx/Switch** — prod.keys, title.keys (нужны с реальной консоли)
|
||||
- [ ] **PCSX2** — PS2 BIOS (нужен)
|
||||
- [ ] **melonDS** — NDS BIOS/firmware
|
||||
|
||||
---
|
||||
|
||||
## 3. Добавление игр в Steam
|
||||
|
||||
### Steam ROM Manager (EmuDeck)
|
||||
- [ ] Запустить из Desktop Mode после настройки симлинков
|
||||
- [ ] Включить парсеры для: SNES, N64, GBA, NDS, Wii, Wii U, PS2, PSP, 3DS, Switch, MAME
|
||||
- [ ] Проверить обложки, исправить неправильно распознанные
|
||||
|
||||
### Игры с Data — добавить в Steam вручную как Non-Steam games
|
||||
**`/run/media/bazzite/Data/games/`** (38 игр, уже установлены):
|
||||
- Bayonetta, Cuphead, GTA V, Fallout 4, Metro Exodus, The Witcher 3, Rayman Legends/Origins, Castle Crashers, Brawlhalla, Duck Game, Human Fall Flat, Pummel Party и др.
|
||||
|
||||
**`/run/media/bazzite/Data/steam/steamapps/common/`** (уже Steam игры):
|
||||
- Gang Beasts, Shovel Knight, Stick Fight, Party Animals, Them's Fightin' Herds, Unravel и др.
|
||||
- [ ] Переместить/добавить эту steamapps папку как вторую Steam library
|
||||
|
||||
### Игры с Windows раздела — перенести на Data
|
||||
Папки которые стоит проверить и перенести если нужно:
|
||||
- [ ] Проверить `Windows/Users/mallexxx/AppData/Local/` на наличие установленных игр
|
||||
- [ ] `Data/unsorted/` — Skyrim SE, Portal 2, Rise of Tomb Raider, Rocket League, Ori — решить: установить через Steam или перенести
|
||||
|
||||
---
|
||||
|
||||
## 4. Перенос сейвов (приоритет высокий)
|
||||
|
||||
### RetroArch
|
||||
Источник: `Windows/Users/mallexxx/AppData/Roaming/RetroArch/`
|
||||
Назначение: `~/.var/app/org.libretro.RetroArch/config/retroarch/`
|
||||
- [ ] `saves/` — 14 .srm: Zelda ALTTP, DKC2, DKC3, Banjo-Tooie, SM64, Contra Hard Corps и др.
|
||||
- [ ] `states/` — Aladdin, DKC2, Contra, Golden Axe и др.
|
||||
|
||||
### OpenEmu → RetroArch
|
||||
Источник: `/run/media/bazzite/Data/openemu/`
|
||||
- [ ] `snes9x/battery saves/*.sav` — Chrono Trigger, Lufia, Brain Lord, Dragon View, Actraiser, Zelda ALTTP (~30+ игр)
|
||||
- [ ] `save states/` — GB, GBA, NDS, NES, SNES
|
||||
- Формат `.oesavestate` — уточнить конвертер (возможно совместим с RetroArch напрямую)
|
||||
|
||||
### Dolphin
|
||||
Источник: `Windows/Users/mallexxx/AppData/Roaming/Dolphin Emulator/`
|
||||
Назначение: `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/`
|
||||
- [ ] `GC/USA/`, `GC/EUR/`, `GC/JAP/` — Memory Card
|
||||
- [ ] `Wii/` — NAND (пустой, сейвы Wii утеряны)
|
||||
|
||||
### Citra (3DS)
|
||||
- [ ] `AppData/Roaming/Citra/` → `~/.var/app/org.citra_emu.citra/`
|
||||
|
||||
### С NAS
|
||||
- [ ] `mallexxx.duckdns.org:/mnt/RED_2TB/backup/game/dkc3 103perc save.zip` — DKC3 103% ⭐
|
||||
- [ ] `…/backup/win_2020/…/RetroArch/saves/` — Mortal Kombat II state (нет на Windows)
|
||||
|
||||
### DKC Returns
|
||||
- ❌ Сейвы Wii **утеряны** нигде не найдены. ROM: `Data/dolphin roms/donkey kong country returns.iso`
|
||||
|
||||
---
|
||||
|
||||
## 5. Личные файлы с Windows раздела
|
||||
|
||||
- [ ] `Documents/основание_контроллер_кормушки.SLDPRT` + `сборка…` → NAS
|
||||
- [ ] `Documents/DAVAProject/` — разобраться
|
||||
- [ ] `Documents/AutoHotkey.ahk` + `Desktop/unbind-guide-button.ps1` → сохранить
|
||||
- [ ] `Documents/JoyToKey/` — конфиги
|
||||
- [ ] `AppData/Roaming/Kodi/userdata/` → `~/.kodi/userdata/`
|
||||
|
||||
---
|
||||
|
||||
## 6. Медиа
|
||||
|
||||
- [ ] `Data/видеокассеты-наташа/` → NAS (семейное видео, приоритет!)
|
||||
- [ ] `Data/мультфильмы/` + `Data/сериалы/` → сравнить с NAS `storage/Cartoons/`, убрать дубли
|
||||
- [ ] `Data/movies/` → сравнить с NAS `storage/Movies/`
|
||||
|
||||
---
|
||||
|
||||
## 7. Бэкап системы
|
||||
|
||||
- [ ] Btrfs snapshots → NAS (`btrbk` или `snapper`)
|
||||
- [ ] `~/Emulation/saves/` rsync → NAS по расписанию
|
||||
- [ ] Проверить automount Data в Gaming Mode (gamescope)
|
||||
|
||||
---
|
||||
|
||||
## 8. Удаление Windows раздела (~230GB)
|
||||
|
||||
Условия готовности:
|
||||
- [ ] Все сейвы перенесены и проверены в игре
|
||||
- [ ] Все личные файлы на NAS/Linux
|
||||
- [ ] Kodi настроен
|
||||
- [ ] Бэкап работает
|
||||
|
||||
```bash
|
||||
# fdisk /dev/sdb → удалить раздел → расширить Data или Linux
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Справка — пути эмуляторов на Bazzite (EmuDeck Flatpak)
|
||||
|
||||
| Эмулятор | Saves path |
|
||||
|----------|-----------|
|
||||
| RetroArch | `~/.var/app/org.libretro.RetroArch/config/retroarch/saves/` |
|
||||
| Dolphin | `~/.var/app/org.DolphinEmu.dolphin-emu/data/dolphin-emu/` |
|
||||
| Citra/Lime3DS | `~/.var/app/org.citra_emu.citra/` |
|
||||
| PCSX2 | `~/.var/app/net.pcsx2.PCSX2/config/PCSX2/memcards/` |
|
||||
| RPCS3 | `~/.var/app/net.rpcs3.RPCS3/config/rpcs3/dev_hdd0/` |
|
||||
| PPSSPP | `~/.var/app/org.ppsspp.PPSSPP/config/ppsspp/PSP/SAVEDATA/` |
|
||||
| melonDS | `~/.var/app/net.kuribo64.melonDS/` |
|
||||
| Ryujinx | `~/.var/app/org.ryujinx.Ryujinx/config/Ryujinx/bis/user/save/` |
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
# HTPC — Система (Bazzite Linux)
|
||||
|
||||
## Железо
|
||||
- CPU: Intel Core i7-6800K
|
||||
- RAM: 32 GB
|
||||
- GPU: AMD Radeon RX 570
|
||||
- Подключение к TV: HDMI
|
||||
- TV: LG webOS (192.168.1.75)
|
||||
- HTPC IP: 192.168.1.86
|
||||
|
||||
## ОС
|
||||
- **Bazzite 44** (Fedora-based, immutable OSTree)
|
||||
- Вариант: `bazzite-deck` (Steam Gaming Mode / gamescope)
|
||||
- Пользователь: `bazzite`
|
||||
- Hostname: `htpc`
|
||||
- DNS: резолвится как `htpc` через роутер (192.168.1.1), см. [[router-bishkek-asus]]
|
||||
|
||||
## Режимы запуска
|
||||
- **Gaming Mode (gamescope-session-steam)** — автологин по умолчанию, Steam Big Picture
|
||||
- **KDE Desktop** — переключение из меню Steam → "Switch to Desktop"
|
||||
|
||||
## Автологин
|
||||
Файл: `/etc/gdm/custom.conf`
|
||||
```ini
|
||||
[daemon]
|
||||
AutomaticLoginEnable=True
|
||||
AutomaticLogin=bazzite
|
||||
Session=gamescope-session-steam
|
||||
```
|
||||
|
||||
## Переменные окружения
|
||||
`/etc/environment`:
|
||||
```
|
||||
GAMESCOPE_DISABLE_HDR=1
|
||||
```
|
||||
|
||||
`~/.config/environment.d/gamescope.conf`:
|
||||
```
|
||||
GAMESCOPE_WIDTH=1920
|
||||
GAMESCOPE_HEIGHT=1080
|
||||
GAMESCOPE_REFRESH=60
|
||||
```
|
||||
|
||||
## Разрешение
|
||||
- **1080p @ 60Hz** — рабочий режим
|
||||
- 4K вызывает AMD HDA audio clock bug: пиксельный клок ~594 MHz → HDMI audio 880 Hz вместо 440 Hz
|
||||
|
||||
## Аудио
|
||||
|
||||
### Проблема
|
||||
LG webOS TV по HDMI принимает **только LPCM 2ch**.
|
||||
Поддерживаемые частоты: 32000 / 44100 / 48000 / 96000 / 192000 Hz, 16/20/24 bit.
|
||||
|
||||
**AMD HDA audio clock bug** (RX 570 + 4K@60Hz):
|
||||
При pixel clock ~594 MHz (4K@60Hz) AMD HDMI audio контроллер выдаёт неправильный clock — тон 440 Hz воспроизводится как 880 Hz (в 2 раза выше). Решение — переключиться на **1080p@60Hz** (pixel clock ~148 MHz, bug не воспроизводится).
|
||||
|
||||
### Решение: зафиксировать 1080p
|
||||
`~/.config/environment.d/gamescope.conf`:
|
||||
```
|
||||
GAMESCOPE_WIDTH=1920
|
||||
GAMESCOPE_HEIGHT=1080
|
||||
GAMESCOPE_REFRESH=60
|
||||
```
|
||||
|
||||
### Решение: PipeWire/WirePlumber конфиги
|
||||
|
||||
`~/.config/wireplumber/wireplumber.conf.d/fix-hdmi.conf`:
|
||||
```lua
|
||||
monitor.alsa.rules = [
|
||||
{
|
||||
matches = [{ node.name = "~alsa_output.pci*hdmi*" }]
|
||||
actions = {
|
||||
update-props = {
|
||||
audio.format = "S16LE"
|
||||
audio.rate = 48000
|
||||
session.suspend-timeout-seconds = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
`~/.config/pipewire/pipewire.conf.d/99-hdmi-fix.conf`:
|
||||
```conf
|
||||
context.properties = {
|
||||
default.clock.allowed-rates = [ 44100 48000 ]
|
||||
}
|
||||
```
|
||||
|
||||
### Проверка
|
||||
```bash
|
||||
# Посмотреть активный sink и его параметры:
|
||||
pactl list sinks | grep -A20 "HDMI"
|
||||
|
||||
# Тест тона 440 Hz — должен звучать как ля первой октавы:
|
||||
speaker-test -t sine -f 440 -c 2
|
||||
```
|
||||
|
||||
## OSTree / Обновления
|
||||
- `/usr/local/bin` слетает при `rpm-ostree` upgrade (новый `/usr` overlay)
|
||||
- Бинари держать в `/home/bazzite/` или пересобирать после обновлений
|
||||
- Проверить после апдейта: `systemctl status magic4pc`
|
||||
|
||||
## KDE Xwayland настройки
|
||||
`~/.config/kwinrc`:
|
||||
```ini
|
||||
[Xwayland]
|
||||
EavesdropMode=2
|
||||
XwaylandEisNoPrompt=true
|
||||
```
|
||||
`XwaylandEisNoPrompt=true` — отключает диалог разрешения XTest (нужен для magic4pc/xdotool).
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
# WebOS TV — luna-send via SSH
|
||||
|
||||
TV IP: `192.168.1.75`, user: `root`
|
||||
|
||||
## Проблема
|
||||
`luna-send` пишет вывод в tty, не в stdout. Через SSH без PTY — пусто.
|
||||
|
||||
## Решение — через `script`
|
||||
```bash
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://...\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
## Методы
|
||||
|
||||
### Список запущенных приложений
|
||||
```bash
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.service.applicationmanager/running '{}'\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
### Закрыть приложение
|
||||
```bash
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.service.applicationmanager/closeByAppId '{\"id\":\"APP_ID\"}'\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
### Удалить приложение (dev)
|
||||
```bash
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.appInstallService/dev/remove '{\"id\":\"APP_ID\"}'\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
### Установить ipk
|
||||
```bash
|
||||
scp app.ipk root@192.168.1.75:/tmp/
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.appInstallService/dev/install '{\"id\":\"APP_ID\",\"ipkUrl\":\"/tmp/app.ipk\",\"subscribe\":true}'\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
### Запустить приложение
|
||||
```bash
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -n 1 -f luna://com.webos.applicationManager/launch '{\"id\":\"APP_ID\"}'\" /tmp/o.txt; cat /tmp/o.txt"
|
||||
```
|
||||
|
||||
## Не работает
|
||||
- `ares-install/ares-launch` — требует dev mode (порт 9922)
|
||||
- `listRunningApps` — нет метода, правильно: `running`
|
||||
- `applicationManager/remove` — нет, правильно: `appInstallService/dev/remove`
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
# HTPC
|
||||
|
||||
**IP:** 192.168.1.86
|
||||
**OS:** Bazzite (Linux)
|
||||
|
||||
## Wake on LAN
|
||||
|
||||
**MAC:** `B0:6E:BF:60:6D:64`
|
||||
|
||||
### Скрипты (~/Automation/)
|
||||
|
||||
```bash
|
||||
# Разбудить HTPC
|
||||
python3 ~/Automation/wake-on-lan.py
|
||||
|
||||
# Разбудить или усыпить TV + HTPC
|
||||
python3 ~/Automation/wake-tv-or-sleep.py
|
||||
```
|
||||
|
||||
### Вручную (без скриптов)
|
||||
|
||||
```bash
|
||||
# через brew
|
||||
brew install wakeonlan
|
||||
wakeonlan B0:6E:BF:60:6D:64
|
||||
|
||||
# через Python
|
||||
python3 -c "
|
||||
import socket
|
||||
mac = 'B06EBF606D64'
|
||||
pkt = bytes.fromhex('F'*12 + mac*16)
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
s.sendto(pkt, ('255.255.255.255', 9))
|
||||
print('Magic packet sent')
|
||||
"
|
||||
```
|
||||
|
||||
### Проверка
|
||||
После отправки пакета подождать ~30 сек:
|
||||
```bash
|
||||
ping -c 5 192.168.1.86
|
||||
```
|
||||
|
||||
### Если не просыпается
|
||||
WoL должен быть включён в BIOS/UEFI. Проверить настройки на HTPC (пока он живой):
|
||||
```bash
|
||||
sudo ethtool enp<X> # смотреть Wake-on: g
|
||||
sudo ethtool -s enp<X> wol g # включить
|
||||
```
|
||||
|
||||
|
||||
## Виртуальная клавиатура
|
||||
|
||||
Установлен **vboard** (fork mallexxx/vboard, ветка `htpc-bazzite-patches`).
|
||||
|
||||
Полная дока с патчами и известными проблемами: [[virtual-keyboard-bazzite]]
|
||||
Executable
+222
@@ -0,0 +1,222 @@
|
||||
# Magic4PC — WebOS Client
|
||||
|
||||
Управление LG MagicRemote как мышью/клавиатурой на HTPC через Bazzite.
|
||||
|
||||
## Архитектура
|
||||
|
||||
- **TV (WebOS)** — app `me.wouterdek.magic4pc` + JS-сервис `me.wouterdek.magic4pc.service`
|
||||
- App: React/Enact UI, слушает кнопки пульта, отправляет в сервис через luna
|
||||
- Сервис: Node.js, бродкастит UDP, принимает подключение от Go-клиента на HTPC
|
||||
- **HTPC (Bazzite)** — Go-клиент `~/magic4pc/`, сервис `magic4pc.service`
|
||||
- Получает UDP-пакеты от TV, инжектирует ввод через `/dev/uinput`
|
||||
- `inputBackKey()` → Esc в gamescope, x1 в KDE
|
||||
- Репо: https://github.com/mallexxx/magic4pc_altclient (ветка `main`)
|
||||
|
||||
## Исходники
|
||||
|
||||
| Компонент | Путь |
|
||||
|-----------|------|
|
||||
| WebOS UI | `~/Developer/magic4pc/webos/src/views/MainPanel.js` |
|
||||
| WebOS сервис | `~/Developer/magic4pc/webos/service/m4p_service.js` |
|
||||
| Go клиент | `~/Developer/magic4pc_altclient/` |
|
||||
| HTPC бинарник | `~/magic4pc/magic4pc` |
|
||||
| HTPC сервис | `~/.config/systemd/user/magic4pc.service` (HTPC) |
|
||||
| run.sh | `~/magic4pc/run.sh` (HTPC) |
|
||||
|
||||
## Кнопки пульта (keyCode)
|
||||
|
||||
| Код | Кнопка | Действие |
|
||||
|-----|--------|----------|
|
||||
| 406 | 🔵 Синяя | Открыть панель настроек |
|
||||
| 461 | Back | Esc (gamescope) / x1 (KDE) |
|
||||
| 458 | Guide | системный (не перехватывается) |
|
||||
| 403 | 🔴 Красная | передаётся на HTPC |
|
||||
| 415 | Play | передаётся на HTPC |
|
||||
| 19 | Pause | передаётся на HTPC |
|
||||
|
||||
## Панель настроек (синяя кнопка)
|
||||
|
||||
- **Статус** — Connected to IP:port / Waiting / Service disabled
|
||||
- **v1.1.0 (YYYY-MM-DD HH:MM)** — версия + дата сборки справа от статуса
|
||||
- **Input source** — выбор HDMI входа
|
||||
- **Enable / Disable** — старт/стоп сервиса
|
||||
- **Default app on exit** — приложение которое запускается при выходе из magic4pc (None / Last used / конкретное)
|
||||
- **Show Log / Hide Log** — лог событий и ошибок поверх видео
|
||||
|
||||
## Версия сборки
|
||||
|
||||
Версия отображается как `1.1.0 (YYYY-MM-DD HH:MM)` — дата инжектируется webpack автоматически при каждой сборке:
|
||||
```js
|
||||
// config/webpack.config.js
|
||||
'process.env.BUILD_DATE': JSON.stringify(new Date().toISOString().slice(0, 16).replace('T', ' '))
|
||||
```
|
||||
|
||||
## Сборка WebOS app
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc/webos
|
||||
NODE_OPTIONS=--openssl-legacy-provider npm run build
|
||||
```
|
||||
|
||||
> ⚠️ Требует `--openssl-legacy-provider` — старый webpack несовместим с Node 25.
|
||||
|
||||
## Сборка IPK
|
||||
|
||||
```bash
|
||||
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
|
||||
```
|
||||
|
||||
> ⚠️ Оба аргумента `dist/ service/` обязательны — иначе сервис не попадёт в IPK.
|
||||
> ⚠️ `npm run package` = `ares-package -n` (unsigned) — **не использовать**, TV отклоняет.
|
||||
|
||||
## Деплой на TV (192.168.1.75)
|
||||
|
||||
### Правильный способ — deploy.sh
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc/webos
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
Скрипт делает всё: build → package → scp → close → remove → install → launch.
|
||||
|
||||
Использует `~/Automation/tv-luna-send.sh` для close/remove/launch.
|
||||
Для install (`-i` subscribe) — прямой ssh+script с polling на `"state":"installed"`.
|
||||
|
||||
> ⚠️ **Не использовать `ares-install` / `ares-launch`** — не ждут завершения, работают ненадёжно.
|
||||
> ⚠️ `luna-send` без PTY молчит — см. [[tv-luna-send]].
|
||||
|
||||
<details><summary>Ручной деплой</summary>
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc/webos
|
||||
NODE_OPTIONS=--openssl-legacy-provider npm run build
|
||||
/Users/admin/webOS_TV_SDK/CLI/bin/ares-package dist/ service/ --outdir .
|
||||
scp me.wouterdek.magic4pc_1.1.0_all.ipk root@192.168.1.75:/tmp/magic4pc.ipk
|
||||
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.service.applicationmanager/closeByAppId '{"id":"me.wouterdek.magic4pc"}' || true
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.appInstallService/dev/remove '{"id":"me.wouterdek.magic4pc"}' || true
|
||||
sleep 2
|
||||
|
||||
# install — через прямой script (luna-send -i не работает через враппер)
|
||||
ssh root@192.168.1.75 "script -q -c \"luna-send -i -f luna://com.webos.appInstallService/dev/install '{\\\"id\\\":\\\"me.wouterdek.magic4pc\\\",\\\"ipkUrl\\\":\\\"/tmp/magic4pc.ipk\\\",\\\"subscribe\\\":true}'\" /tmp/install.txt &
|
||||
for i in \$(seq 1 30); do sleep 1; grep -q '\"state\":\"installed\"' /tmp/install.txt 2>/dev/null && break; done
|
||||
kill %1 2>/dev/null; grep -v '^Script ' /tmp/install.txt; rm -f /tmp/install.txt"
|
||||
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.applicationManager/launch '{"id":"me.wouterdek.magic4pc"}'
|
||||
```
|
||||
</details>
|
||||
|
||||
### Проверка статуса сервиса
|
||||
|
||||
```bash
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://me.wouterdek.magic4pc.service/query '{}'
|
||||
```
|
||||
|
||||
Ожидаемый результат: `serviceActive: true`, `broadcastAdsActive: true`.
|
||||
|
||||
## Деплой Go-клиента на HTPC
|
||||
|
||||
```bash
|
||||
cd ~/Developer/magic4pc_altclient
|
||||
GOOS=linux GOARCH=amd64 go build -o magic4pc_new .
|
||||
scp magic4pc_new bazzite@192.168.1.86:~/magic4pc/
|
||||
ssh bazzite@192.168.1.86 "
|
||||
systemctl --user stop magic4pc
|
||||
mv ~/magic4pc/magic4pc_new ~/magic4pc/magic4pc
|
||||
systemctl --user start magic4pc
|
||||
"
|
||||
```
|
||||
|
||||
## HTPC сервис
|
||||
|
||||
```bash
|
||||
ssh bazzite@192.168.1.86 "systemctl --user status magic4pc"
|
||||
ssh bazzite@192.168.1.86 "systemctl --user restart magic4pc"
|
||||
```
|
||||
|
||||
> `enable` не используется — autostart через EIM на стороне TV.
|
||||
|
||||
## Auto-launch при boot/wake
|
||||
|
||||
Magic4pc автоматически запускает выбранный app при включении TV.
|
||||
|
||||
### Логика
|
||||
|
||||
- **Boot** — `/tmp` чистится → нет `run-state` → `freshStart=true` → запускает app
|
||||
- **Wake** — init.d при Suspend удаляет `run-state` → при wake `freshStart=true` → запускает app
|
||||
- **Ручной запуск** — `run-state=running` уже есть → `freshStart=false` → ничего не запускает ✅
|
||||
|
||||
### Файлы persistent storage
|
||||
|
||||
`PERSISTENT_DIR = /media/developer/apps/usr/palm/services/me.wouterdek.magic4pc.service`
|
||||
|
||||
| Файл | Где | Что |
|
||||
|------|-----|-----|
|
||||
| `magic4pc-settings` | `PERSISTENT_DIR/` | Выбранный app: appId / `__last_used__` / `none` |
|
||||
| `magic4pc-last-app` | `PERSISTENT_DIR/` | Последний foreground app |
|
||||
| `magic4pc-run-state` | `/tmp/` | `running` = уже запускался после boot/wake |
|
||||
|
||||
### Init.d скрипт
|
||||
|
||||
Файл на TV: `/var/lib/webosbrew/init.d/magic4pc`
|
||||
Исходник: `tv-scripts/init.d-magic4pc.sh` в репо
|
||||
|
||||
```bash
|
||||
# Деплой
|
||||
scp tv-scripts/init.d-magic4pc.sh root@192.168.1.75:/var/lib/webosbrew/init.d/magic4pc
|
||||
ssh root@192.168.1.75 "chmod +x /var/lib/webosbrew/init.d/magic4pc"
|
||||
# Применяется после ребута TV
|
||||
```
|
||||
|
||||
> ⚠️ Всегда править в репо, не на TV напрямую.
|
||||
|
||||
## Отладка
|
||||
|
||||
```bash
|
||||
# Лог UI (appendLogPersist пишет сюда)
|
||||
ssh root@192.168.1.75 "tail -30 /tmp/m4p_debug.log"
|
||||
|
||||
# Run-state
|
||||
ssh root@192.168.1.75 "cat /tmp/magic4pc-run-state"
|
||||
|
||||
# Settings / last-app
|
||||
ssh root@192.168.1.75 "cat $PERSISTENT_DIR/magic4pc-settings"
|
||||
ssh root@192.168.1.75 "cat $PERSISTENT_DIR/magic4pc-last-app"
|
||||
```
|
||||
|
||||
> ⚠️ `appendLog()` пишет **только в UI**. В файл попадает только `appendLogPersist()`. При отладке использовать `appendLogPersist`.
|
||||
|
||||
## Back и клавиатура — особенности WebOS
|
||||
|
||||
**Как работает Back когда открыта системная клавиатура:**
|
||||
|
||||
- **Back #1** — система поглощает полностью: закрывает клавиатуру, вызывает `Input.onClose`. DOM `keydown` **не приходит**, `onButtonDown` **не вызывается**.
|
||||
- **Back #2** — приходит в DOM → `onButtonDown`.
|
||||
|
||||
**Следствие:** нельзя детектировать первый Back через `keydown`. Единственный способ — флаг в `onActivate`.
|
||||
|
||||
**Реализованный фикс** (`_kbWasOpen` в `MainPanel.js`):
|
||||
```js
|
||||
// Input.onActivate:
|
||||
this._kbWasOpen = true;
|
||||
|
||||
// onButtonDown при Back:
|
||||
if (this.state.wolMacActive || this._kbWasOpen) {
|
||||
this._kbWasOpen = false;
|
||||
return; // не закрывать панель
|
||||
}
|
||||
```
|
||||
|
||||
**Что не работает на WebOS:**
|
||||
- `Popup.noAutoDismiss` — Back закрывает через `onButtonDown`, не через Popup.onClose
|
||||
- Таймаут (`Date.now() < ts + 1000ms`) — ненадёжно
|
||||
- Polling `document.activeElement` — фокус никогда не переходит на `INPUT`, клавиатура — системный overlay
|
||||
|
||||
## Известные проблемы
|
||||
|
||||
- **Guide (458)** — перехватывается WebOS системно. Нет решения.
|
||||
- **listApps** — `dev/listApps` недоступен без dev mode. Используется `applicationManager/listApps`.
|
||||
- **Self-launch** — фильтруется в `checkAutoLaunch` по appId.
|
||||
- **HDMI как last-app** — при `__last_used__` и последнем активном HDMI не запустит ничего полезного. Решение: выбрать конкретный app.
|
||||
- **`ares-install` ненадёжен** — молчит без PTY, не ждёт завершения. Использовать `luna-send dev/install` через script.
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
# Музыкальный плеер с TrueNAS на Android
|
||||
|
||||
**Статус:** 📋 Планируется
|
||||
**Дата:** 2026-05-10
|
||||
|
||||
## Задача
|
||||
Поднять стриминг музыки с TrueNAS (`/mnt/RED_2TB/storage/Music/`) на Android-устройства.
|
||||
|
||||
## Варианты
|
||||
|
||||
### ✅ Вариант 1 — Navidrome + Symfonium (рекомендован)
|
||||
- **Сервер:** [Navidrome](https://www.navidrome.org/) — лёгкий музыкальный сервер, Docker-образ
|
||||
- **Плеер Android:** [Symfonium](https://symfonium.app/) — Subsonic API, офлайн-кэш, теги, обложки
|
||||
- Работает через интернет по порту, можно за nginx reverse proxy
|
||||
- Docker уже есть: `/mnt/RED_2TB/docker/`
|
||||
|
||||
### Вариант 2 — Jellyfin + Finamp
|
||||
- **Сервер:** Jellyfin (Docker) — универсален (видео, фото, музыка)
|
||||
- **Плеер Android:** [Finamp](https://github.com/jmshrv/finamp) — опенсорс
|
||||
- Чуть тяжелее Navidrome
|
||||
|
||||
### Вариант 3 — SMB напрямую
|
||||
- Без сервера, VLC или Solid Explorer играют по SMB
|
||||
- Только для домашней сети — по интернету медленно и небезопасно
|
||||
|
||||
## Следующие шаги
|
||||
- [ ] Поднять Navidrome в Docker на TrueNAS
|
||||
- [ ] Пробросить порт / настроить nginx proxy
|
||||
- [ ] Установить Symfonium на Android, подключить
|
||||
Executable
+336
@@ -0,0 +1,336 @@
|
||||
---
|
||||
tags:
|
||||
- raspberry-pi
|
||||
- nas
|
||||
- openmediavault
|
||||
- how-to
|
||||
created: '2026-05-11'
|
||||
updated: '2026-05-12'
|
||||
status: hermes-pending
|
||||
ip: 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 отключён (modprobe blacklist brcmfmac/brcmutil) |
|
||||
| 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 — Перенос данных | 🔲 | |
|
||||
| 11 — Hermes агент Кракен | 🚧 | Dockerfile + config готовы, нужно: заполнить .env, HA token, собрать образ |
|
||||
| 12 — Obsidian sync (Taiga↔Kraken↔Eagle) | 🔲 | Настроить синхронизацию vault между всеми тремя агентами |
|
||||
|
||||
---
|
||||
|
||||
## Железо
|
||||
|
||||
- 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.local
|
||||
```
|
||||
|
||||
Обновление системы:
|
||||
```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.local`)
|
||||
- Логин: `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.14>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 |
|
||||
| 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
|
||||
|
||||
---
|
||||
|
||||
## Шаг 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/`
|
||||
|
||||
**Расписание** (crontab kraken-пользователя):
|
||||
- `0 4 * * *` UTC (10:00 GMT+6) → `/usr/local/bin/tm-start.sh` — поднять контейнер
|
||||
- `0 16 * * *` UTC (22:00 GMT+6) → `/usr/local/bin/tm-stop.sh` — остановить контейнер
|
||||
- `restart: no` — при загрузке Pi не стартует автоматически
|
||||
|
||||
**Credentials:**
|
||||
- Пользователь: `timemachine`
|
||||
- Пароль: `timemachine` ⚠️ сменить позже
|
||||
|
||||
**Подключение с Mac:**
|
||||
1. Finder → `⌘K` → `smb://192.168.1.14`
|
||||
2. Логин: `timemachine` / `timemachine`
|
||||
3. System Preferences → Time Machine → Add Disk → выбрать `kraken`
|
||||
|
||||
Лог cron: `/var/log/timemachine-cron.log`
|
||||
|
||||
---
|
||||
|
||||
## Шаг 10 — Перенос данных
|
||||
|
||||
### Фильмы с Mac на NAS
|
||||
```bash
|
||||
rsync -avh --progress /path/to/movies/ kraken@kraken.local:/srv/.../media/movies/
|
||||
```
|
||||
|
||||
### Time Machine
|
||||
> ⚠️ Старый TM-бэкап перенести нельзя напрямую — TM привязывает бэкап к конкретному диску/хосту.
|
||||
> Начать новый бэкап на NAS, старый HDD хранить как архив или отформатировать после нескольких успешных новых бэкапов.
|
||||
|
||||
---
|
||||
|
||||
## Шаг 11 — Hermes агент Кракен
|
||||
|
||||
### Файлы
|
||||
```
|
||||
/home/kraken/hermes/
|
||||
Dockerfile — образ на базе node:20-slim + hermes-agent + obsidian-mcp
|
||||
docker-compose.yml — restart: unless-stopped, network_mode: host
|
||||
.env — API ключи (заполнить вручную)
|
||||
config.yaml → копируется в /srv/.../docker/hermes/config/config.yaml
|
||||
```
|
||||
|
||||
### Модели (проверено 2026-05-12)
|
||||
Бесплатные модели с tool calling на OpenRouter:
|
||||
| Модель | Статус |
|
||||
|--------|--------|
|
||||
| `nvidia/nemotron-3-super-120b-a12b:free` | ✅ работает |
|
||||
| `openrouter/free` | ✅ fallback (авто-роутинг) |
|
||||
| `deepseek/deepseek-chat-v3-0324:free` | ❌ 404 |
|
||||
| `qwen/qwen3-235b-a22b:free` | ❌ 404 |
|
||||
| `google/gemma-4-31b-it:free` | ❌ 429 rate limit |
|
||||
|
||||
**Primary**: `nvidia/nemotron-3-super-120b-a12b:free` (262K ctx, tools ✅)
|
||||
**Auxiliary/Fallback**: `openrouter/free`
|
||||
**Рекомендуется**: добавить `GOOGLE_API_KEY` → Gemini Flash как auxiliary
|
||||
|
||||
### Telegram бот
|
||||
- Имя: Кракен
|
||||
- Bot: [@kraken_htpc_bot](https://t.me/kraken_htpc_bot)
|
||||
- Token: `8750114596:AAH625OBSdb_Bn7ZSwshjDD3mbENnkSRYag`
|
||||
|
||||
### Toolsets
|
||||
`hermes-cli, terminal, file, web, web_crawler, memory, spotify, homeassistant`
|
||||
|
||||
### Деплой (после заполнения .env)
|
||||
```bash
|
||||
# Заполнить ключи:
|
||||
nano /home/kraken/hermes/.env
|
||||
# OPENROUTER_API_KEY=sk-or-...
|
||||
# GOOGLE_API_KEY=...
|
||||
# HASS_TOKEN=... (создать в HA UI → Profile → Long-Lived Access Tokens)
|
||||
|
||||
# Собрать и запустить:
|
||||
cd /home/kraken/hermes
|
||||
sudo docker compose build
|
||||
sudo docker compose up -d
|
||||
|
||||
# Проверить:
|
||||
sudo docker logs hermes-kraken --tail 20
|
||||
```
|
||||
|
||||
### TODO
|
||||
- [ ] Заполнить .env (OPENROUTER_API_KEY, GOOGLE_API_KEY)
|
||||
- [ ] Настроить HA → создать Long-Lived token → вписать в HASS_TOKEN
|
||||
- [ ] Собрать и запустить контейнер
|
||||
- [ ] Настроить obsidian-mcp (vault path = /vault)
|
||||
- [ ] Перенести Spotify auth с Eagle (или запарить заново)
|
||||
|
||||
---
|
||||
|
||||
## Шаг 12 — Obsidian sync (Taiga ↔ Kraken ↔ Eagle)
|
||||
|
||||
Все три агента должны работать с одним vault. Варианты:
|
||||
- **Git sync** — vault в git repo, каждый агент делает pull/push
|
||||
- **rsync** — периодическая синхронизация через SSH
|
||||
- **Syncthing** — p2p sync без облака
|
||||
|
||||
Текущее состояние vault:
|
||||
- Eagle (Mac): `~/obsidian/` — git repo, auto-commit 23:00
|
||||
- Taiga (TrueNAS): `/mnt/RED_2TB/storage/obsidian/` — read-only mount
|
||||
- Kraken (RPi): `/vault` — пока не подключён
|
||||
|
||||
**Следующие шаги:**
|
||||
- [ ] Определить схему sync (git vs syncthing vs rsync)
|
||||
- [ ] Настроить write-доступ на Тайге и Кракене
|
||||
- [ ] Автоматический pull на всех агентах при изменениях
|
||||
|
||||
---
|
||||
|
||||
## Уроки (что пошло не так при установке)
|
||||
|
||||
- **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/
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
# Роутер Бишкек — ASUS RT-AC68U
|
||||
|
||||
## Основное
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Модель | ASUS RT-AC68U |
|
||||
| IP | 192.168.1.1 |
|
||||
| Login | admin |
|
||||
| SSH | включён (dropbear) |
|
||||
| SSH auth | ключ `~/.ssh/id_rsa` (mallexxx@Alexeys-MBP) |
|
||||
|
||||
## SSH доступ
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_rsa admin@192.168.1.1
|
||||
```
|
||||
|
||||
Ключ хранится в `/home/root/.ssh/authorized_keys` на роутере.
|
||||
|
||||
## DNS конфигурация
|
||||
|
||||
### Upstream DNS (WAN)
|
||||
- Primary: `94.140.14.14` (AdGuard DNS)
|
||||
- Secondary: `94.140.15.15` (AdGuard DNS)
|
||||
|
||||
### DHCP DNS для клиентов
|
||||
Клиенты получают IP роутера (`192.168.1.1`) как единственный DNS-сервер.
|
||||
Это позволяет dnsmasq на роутере резолвить локальные имена.
|
||||
|
||||
> ⚠️ **Было**: `dhcp_dns1_x=4.4.4.4` — клиенты шли напрямую в интернет, локальные имена не резолвились. Убрано 2026-05-10.
|
||||
|
||||
## Локальные DNS имена
|
||||
|
||||
Настроено в `/jffs/configs/dnsmasq.conf.add`:
|
||||
|
||||
```
|
||||
# Static local hostnames
|
||||
address=/htpc/192.168.1.86
|
||||
address=/tv/192.168.1.75
|
||||
```
|
||||
|
||||
Динамические имена из DHCP leases резолвятся автоматически (Mac, MacBookPro, LGwebOSTV и др.).
|
||||
|
||||
## Устройства в сети
|
||||
|
||||
| Имя | IP | MAC | Примечание |
|
||||
|-----|----|-----|------------|
|
||||
| htpc | 192.168.1.86 | — | Bazzite, статический IP, RX 570 |
|
||||
| tv / LGwebOSTV | 192.168.1.75 | ac:5a:f0:25:11:c6 | LG TV |
|
||||
| Mac | 192.168.1.57 | 5a:fe:e7:bb:b3:d1 | |
|
||||
| MacBookPro | 192.168.1.43 | 76:88:0d:b9:6a:cd | |
|
||||
| zhimi-airpurifier (1) | 192.168.1.58 | b4:04:29:38:6a:63 | Xiaomi очиститель воздуха |
|
||||
| zhimi-airpurifier (2) | 192.168.1.59 | 64:90:c1:f2:cb:13 | Xiaomi очиститель воздуха |
|
||||
| Galaxy-S23 | 192.168.1.96 | 3a:2f:09:6e:49:1e | |
|
||||
|
||||
## Полезные команды
|
||||
|
||||
```bash
|
||||
# Проверить DNS резолвинг локальных имён
|
||||
dig @192.168.1.1 htpc +short
|
||||
dig @192.168.1.1 tv +short
|
||||
|
||||
# Посмотреть DHCP leases
|
||||
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 "cat /tmp/dnsmasq.leases"
|
||||
|
||||
# Перезапустить dnsmasq
|
||||
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 "service restart_dnsmasq"
|
||||
|
||||
# Показать nvram DNS настройки
|
||||
ssh -i ~/.ssh/id_rsa admin@192.168.1.1 "nvram show | grep -E '^(dhcp_dns|wan_dns|wan0_dns)'"
|
||||
```
|
||||
|
||||
## Кастомный dnsmasq
|
||||
|
||||
Файл: `/jffs/configs/dnsmasq.conf.add`
|
||||
|
||||
```
|
||||
address=/snu.lge.com.usgcac.cdnetworks.net/snu.lge.com/su.lge.com/192.168.1.1
|
||||
|
||||
# Static local hostnames
|
||||
address=/htpc/192.168.1.86
|
||||
address=/tv/192.168.1.75
|
||||
```
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
# Музыка на SD-карту колонки
|
||||
|
||||
*Обновлено: 2026-05-12*
|
||||
|
||||
## Рабочие папки (Mac)
|
||||
- `~/Downloads/music-merged/` — итоговая папка для записи на SD (309+ треков, 26+ папок)
|
||||
- `~/Downloads/music-sd/` — новые треки подборки (не было на SD)
|
||||
- `~/Downloads/music-sd-backup-2026-05-12/` — бэкап оригинального содержимого SD
|
||||
- `~/Downloads/music/` — полная коллекция (~156 треков, не все идут на SD)
|
||||
|
||||
## Структура на SD
|
||||
Папка `Детские/` — советские мультяшные и детские песни.
|
||||
Все остальные артисты — **отдельные папки**, даже с 1 треком.
|
||||
|
||||
## Что входит в подборку
|
||||
| Артист | Кол-во | Примечания |
|
||||
|--------|--------|------------|
|
||||
| Король и Шут | 75 | Полный набор (старый SD + новые) |
|
||||
| КняZz | 18 | Все скачанные |
|
||||
| Детские | 160+ | Советские мультяшные |
|
||||
| Агата Кристи | 7 | Без: Сердцебиение, Секрет, Пуля, Нисхождение, Декаданс, В интересах революции |
|
||||
| Наутилус Помпилиус | 5 | |
|
||||
| Высоцкий | 6 | Сказочные/приключенческие + Козёл отпущения |
|
||||
| Ляпис Трубецкой | 6 | Студийные версии (не концертные) |
|
||||
| Жуки | 3 | Батарейка, Танкист, Влечение |
|
||||
| Любэ | 3 | Конь, Там за туманами, Скворцы |
|
||||
| Сектор Газа | 4 | Лирика, Туман + Демобилизация, Пора домой |
|
||||
| Саундтреки | 2 | He's a Pirate, Harry Potter Main Theme |
|
||||
| Тамара Миансарова | 1 | Чёрный кот (оригинал 1963, не Браво!) |
|
||||
| Андрей Миронов | 3 | Бабочка, Белеет мой парус, Остров невезения |
|
||||
| Пионерлагерь Пыльная Радуга | 2 | Бемби, Дорога добра |
|
||||
| Little Big | 1 | Skibidi |
|
||||
| Серьга | 1 | Живёт моя отрада |
|
||||
| Ундервуд | 1 | Вдоль по питерской |
|
||||
| Руки вверх | 2 | |
|
||||
| Green Apelsin | 2 | |
|
||||
| Чичерина | 2 | |
|
||||
| Юрий Никулин | 3 | |
|
||||
| Хабиб | 1 | Ягода малинка |
|
||||
| Женя Трофимов | 1 | Первая Любовь |
|
||||
| Plamenev | 3 | |
|
||||
|
||||
## Правила сортировки
|
||||
- Из `Детские/` **выносить** в отдельные папки: Сектор Газа, Серьга, Ундервуд, Андрей Миронов, Пионерлагерь Пыльная Радуга, Little Big, Руки вверх
|
||||
- Файлы формата `Артист - Название.mp3` → разбивать по папкам автоматически
|
||||
- КиШ: убирать префикс "Король и Шут - " из имён файлов
|
||||
|
||||
## Что НЕ вошло (есть в ~/Downloads/music/)
|
||||
КняZz (все вошли), Классика, Муслим Магомаев, Мельница, Ария, Iron Maiden, Jethro Tull, Машина Времени, Пикник, Аквариум, Би-2, ДДТ, Чайф, Сплин, Визбор, Окуджава, Камбурова, Мгзавреби, Слава КПСС, Otava Yo, The Hatters, Несчастный случай, Калинов Мост, Канцлер Ги
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
# TrueNAS — Домашний NAS
|
||||
|
||||
## Основное
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|------------------------------------|
|
||||
| Версия | TrueNAS SCALE 24.10 |
|
||||
| Web UI | https://mallexxx.duckdns.org |
|
||||
| Web UI (IP) | http://90.189.160.148 |
|
||||
| SSH | truenas_admin@mallexxx.duckdns.org |
|
||||
| SSH (IP) | truenas_admin@90.189.160.148 |
|
||||
| SSH-ключ | ~/.ssh/id_rsa |
|
||||
|
||||
## Подключение
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/id_rsa truenas_admin@mallexxx.duckdns.org
|
||||
```
|
||||
|
||||
## Пул и датасеты
|
||||
|
||||
Пул: RED_2TB (ZFS)
|
||||
Точка монтирования: /mnt/RED_2TB/
|
||||
|
||||
| Датасет | Путь | Назначение |
|
||||
|---------------|-------------------------------|-----------------------|
|
||||
| storage/ | /mnt/RED_2TB/storage/ | Общее хранилище |
|
||||
| backup/ | /mnt/RED_2TB/backup/ | Резервные копии |
|
||||
| Photos/ | /mnt/RED_2TB/Photos/ | Фотографии |
|
||||
| TimeMachine/ | /mnt/RED_2TB/TimeMachine/ | Бэкапы macOS |
|
||||
| Edu/ | /mnt/RED_2TB/Edu/ | Учебные материалы |
|
||||
| storage/git/ | /mnt/RED_2TB/storage/git/ | Git-репозитории |
|
||||
|
||||
## ⚠️ Важно: boot-pool не выживает после обновления
|
||||
|
||||
/home и /root находятся на boot-pool и **стираются при обновлении TrueNAS**.
|
||||
|
||||
Всё важное (конфиги, ключи, скрипты) должно лежать в /mnt/RED_2TB/,
|
||||
а не в /home/truenas_admin/ или /root/.
|
||||
|
||||
Типичные жертвы:
|
||||
- SSH authorized_keys в /home
|
||||
- Cron jobs, написанные в /etc
|
||||
- Любые файлы вне /mnt/RED_2TB/
|
||||
Executable
+118
@@ -0,0 +1,118 @@
|
||||
# TrueNAS — инфраструктура
|
||||
|
||||
> Обновлено: 2026-04-30
|
||||
|
||||
## Доступ
|
||||
|
||||
- **Host (local):** `192.168.2.197`
|
||||
- **Host (external):** `mallexxx.duckdns.org` (DuckDNS, иногда слетает резолв — fallback на 192.168.2.197)
|
||||
- **SSH:** `truenas_admin@mallexxx.duckdns.org -i ~/.ssh/id_rsa`
|
||||
- **Web UI:** http://truenas.mallexxx.duckdns.org
|
||||
- **Portainer:** https://portainer.mallexxx.duckdns.org
|
||||
|
||||
## Пользователи и группы (ключевые)
|
||||
|
||||
| uid | Имя | gid | Назначение |
|
||||
|-----|-----|-----|------------|
|
||||
| 950 | truenas_admin | 950 | SSH-пользователь, управление docker |
|
||||
| 911 | transdamon | 911 | Процесс Transmission внутри контейнера |
|
||||
| 921 | transmission | 921 | Старый пользователь (не используется контейнером) |
|
||||
| 3000 | nas_users | 3000 | Общая группа доступа к NAS |
|
||||
|
||||
## Структура папок
|
||||
|
||||
```
|
||||
/mnt/RED_2TB/
|
||||
├── docker/ ← конфиги docker-контейнеров (бэкапятся → mailru-crypt:)
|
||||
│ ├── caddy/
|
||||
│ ├── filebrowser/
|
||||
│ ├── ha/ ← Home Assistant
|
||||
│ ├── hermes/ ← Hermes-Taiga
|
||||
│ ├── homeassistant/
|
||||
│ ├── immich/
|
||||
│ ├── inpx-web/
|
||||
│ ├── inpxer/
|
||||
│ ├── mbusd/
|
||||
│ ├── modbus-bridge/
|
||||
│ ├── mosquitto/
|
||||
│ ├── nodered/
|
||||
│ ├── portainer/
|
||||
│ ├── python/
|
||||
│ ├── rclone/
|
||||
│ ├── ser2net/
|
||||
│ ├── transmission/ ← конфиг Transmission (settings.json, torrents, resume...)
|
||||
│ ├── vless-proxy/
|
||||
│ ├── watchtower/
|
||||
│ ├── webdav/
|
||||
│ └── zigbee2mqtt/
|
||||
├── storage/
|
||||
│ ├── Downloads/ ← данные торрентов (монтируется в контейнер как /mnt/storage)
|
||||
│ │ ├── transmission/ ← старый путь конфига (больше не используется)
|
||||
│ │ └── [медиафайлы]
|
||||
│ └── obsidian/ ← vault (read-only для hermes-taiga)
|
||||
├── backup/ ← ручные бэкапы (бэкапятся → mailru-crypt:)
|
||||
│ └── transmission-config/ ← снапшот конфига от 2026-04-30
|
||||
├── Photos/ ← фото (бэкапятся → mailru:Photos/Photos)
|
||||
├── old-bu/ ← старый архив (бэкапятся → mailru:Photos/old-bu)
|
||||
└── immich-photos-upload/ ← библиотека Immich (бэкапятся → mailru:Photos/immich)
|
||||
```
|
||||
|
||||
## NFSv4 ACL — важно
|
||||
|
||||
TrueNAS использует **NFSv4 ACL**, а не стандартный POSIX chmod/chown.
|
||||
- `ls -la` показывает `----------` даже если ACL есть → всегда проверять через `midclt call filesystem.getacl <path>`
|
||||
- Добавить запись: `midclt call filesystem.setacl '{...}'`
|
||||
- `truenas_admin` не имеет passwordless sudo → root-операции только через midclt или TrueNAS UI
|
||||
|
||||
## Docker-контейнеры
|
||||
|
||||
| Контейнер | Image | Порт | Домен |
|
||||
|-----------|-------|------|-------|
|
||||
| transmission | linuxserver/transmission:latest | 9091, 51413 | transmission.mallexxx.duckdns.org |
|
||||
| hermes-taiga | hermes-taiga:latest | — | — |
|
||||
| vless-proxy | teddysun/xray:latest | — | — |
|
||||
| filebrowser | filebrowser/filebrowser:latest | — | — |
|
||||
| webdav | hacdias/webdav:latest | — | webdav.mallexxx.duckdns.org |
|
||||
| homeassistant | home-assistant:stable | 8123 | mallexxx.duckdns.org |
|
||||
| immich-server | immich-app/immich-server:release | 2283 | immich.mallexxx.duckdns.org |
|
||||
| immich-postgres | tensorchord/pgvecto-rs:pg14-v0.2.0 | — | — |
|
||||
| immich-redis | redis:7 | — | — |
|
||||
| nodered | nodered/node-red:latest | 1880 | nodered.mallexxx.duckdns.org |
|
||||
| mosquitto | eclipse-mosquitto:latest | — | — |
|
||||
| caddy | caddy:latest | 80, 443 | reverse proxy для всего |
|
||||
| rclone | rclone/rclone:latest | — | бэкап по cron |
|
||||
| portainer | portainer/portainer-ce:latest | 9000 | portainer.mallexxx.duckdns.org |
|
||||
| watchtower | containrrr/watchtower:latest | — | авто-обновление образов |
|
||||
| inpxer | ghcr.io/hedger/inpxer:latest | 18080 | books.mallexxx.duckdns.org |
|
||||
| nodered | node-red:latest | 1880 | nodered.mallexxx.duckdns.org |
|
||||
| zigbee2mqtt | koenkk/zigbee2mqtt:latest | — | — |
|
||||
| mbusd | 3cky/mbusd:latest | — | Modbus |
|
||||
| modbus-bridge | modbus-bridge | — | — |
|
||||
| cups-splix | cups-splix | — | принтер |
|
||||
|
||||
### Transmission — детали
|
||||
- **Config:** `/mnt/RED_2TB/docker/transmission/` (монтируется как `/config`)
|
||||
- **Данные:** `/mnt/RED_2TB/storage` (монтируется как `/mnt/storage`)
|
||||
- **Download dir:** `/mnt/storage/Downloads`
|
||||
- **UID/GID:** 911/911 (пользователь `transdamon`)
|
||||
- **RPC whitelist:** `172.16.6.*`
|
||||
- **Web:** https://transmission.mallexxx.duckdns.org
|
||||
- **Порты:** 9091 (RPC/web), 51413 (TCP/UDP peers)
|
||||
|
||||
### Caddy — домены
|
||||
| Домен | → |
|
||||
|-------|---|
|
||||
| mallexxx.duckdns.org | Home Assistant :8123 |
|
||||
| transmission.mallexxx.duckdns.org | Transmission :9091 |
|
||||
| immich.mallexxx.duckdns.org | Immich :2283 |
|
||||
| nodered.mallexxx.duckdns.org | Node-RED :1880 |
|
||||
| webdav.mallexxx.duckdns.org | WebDAV |
|
||||
| books.mallexxx.duckdns.org | Inpxer :18080 |
|
||||
| portainer.mallexxx.duckdns.org | Portainer :9000 |
|
||||
| truenas.mallexxx.duckdns.org | TrueNAS UI :80 |
|
||||
| cam.mallexxx.duckdns.org | Камера :8090 |
|
||||
| docs.mallexxx.duckdns.org | Docs :8000 |
|
||||
|
||||
## Связанные заметки
|
||||
- [[truenas-access]] — SSH-доступ
|
||||
- [[truenas-rclone-backup]] — система бэкапов
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
# TrueNAS — rclone backup
|
||||
|
||||
## Контейнер
|
||||
|
||||
- Image: `rclone/rclone:latest`
|
||||
- Имя: `rclone`
|
||||
- Запуск: cron внутри контейнера (`crond -f`)
|
||||
|
||||
## Маппинги
|
||||
|
||||
| Host | Контейнер |
|
||||
|------|-----------|
|
||||
| `/mnt/RED_2TB/docker/rclone/config` | `/config/rclone` |
|
||||
| `/mnt/RED_2TB` | `/data` |
|
||||
|
||||
## Расписание
|
||||
|
||||
```
|
||||
0 3 * * 0 # каждое воскресенье в 03:00
|
||||
```
|
||||
|
||||
Скрипт: `/config/rclone/backup.sh`
|
||||
|
||||
## Что бэкапится
|
||||
|
||||
| Метка | Источник (host) | Назначение | Шифрование |
|
||||
|-------|-----------------|------------|------------|
|
||||
| Photos | `/mnt/RED_2TB/Photos` | `mailru:Photos/Photos` | нет |
|
||||
| old-bu | `/mnt/RED_2TB/old-bu` | `mailru:Photos/old-bu` | нет |
|
||||
| immich | `/mnt/RED_2TB/immich-photos-upload` | `mailru:Photos/immich` | нет |
|
||||
| docker | `/mnt/RED_2TB/docker` | `mailru-crypt:` | ✅ да |
|
||||
| backup | `/mnt/RED_2TB/backup` | `mailru-crypt:` | ✅ да |
|
||||
|
||||
## Remotes
|
||||
|
||||
- **mailru** — WebDAV, Mail.ru Cloud (`webdav.cloud.mail.ru`), user: `mallexxx@mail.ru`
|
||||
- **mailru-crypt** — rclone crypt поверх `mailru:backup`, шифрование имён файлов и директорий (`standard`)
|
||||
|
||||
## Добавить что-то в бэкап
|
||||
|
||||
Шифрованное → положить в `/mnt/RED_2TB/backup/` или `/mnt/RED_2TB/docker/` — подхватится автоматически.
|
||||
Нешифрованное → добавить `run_sync` строку в `/mnt/RED_2TB/docker/rclone/config/backup.sh`.
|
||||
|
||||
## Файлы конфигурации
|
||||
|
||||
- `/mnt/RED_2TB/docker/rclone/config/rclone.conf` — remotes (root-only)
|
||||
- `/mnt/RED_2TB/docker/rclone/config/crontab` — расписание
|
||||
- `/mnt/RED_2TB/docker/rclone/config/backup.sh` — скрипт
|
||||
Executable
+49
@@ -0,0 +1,49 @@
|
||||
# tv-luna-send.sh — враппер для luna-send на LG TV
|
||||
|
||||
Скрипт: `~/Automation/tv-luna-send.sh`
|
||||
|
||||
## Проблема
|
||||
|
||||
`luna-send` на WebOS через SSH **не выводит результат в stdout** без PTY.
|
||||
|
||||
- `ssh root@TV "luna-send -n 1 ..."` — молчит
|
||||
- `ssh -t root@TV "luna-send -n 1 ..."` — тоже молчит
|
||||
- `script -q -c "luna-send ..." /tmp/out.txt` — **работает**
|
||||
|
||||
Причина: luna-send детектирует TTY и отказывается писать в pipe.
|
||||
|
||||
## Решение
|
||||
|
||||
`script(1)` аллоцирует псевдо-TTY и пишет вывод в файл. Враппер запускает luna-send через script, читает tmpfile (уникальный через $$), фильтрует мусор, удаляет файл.
|
||||
|
||||
## Использование
|
||||
|
||||
```bash
|
||||
~/Automation/tv-luna-send.sh [luna-send flags] luna://service/method 'json'
|
||||
```
|
||||
|
||||
Примеры:
|
||||
```bash
|
||||
# foreground app
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.applicationManager/getForegroundAppInfo '{}'
|
||||
|
||||
# закрыть app
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.service.applicationmanager/closeByAppId '{"id":"me.wouterdek.magic4pc"}'
|
||||
|
||||
# запустить app
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://com.webos.applicationManager/launch '{"id":"me.wouterdek.magic4pc"}'
|
||||
|
||||
# статус сервиса
|
||||
~/Automation/tv-luna-send.sh -n 1 -f luna://me.wouterdek.magic4pc.service/query '{}'
|
||||
```
|
||||
|
||||
Переменная `TV_HOST` переопределяет таргет (default: `root@LGwebOSTV`, alias `root@tv`, IP: `root@192.168.1.75`).
|
||||
DNS резолвится через роутер (192.168.1.1), см. [[router-bishkek-asus]].
|
||||
|
||||
## Ограничение
|
||||
|
||||
`luna-send -i` (subscribe, бесконечный) не работает через враппер. Для install (`dev/install`) используется прямой ssh+script с polling в deploy.sh.
|
||||
|
||||
## Где используется
|
||||
|
||||
`~/Developer/magic4pc/webos/deploy.sh` — close, remove, launch.
|
||||
Executable
+172
@@ -0,0 +1,172 @@
|
||||
# Виртуальная клавиатура на HTPC (Bazzite KDE Wayland)
|
||||
|
||||
Связано: [[htpc]] | [[magic4pc-webos]]
|
||||
|
||||
## Контекст
|
||||
|
||||
**HTPC:** [[htpc]] (192.168.1.86, Bazzite, KDE Plasma 6, Wayland)
|
||||
Задача: экранная клавиатура для редкого ввода текста без физической клавиатуры.
|
||||
|
||||
---
|
||||
|
||||
## Изученные варианты
|
||||
|
||||
### ❌ Maliit (официальная KDE клавиатура)
|
||||
- Единственный officially supported OSK для KDE Wayland
|
||||
- **Критический баг (upstream, не Bazzite):** появляется один раз, после скрытия повторно не открывается без `pkill maliit-keyboard && maliit-keyboard`
|
||||
- На Bazzite desktop: опция Virtual Keyboard вообще отсутствует в Accessibility Settings
|
||||
- Статус: **не пригоден для HTPC**
|
||||
|
||||
### ❌ Onboard
|
||||
- Полнофункциональная клавиатура с modifier keys
|
||||
- Работает через XWayland + uinput (`GDK_BACKEND=x11 onboard`)
|
||||
- Не rpm-ostree пакет, требует `rpm-ostree install onboard` (layered package)
|
||||
- Нет трея, нет интеграции с KDE Virtual Keyboard API
|
||||
- Статус: **рабочий fallback, но хуже vboard**
|
||||
|
||||
### ✅ vboard (выбранное решение)
|
||||
- Форк: [archisman-panigrahi/vboard](https://github.com/archisman-panigrahi/vboard) (оригинал mdev588/vboard заброшен/заархивирован)
|
||||
- Наш форк с патчами: [mallexxx/vboard](https://github.com/mallexxx/vboard) ветка `htpc-bazzite-patches`
|
||||
- Python + GTK3 + uinput backend
|
||||
- Нативный Wayland на KDE Plasma, трей, регистрируется как Virtual Keyboard
|
||||
|
||||
---
|
||||
|
||||
## Установка на Bazzite
|
||||
|
||||
### Зависимости (pip, без rpm-ostree)
|
||||
```bash
|
||||
pip3 install python-uinput meson ninja
|
||||
```
|
||||
> `/dev/uinput` уже доступен через Steam ACL (`user:bazzite:rw-` через `steam-devices` udev rules) — sudo не нужен.
|
||||
|
||||
### Сборка и установка (user scope)
|
||||
```bash
|
||||
git clone https://github.com/mallexxx/vboard.git
|
||||
cd vboard
|
||||
git checkout htpc-bazzite-patches
|
||||
|
||||
meson setup builddir-user --prefix=$HOME/.local
|
||||
meson compile -C builddir-user
|
||||
meson install -C builddir-user
|
||||
# Создаёт KWin rule автоматически
|
||||
```
|
||||
|
||||
### Регистрация как KDE Virtual Keyboard
|
||||
```bash
|
||||
kwriteconfig6 --file kwinrc --group Plugins --key kwin_wayland_vkbd_plugin 'io.github.archisman-panigrahi.vboard'
|
||||
kwriteconfig6 --file kwinrc --group Plugins --key VirtualKeyboardEnabled true
|
||||
```
|
||||
Проверить: System Settings → Input Devices → Virtual Keyboard → выбрать Vboard.
|
||||
|
||||
---
|
||||
|
||||
## Известные проблемы и решения
|
||||
|
||||
### ⚠️ Ввод не работает (NullInputBackend)
|
||||
**Причина:** `python-uinput` из pip не имеет `KEY_LESS` (есть только в системном пакете).
|
||||
UInputBackend падает при инициализации → fallback на NullInputBackend → нажатия игнорируются.
|
||||
|
||||
**Патч** (`vboard/input_backends.py`):
|
||||
```python
|
||||
# было:
|
||||
"<": uinput.KEY_LESS,
|
||||
# стало:
|
||||
"<": uinput.KEY_102ND,
|
||||
```
|
||||
`KEY_102ND` — стандартный keycode для клавиши `<`/`>` на европейских раскладках, есть в pip-версии.
|
||||
|
||||
### ⚠️ Автопоказ/скрытие по фокусу поля не работает
|
||||
**Причина:** vboard не реализует `zwp_input_method_v2` Wayland протокол.
|
||||
KDE запускает его как процесс, но сигналы "show/hide" не передаются.
|
||||
**Решение:** оставить как есть — клавиатура висит поверх, управление через трей.
|
||||
|
||||
### ⚠️ Русская раскладка вводит латиницу
|
||||
**Причина:** vboard шлёт физические keycodes (KEY_Q и т.д.), система переводит по своей раскладке.
|
||||
**Решение:** синхронизировать системную раскладку KDE через D-Bus при переключении (см. патчи ниже).
|
||||
|
||||
### ⚠️ Таскбар исчез при попытке закрепить иконку через kwriteconfig
|
||||
**Причина:** неверный group path в `plasma-org.kde.plasma.desktop-appletsrc` → plasmashell упал.
|
||||
**Решение:** `plasmashell --replace` через SSH.
|
||||
**Правильный способ** закрепить иконку: правый клик на `^` → Configure System Tray → Entries → Virtual Keyboard → Always Shown.
|
||||
|
||||
---
|
||||
|
||||
## Кастомные патчи (ветка htpc-bazzite-patches)
|
||||
|
||||
### 1. Скрыть кнопку закрытия
|
||||
`vboard/window.py`:
|
||||
```python
|
||||
# было:
|
||||
self.header.set_show_close_button(True)
|
||||
# стало:
|
||||
self.header.set_show_close_button(False)
|
||||
```
|
||||
|
||||
### 2. Кнопка переключения EN/RU в хедере
|
||||
`vboard/window.py` — в `create_settings()` после ESC кнопки:
|
||||
```python
|
||||
self.lang_button = Gtk.Button(label=self.keyboard_layout.upper())
|
||||
self.lang_button.connect("clicked", self.cycle_keyboard_layout)
|
||||
self.lang_button.set_name("esc-button")
|
||||
self.header.pack_start(self.lang_button)
|
||||
```
|
||||
|
||||
Новые методы:
|
||||
```python
|
||||
def cycle_keyboard_layout(self, widget=None):
|
||||
keys = [k for k, _ in KEY_LAYOUT_CHOICES]
|
||||
idx = keys.index(self.keyboard_layout) if self.keyboard_layout in keys else 0
|
||||
next_key = keys[(idx + 1) % len(keys)]
|
||||
self.set_keyboard_layout(next_key)
|
||||
self.lang_button.set_label(next_key.upper())
|
||||
self.sync_system_layout(next_key)
|
||||
|
||||
def sync_system_layout(self, layout_key):
|
||||
import subprocess
|
||||
layout_map = {"en": "0", "ru": "1"}
|
||||
index = layout_map.get(layout_key)
|
||||
if index is None:
|
||||
return
|
||||
try:
|
||||
subprocess.Popen([
|
||||
"qdbus", "org.kde.keyboard", "/Layouts",
|
||||
"org.kde.KeyboardLayouts.setLayout", index
|
||||
], env=dict(__import__("os").environ,
|
||||
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"))
|
||||
except Exception:
|
||||
pass
|
||||
```
|
||||
> Индексы `en=0, ru=1` соответствуют порядку раскладок в KDE: проверить через
|
||||
> `qdbus --literal org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayoutsList`
|
||||
|
||||
### 3. Только EN/RU раскладки
|
||||
`vboard/constants.py`:
|
||||
```python
|
||||
KEY_LAYOUT_CHOICES = (
|
||||
("en", "English (US)"),
|
||||
("ru", "Russian"),
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Управление
|
||||
|
||||
```bash
|
||||
# Запустить вручную (обычно KDE делает сам)
|
||||
XDG_RUNTIME_DIR=/run/user/1000 WAYLAND_DISPLAY=wayland-0 \
|
||||
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
|
||||
python3 ~/.local/bin/vboard &
|
||||
|
||||
# Перезапустить
|
||||
kill -9 $(pgrep -f vboard)
|
||||
# KDE перезапустит автоматически через ~3 сек
|
||||
|
||||
# Проверить что backend работает
|
||||
python3 -c "
|
||||
import sys; sys.path.insert(0, '$HOME/.local/share/vboard')
|
||||
from vboard.input_backends import UInputBackend
|
||||
b = UInputBackend(); print('OK')
|
||||
"
|
||||
```
|
||||
Reference in New Issue
Block a user