58 KiB
rpi — домашняя Raspberry Pi 4 (rpi.local, 192.168.10.25)
Поднята 2026-10-11. Домашний сервер за NAT: первая задача — бэкап личного OneDrive на внешний HDD; с того же дня ещё и медиацентр (Jellyfin + *arr, Docker). Мониторится с fr1 через pushgateway (скрейпить её снаружи нельзя — она за домашним роутером).
Железо и ОС
- Raspberry Pi 4, SD 64 ГБ (
mmcblk0), питание штатное —vcgencmd get_throttled=0x0. - Raspberry Pi OS Lite 64-bit Trixie (Debian 13), образ
2026-10-06-raspios-trixie-arm64-lite. - Headless-настройка — cloud-init, а не старые
ssh/userconf.txt: в Trixie Pi Imager пишетuser-data/network-configнаbootfs. Нашuser-dataсоздал пользователя, ключ, hostname, таймзону MSK. - Сеть: Ethernet 1 Гбит/с, DHCP. MAC
dc:a6:32:db:b0:f9, роутер192.168.10.254(Huawei HG8245X6-10, Cyta). Адрес192.168.10.25закреплён за MAC статической DHCP-привязкой на роутере (2026-10-11; была без резерва).
Доступ
- С Mac:
ssh rpi(алиас →rpi.local, userrus, ключ~/.ssh/id_ed25519). Резолвится через mDNS (avahi в образе по умолчанию). - Только по ключу:
passwordauthentication no, уrusпароль заблокирован, sudo NOPASSWD (иначе sudo был бы недоступен вовсе).
Диски
| Устройство | Модель | Роль |
|---|---|---|
sda |
WD My Passport 4 ТБ (WD40NDZW, s/n WD-WX82D6228YCD) | ext4 backup → /mnt/backup |
| — | WD Elements 1 ТБ (WD10SDRW) | в USB роутера, не малины: NTFS/MBR, метка ROUTER → router: / /mnt/router (см. «Вторая копия») |
- fstab по UUID с
nofail,x-systemd.device-timeout=30s(stacks/rpi-backup/fstab.line): без диска малина грузится, бэкап просто пропускается (mountpoint -q). - ⚠️ Два 2.5" HDD от USB Pi 4 не тянут. Проверено 2026-10-11: при раскрутке обоих —
over-currentна всех USB3-портах; под нагрузкой 4-ТБ диск отваливался (USB disconnect) и залипал вUnit Not Ready. Один диск стабилен (20 ГБ чтения 103 МБ/с, mkfs ~60 ГБ записи без сбросов). Второй диск — только через USB3-хаб с собственным питанием. - Залипший после отвала диск лечится power-cycle всех USB (Pi 4 переключает питание портов только разом):
sudo uhubctl -l 2 -a off; sudo uhubctl -l 1-1 -a off; sleep 8; …-a on. - SMART на момент ввода: 9 897 ч, 0 переназначенных/ожидающих, Start_Stop 21 946, Load_Cycle 42 530.
Бэкап OneDrive (код — stacks/rpi-backup/)
- rclone (официальный .deb, v1.75.2 — в Debian 1.60, старый), remote
onedrive:= личный OneDrive (drive_type personal). Токен — в~rus/.config/rclone/rclone.conf(600), только на малине. Получен черезrclone authorize onedriveна Mac. onedrive-backup(таймер каждые 4 ч,00/4:30):rclone syncв/mnt/backup/onedrive/current, всё удалённое/перезаписанное в облаке — вarchive/<ts>/навсегда (пользователь хочет иметь всё, что когда-либо было в OneDrive). Хэши архива —manifests/archive-<ts>.qxh, лог каждого прогона —logs/sync-<ts>.log(INFO: поштучно что скачано/убрано в архив).- Целостность: rclone сверяет QuickXorHash каждого скачанного файла с OneDrive;
onedrive-verify(вс 05:00) перечитывает весь HDD:rclone checkcurrent↔облако +rclone checksumarchive↔манифесты. Отчёт —logs/verify-<ts>*. - Оба юнита под общим
flock /run/lock/onedrive-backup.lock— не идут параллельно и не убивают друг друга. - ⚠️ Файл, загруженный и удалённый в облаке между прогонами (<4 ч), в бэкап не попадёт.
- ⚠️
Personal Vaultисключён — rclone через API туда не ходит. - ⚠️ Архив без ротации: растёт вечно. Скрипт выходит с кодом 2 при заполнении >90 % (→ алерт BackupFailed), плюс HostDisk* если когда-то поставим node-exporter.
- Первая полная выгрузка (368 ГБ) запущена 2026-10-11 ~13:13, ~27 МБ/с (упор в домашний канал).
Вторая копия — 1 ТБ диск в роутере (с 2026-10-11)
-
Диск воткнут в роутер Huawei (
192.168.10.254), а не в малину — не ест питание USB малины (два HDD от неё не тянут, см. «Диски»). Доступ — SFTP роутера на порту 8022, пользовательroot, remoterouter:в~rus/.config/rclone/rclone.conf(пароль только там), host key —~rus/.ssh/known_hosts_router. -
⚠️ Роутер не считает хэши (
shell_type = none,md5sum_command = none) — rclone сравнивает по размеру+mtime, целостность проверяется перечиткой. -
mnt-router.service—rclone mount router: /mnt/router(user rus,--vfs-cache-mode writes, кэш в/mnt/backup/.rclone-cache). Для просмотра/ручной работы; бэкап пишет напрямую в remote, не через FUSE (коды ошибок, без кэша). -
Скорость (замер 2026-10-11, параллельно с выгрузкой OneDrive): запись ~8 МБ/с, чтение ~11 МБ/с — первичная копия ~370 ГБ ≈ 13 ч. Диск 932 ГБ.
-
router-backup(stacks/rpi-backup/, таймер 06:00,flock): вrouter:rpi-backup/—onedrive/{archive,manifests,logs}толькоcopy(там ничего не удаляется), затем зеркалоonedrive/currentс--max-delete 1000, затем зеркало зашифрованныхservers/с--max-delete 50. Порядок важен: удалённое из current к этому моменту уже скопировано в archive. Логи —/mnt/backup/router-logs/. -
⚠️
--max-delete— предохранитель: если локально «пропадёт» много файлов (сбой диска/монтирования), копия на роутере не зачистится, а прогон упадёт с ошибкой → алертBackupFailed. -
По воскресеньям
verify: сверка размеров деревьев + перечитать с роутера последний daily каждого сервера и сравнить sha256. -
Ежемесячно (1-го, 08:00)
router-sample: случайные файлы OneDrive изcurrent/иarchive/старше суток, ~2 ГБ / до 300 шт., перечитываются с роутера и сверяются sha256 с HDD — ловит тихую порчу, которую сверка размеров не видит. Отсутствующий на роутере файл = ошибка. Итог —backup_*{job="backup_router_sample"}→BackupFailed,BackupStale(>35 дней). Проверено 2026-10-11: 20 из 20 скопированных файлов совпали. -
Мониторинг:
router_mount_upи заполнение/mnt/router(вsmart-metrics,dfподtimeout 20), итог прогона —backup_*{job="backup_router"}; алертыRouterDiskMountDown(30 мин),BackupDiskFull(>90 %, любой диск бэкапа),BackupStale(>30 ч); ряд «Вторая копия» на дашборде rpi-disk. -
⚠️ 1 ТБ меньше основного диска: сейчас влезает (~370 ГБ OneDrive + ~100 ГБ серверов), но архив версий растёт вечно — следить за
BackupDiskFull. -
Почему NTFS (2026-10-11): прошивка Cyta видит FAT32 и NTFS, exFAT — нет (диск в списке USB не появлялся); FAT32 отпал из-за лимита 4 ГБ на файл. Файл 4,4 ГБ через SFTP записан и прочитан. На Mac NTFS штатно не создать — делали
mkntfsиз ntfs-3g, собранного без FUSE (--disable-ntfs-3g), на блочное/dev/diskNs1(наrdiskmkntfs отказывается). -
⚠️ FTP роутера (порт 21) включён в его конфиге, но из LAN filtered: доступ к FTP со стороны LAN открывается только на странице ONT Access Control, а у пользователя
cytauserеё нет (нужен суперадмин Cyta). Поэтому SFTP: включён 2026-10-11 через веб-API роутера — сервер8022, LAN=1, WAN=0, аккаунтrootс корнем/mnt/usb/usb-1058-363434_1. Пароли SFTP и веб-интерфейса — только у пользователя и вrclone.conf. -
⚠️ Потолок ~10 МБ/с — CPU роутера (dropbear):
aes128/256-ctrвдвое медленнееchacha20(нет аппаратного AES), параллельные потоки почти не помогают. Быстрее только диск на малине через хаб с питанием (~100 МБ/с).
Бэкап серверов fr1/ru1 (с 2026-10-11, код — stacks/server-backup/)
- Малина — внешняя площадка для VPS:
servers-backup.timer(02:15) забирает по SSH выгрузки, которые сервер сам шифрует открытым ключом age (tar | zstd | age). Закрытого ключа на малине нет — ни она, ни Astra, ни взломщик архивы не прочитают. Ключ у владельца: Mac~/.config/age/servers-backup.key. - Хранилище
/mnt/backup/servers/<host>/{daily,weekly,monthly}(root 700): 14 / 8 / 12, monthly — хардлинк первого daily месяца. fr1 daily ~2.1 ГБ (5.5 мин), ru1 ~17 МБ, fr1 weekly (вс) — тома ботов и imgbot. - Ключ
/etc/server-backup/id_ed25519(root 600): на серверах ограничен forced command — только запустить выгрузку. Host keys закреплены в/etc/server-backup/known_hosts. - Целостность: sha256 шифротекста считает сервер, малина сверяет при приёме и по воскресеньям (
servers-backup verify). Итог — метрикиbackup_*{job="backup_servers"}, алертBackupStale>26 ч, панель на дашборде rpi-disk. - Пробное восстановление 2026-10-11 на Mac: оба архива расшифрованы, на месте CA OpenVPN (
easy-rsa/pki/private/ca.key), ключи AWG, конфиги прокси, репо gitea, снимокgitea.db.
Мониторинг → fr1
smartd(stacks/rpi-backup/smartd.conf):DEVICESCAN -d removable,-n standby,q(не будить диск), короткий самотест сб 03:00, длинный 1-го числа 05:00. ⚠️-d satс DEVICESCAN не работает («Not a SAT device») — тип моста пусть определяет сам.smart-metrics(таймер 15 мин): smartctl-n standby→ метрикиsmart_*→ jobsmart. Спящий диск не будится: отдаются значения из кэша/var/lib/smart-metrics/+smart_disk_standby=1.backup-metrics <job>—ExecStopPost=+у юнитов бэкапа:backup_last_exit_code,backup_last_run_timestamp,backup_last_success_timestamp(время успеха хранится локально в/var/lib/backup-metrics/, т.к. PUT заменяет группу целиком).- Доставка:
metrics-push <job>= ssh с ключом/etc/metrics-push/id_ed25519(root, 600) наrus@161.97.93.252; host key fr1 закреплён в/etc/metrics-push/known_hosts. На fr1 ключ ограничен forced command (servers/fr1.md→ Мониторинг). smart-metricsзаодно отдаётbackup_disk_size_bytes/backup_disk_avail_bytesдля/mnt/backup(statfs, диск не будит).- Дашборд: https://mon.ruzzy.dev/d/rpi-disk (SMART, износ за сутки, свежесть бэкапов, заполнение).
- ⚠️
BackupStaleвидит только существующие серии — задача, ни разу не отчитавшаяся, им не ловится. Для этогоBackupNeverReportedнаabsent()(с 2026-10-11): OneDrive 12 ч, серверы 26 ч, роутер 30 ч, проверка OneDrive 8 дней; иPushMetricsStaleна отсутствие SMART-метрик 1 ч. Доставка в Telegram проверена тестовым алертом 2026-10-11. - monwatch — сторож самого мониторинга (с 2026-10-11,
stacks/rpi-backup/bin/monwatch, таймер раз в час): весь мониторинг живёт на fr1, и если упадёт fr1 или цепочка доставки — алертов не будет вообще. Малина спрашивает fr1health(тот же ключ метрик, режим только чтение): живы ли Prometheus/Alertmanager/pushgateway, видит ли Prometheus пуши малины моложе часа, не растут лиalertmanager_notifications_failed_total{integration="telegram"}. При проблеме (после повторной проверки через 2 мин) пишет в Telegram напрямую, минуя fr1 — ботом @rasp_contol_bot (токен из/etc/astra-bot.env) в чат 607015; повтор раз в 6 ч, ✅ при восстановлении. Состояние —/var/lib/monwatch/. Путь тревоги проверен имитацией 2026-10-11 (MONWATCH_MAX_PUSH_AGE=1). - ⚠️ Сообщения сторожа приходят в чат с ботом Astra — это бот сам пишет, Codex их не видит и не обрабатывает.
- Алерты — группа
rpiвstacks/monitoring/prometheus/rules/alerts.yml.
Домашняя печать (с 2026-10-11)
-
Brother DCP-L2620DW обнаружен через mDNS:
192.168.10.24,BRW2C9C58C1EEA7.local, IPP порт 631/ipp/print; чёрно-белый, A4, двусторонняя печать. Ранее службы печати на rpi не было. -
Установлены
cups,cups-client,cups-filters,cups-ipp-utils(CUPS 2.4.10); включёнcups.service. Очередь по умолчаниюhome-brother, драйверeverywhere, URIipp://BRW2C9C58C1EEA7.local:631/ipp/print. По умолчанию A4, одна сторона;printer-is-shared=false, CUPS слушает только127.0.0.1:631и[::1]:631. Доступ из Telegram — команда агента, без отдельного открытого веб-интерфейса. -
Код настройки и команда —
stacks/rpi-print/;home-printустановлен в/usr/local/bin/(root, 755).home-print status— состояние/очередь;home-print [--duplex] <PDF/PNG/JPEG>— одна копия, A4 с подгонкой. Печать только по прямой просьбе пользователя; приём задания в очередь не означает, что бумага уже вышла. -
Навык
home-printупрощён для ребёнка 2026-10-11; источник — astra-bot11d0a85,codex/skills/home-print/, установлен в~astra/.codex/skills/home-print/. Вместо PNG каждой страницы и повторного подтверждения отправляет один PDF, затем по прямой просьбе «распечатай» печатает одну копию A4 с одной стороны без дополнительных вопросов. Текст извлекается из скриншотов, картинки сохраняются в оттенках серого, все страницы проверяются локально. Если PDF не доставлен, печать не запускается; повторная отправка задания при ошибке не автоматическая. Для этого сценария установлены узкие постоянные разрешения~astra/.codex/rules/home-print.rules(источникcodex/rules/в astra-bot): только/usr/local/bin/home-printи PDF-режим штатного отправщика. Общая политика подтверждений сохранена. Проверка: 31 тест, валидация скилла и правил; произвольный Python правилами не разрешается. Инструкции установлены в~/.codex/AGENTS.md; новые разговоры получают их автоматически. -
Кнопки и промежуточные ответы печати убраны в самом боте 2026-10-11, astra-bot
6b1317d. Ранее постоянных правил скилла было недостаточно: запросы approval и все agentMessage уходили в Telegram. Бот теперь автоматически отвечает accept только на штатную PDF-отправку разрешённому чату и home-print для print.pdf в каталогах /tmp/astra-print-*; shell-операторы и произвольные команды исключены. В задачах печати сохраняет последний ответ и отправляет его после завершения, PDF доставляется отдельным вложением. Проверено 34 тестами, установлен bot.py; прежний код — /opt/astra-bot/bot.py.bak-20261011-child-print. Перезапуск через restart-check.py после завершения текущего ответа. -
⚠️ DOCX напрямую не печатается — сначала преобразовать в PDF. Hostname выбран вместо DHCP-IP, чтобы пережить смену адреса; требуется mDNS и включённый принтер.
printer-error-policy=abort-jobисключает неожиданную автоматическую печать старых заданий после ошибки; ошибочный прогон нужно отправить заново. -
Проверено: запрос атрибутов IPP (
ipptool) PASS, принтер idle/enabled, A4/Gray/duplex доступны. Портрет успешно преобразован фильтрами CUPS PNG → PDF → PWG Raster (A4, 300 dpi), без ошибок. Тестовая страница A4 отправлена 2026-10-11 в 15:20 MSK:home-brother-1, CUPS сообщилjob-completed-successfully, принтер вернулся в idle, очередь пуста; качество на бумаге проверяет пользователь. -
Для перевёрстки извлечённого текста в PDF установлен
python3-reportlab4.3.1 (2026-10-11; ранее средств создания PDF с кириллицей не было), с зависимостями Pillow/Cairo. Шрифт DejaVu Sans внедряется в PDF; PNG-предпросмотр строится из итогового серого PDF. Проверено на комплекте Лермонтова: 3 страницы A4, текст со скриншотов и исходный портрет.
Медиацентр (с 2026-10-11, код — stacks/rpi-media/)
Docker CE 29.9 + Compose v5.6 из репо download.docker.com (в Debian старее). /etc/docker/daemon.json: json-file 10m×3 — чтобы логи контейнеров не точили SD. rus в группе docker (= root-эквивалент; у него и так sudo NOPASSWD). Стек — /opt/media/docker-compose.yml, конфиги — /opt/media/config/<сервис> (SD, ~20 МБ), образы ~7.8 ГБ на SD.
| Сервис | Порт | Зачем | Версия на 2026-10-11 |
|---|---|---|---|
| Jellyfin | 8096 (host-сеть) | медиасервер; клиенты LG webOS, Infuse/Swiftfin на iOS | 12.2 |
| Seerr | 5055 | каталог «хочу посмотреть» → Radarr/Sonarr | v3.5.0 |
| qBittorrent | 8080, торренты 6881 tcp/udp | загрузка | 5.2.4 |
| Radarr / Sonarr | 7878 / 8989 | фильмы / сериалы: поиск, загрузка, импорт | 6.4.4 / 4.0.20 |
| Prowlarr | 9696 | индексаторы, раздаёт их в Radarr/Sonarr | 2.6.5 |
| FlareSolverr | 8191 | обход Cloudflare для индексаторов с тегом flaresolverr |
v3.5.2 |
| Bazarr | 6767 | субтитры, профиль ru+en |
v1.6.2 |
| Homepage | 3000 | стартовая страница: все сервисы с описанием по-русски, живой статус, CPU/температура/диск | v2.5.0 |
- Данные —
/mnt/backup/media(4-ТБ диск, решение пользователя):torrents/{movies,tv,other},library/{movies,tv},.cache/jellyfin(кэш и транскоды Jellyfin — не на SD). qBittorrent и *arr монтируют один и тот же корень как/data— иначе импорт изtorrents/вlibrary/превращается из хардлинка в копию и раздача занимает место дважды.copyUsingHardlinksвключён. В бэкапы (router-backup,onedrive-*)media/не входит. - ⚠️ Медиа делят диск с бэкапами.
onedrive-backupпадает с кодом 2 при заполнении >90 % (~370 ГБ свободно) →BackupFailed. В Radarr/Sonarr стоитminimumFreeSpaceWhenImporting = 500 ГБ: ниже этого импорт останавливается. qBittorrent своего порога не имеет — ручная заливка торрентов мимо *arr может забить диск. - Jellyfin в
network_mode: host— иначе LG/iOS не находят сервер автообнаружением (UDP 7359 и DLNA-мультикаст не проходят через бридж). Аппаратного транскодинга на Pi 4 нет (V4L2 убран в Jellyfin 10.9),EncodingThreadCount=3: расчёт на Direct Play. ⚠️ Транскод 4K/HEVC Pi не тянет — клиенту нужен нативный кодек (Infuse играет почти всё сам). - Метаданные и интерфейс — ru, предпочтительные аудио/субтитры у пользователя —
rus, режим субтитров Smart. Библиотеки «Фильмы» (/data/library/movies) и «Сериалы» (/data/library/tv), в Jellyfin только чтение. - Индексаторы (публичные, без аккаунтов): NoNaMe Club, The Pirate Bay, YTS — синхронизированы в Radarr/Sonarr; Rutor и EZTV есть в Prowlarr, но в *arr не доехали (Rutor не проходит тест по категориям, EZTV на момент настройки лежал); 1337x не добавился (таймаут даже через FlareSolverr). RuTracker (добавлен 2026-10-11, аккаунт пользователя; логин/пароль — только в БД Prowlarr): через FlareSolverr, опции «убрать кириллицу», «добавить RUS», «первые теги в конец» — чтобы *arr сопоставляли английские названия и видели русскую дорожку; приоритет 10 (выше публичных, 25). Синхронизирован в Radarr и Sonarr. Kinozal и прочие приватные — руками.
- ⚠️ RuTracker закрывает
login.php/tracker.phpчелленджем Cloudflare (по IPv4; IPv6 у малины нет маршрута). FlareSolverr на Pi решает его 80–180 с — у прокси в ProwlarrrequestTimeout=180(было 60, с ним добавление падало по таймауту). После решения Prowlarr держит cookie и поиск идёт ~4 с; когда cookie протухнет, первый поиск снова будет минутами, и *arr могут на время пометить индексатор недоступным. - Языки дорожек (2026-10-11,
provision.py langs): custom formats «Русская дорожка» (язык Russian илиRUS|MVO|DVO|Dub|Дубляжв названии) = 100 и «Оригинальная»/«Английская дорожка» = 50 во всех профилях Radarr/Sonarr;minFormatScore=0(ничего не отклоняется),cutoffFormatScore=150+upgradeAllowed— *arr сами перекачают, когда появится раздача с русской дорожкой. Язык профилей Radarr — Any (было Original: раздачи только с дубляжом отклонялись). Повод — первый фильм (The Fix, 2026) скачался с YTS только на английском; русского дубляжа у свежих релизов ещё нет неделями, есть толькоSub-раздачи. - Bazarr: провайдеры без аккаунтов (
embeddedsubtitles,podnapisi,yifysubtitles); для русских субтитров лучший — OpenSubtitles.com, нужен аккаунт. ⚠️ Бесплатные провайдеры для свежих фильмов русских субтитров не находят (The Fix — пусто); тогда субтитры вытаскивали изSub-раздачи RuTor: mkv вtorrents/other,ffmpeg -map 0:s:m:language:rus -c copy→<имя>.ru.srtрядом с фильмом (сверить длительность/fps — иначе рассинхрон), лишнюю раздачу удалить. - Авторизация: везде пользователь
rus, один пароль —/opt/media/.admin-password(rus 600). *arr — формы, пароль всегда (режим «без пароля из LAN» в новых *arr требуетAllowedHosts). Между собой сервисы ходят по API-ключам изconfig/<app>/config.xml. - Пароли сняты для домашней сети 2026-10-11 (решение владельца): Radarr/Sonarr/Prowlarr —
AuthenticationRequired=DisabledForLocalAddresses(из LAN/частных сетей без входа, снаружи пароль бы остался; API по-прежнему по ключу — UI берёт его из/initialize.json); qBittorrent —bypass_auth_subnet_whitelist192.168.10.0/24 + 172.16.0.0/12 иbypass_local_auth(учёткаrusдля *arr не тронута); Bazarr —auth.type: null. Бэкапы конфигов —config/<app>/*.bak-20261011-auth. Jellyfin: пустой пароль у админа запрещён самим Jellyfin 12 («Admin user passwords must not be empty») — поэтому заведён пользователь «Дом» без пароля и без прав админа (все библиотеки, без удаления), он один на экране входа;rus(админ) — с паролем, для настроек. Seerr по-прежнему входит через учётку Jellyfin. ⚠️ Теперь любое устройство в домашней сети (гости в Wi‑Fi, умный дом) управляет загрузками и библиотекой. ⚠️provision.pyна чистой установке снова включит пароли — при переустановке повторить. - Точка входа для пользователя — http://192.168.10.25:3000 (Homepage, конфиги
stacks/rpi-media/homepage/→/opt/media/homepage/). Ключи виджетов —/opt/media/homepage.env(rus 600,HOMEPAGE_VAR_*, генеритprovision.py homepage). ⚠️ Там же пароль qBittorrent: после смены общего пароля перегенерировать env иdocker compose up -d homepage, иначе виджет qBittorrent отвалится.HOMEPAGE_ALLOWED_HOSTSобязателен — без него 400 на любой Host, кроме localhost. - ⚠️ Встроенный виджет
jellyfinHomepage 2.5 с Jellyfin 12 не работает: ходит на/emby/…?api_key=— пути нет (404), ключ в query отключён (EnableLegacyAuthorization=false, включать не стали). Вместо негоcustomapiна/Items/Countsс заголовкомAuthorization: MediaBrowser Token=…. - Radarr/Sonarr → Jellyfin (Connect «Jellyfin», тип MediaBrowser, ключ Jellyfin
homepage;provision.py connectна чистой установке заводит ключarr-connect): библиотека обновляется сразу после импорта. Без этого новый фильм висел невидимым до скана по расписанию — realtime-монитор хардлинк не заметил (проверено 2026-10-11 на первом фильме). - Первичная связка —
stacks/rpi-media/provision.py(идемпотентный, пароль и ключи читает на месте):python3 /opt/media/provision.py [qbit jellyfin arr prowlarr bazarr seerr connect homepage]. - ⚠️ Каталог
config/<сервис>, которого нет доup, docker создаёт от root — Jellyfin/Seerr (uid 1000) падают сPermission denied. Новые каталоги создавать заранее илиchown -R rus:rus /opt/media/config. - ⚠️
fallenbagel/jellyseerrзаброшен (последний образ 2025-08) и не логинится в Jellyfin 12 — заменён наghcr.io/seerr-team/seerr. - Торренты идут напрямую с домашнего IP (решение пользователя 2026-10-11; вариант через AWG fr1 отложен). Порт 6881 на роутере не проброшен — входящих соединений нет, раздача и скорость хуже.
- Astra управляет медиацентром (с 2026-10-11) — скилл
mediaвruzzy/astra-bot, команда/usr/local/bin/media(поиск/добавление/выбор раздачи по языку/очередь/удаление; изменения — только--yesи кнопкой). Ключи —/etc/media.env(root:astra 640). ⚠️ Там же копия пароля qBittorrent — при смене общего пароля обновлять вместе сhomepage.env. В инструкциях Astra/mnt/backup/media— исключение из «ничего в /mnt/backup не удалять», но только черезmedia. Поле — только чтение. - Образы на
:latest, автообновления нет:cd /opt/media && docker compose pull && docker compose up -d.
Агент Astra (с 2026-10-11)
Агент на базе Codex (OpenAI), работает на самой малине, управление — из Telegram-бота @rasp_contol_bot. Код бота — отдельный репо ruzzy/astra-bot (там же схема работы).
-
Пользователь
astra(группыsudo,adm,systemd-journal,users), пароль заблокирован, sudo NOPASSWD (/etc/sudoers.d/90-astra) — по решению пользователя. SSH-вход под ним — ключом~/.ssh/id_ed25519с Mac (алиасssh rpi-astra). -
⚠️ sudo = агент видит всё: токен OneDrive (
~rus/.config/rclone/rclone.conf), пуш-ключ метрик (/etc/metrics-push/), deploy-ключ с записью вinfra, токен бота. Утечка контекста агента = утечка этих секретов. -
Codex CLI 0.162.1 — полный пакет в
/opt/codex, симлинк/usr/local/bin/codex. ⚠️ Голый бинарник из релиза (codex-aarch64-…tar.gz) не годится:remote-control/app-server требуют пакет (codex-package-aarch64-unknown-linux-musl.tar.gz), иначе «this CLI has no complete local package». Логин — подпиской ChatGPT (codex login --device-auth, аккаунт ruzzyrullezz@gmail.com, Plus), токен~astra/.codex/auth.json(600). Ключ API не используется. -
Агенту разрешено пушить в
mainruzzy/infraнапрямую (решение пользователя 2026-10-11, перекрывает правило изCLAUDE.mdтолько для него): любые изменения сервера он обязан внести вservers/rpi.md/stacks/и запушить в том же прогоне, конфликты —pull --rebaseбез--force, неразрешимые — отдать пользователю. Источник инструкций —codex/AGENTS.mdвruzzy/astra-bot. -
Конфиг
~astra/.codex/config.toml:approval_policy=on-request,sandbox_mode=workspace-write; инструкции агенту —~astra/.codex/AGENTS.md(паспорт, правила infra, что не трогать). -
astra-bot (
astra-bot.service, userastra):/opt/astra-bot/bot.py⇄codex app-server(JSON-RPC stdio) ⇄ Telegram long polling. Подтверждения команд/правок — кнопками в чате. Конфиг/etc/astra-bot.env(root 600):TG_TOKEN,TG_ALLOWED_IDS=607015,6310034441. Тред Codex на чат —~astra/.local/state/astra-bot.json. Бот лежит в/optпод root, а не в~/infra, чтобы агент не правил свой код безsudo. -
Приём вложений исправлен 2026-10-11 (раньше бот читал только
text, фото и подписи молча пропадали): код —ruzzy/astra-bot. Фото и JPEG/PNG/WebP-документы до 20 МиБ скачиваются через TelegramgetFileв~astra/.local/share/astra-bot/incoming/(файлы 600, UUID), передаются Codex какlocalImage; подпись и источник пересылки — текстом. Пересланные/stopи другие команды читаются как цитата. Во время работы сообщения ставятся в очередь процесса, реальная доставка картинки с подписью и источником подтверждена пользователем 2026-10-11. -
Пачки изображений добавлены 2026-10-11 (раньше каждый элемент альбома запускал отдельную задачу и отдельное уведомление очереди): установлен коммит
6276bf8. Бот собирает альбом поmedia_group_id/чату/отправителю, быстро пересланные картинки без ID — по чату/отправителю; после 1,5 секунды тишины передаёт все картинки, подписи и источники одним запросом Codex в порядкеmessage_id. Служебные уведомления ожидания убраны 2026-10-11 (коммитc4e3cd1): прежняя проверка пустой очереди повторяла их между пачками; очередь сохранена и работает молча. Проверка включает повторное заполнение опустевшей очереди. Предыдущий код —/opt/astra-bot/bot.py.bak-20261011-silent-queue. 23 теста прошли; изменение загружается при перезапуске черезrestart-check.py. ⚠️ Пауза больше 1,5 секунды разделяет серию на пачки; буфер и очередь не переживают перезапуск. Предыдущий код —/opt/astra-bot/bot.py.bak-20261011-batches. -
Код бота с доработкой Astra перенесён в
ruzzy/astra-bot(f9f6c39; текущая установленная версия —c4e3cd1); временная копияstacks/astra-bot/удалена 2026-10-11. Клон —~astra/astra-bot. Резервная копия прежнего кода —/opt/astra-bot/bot.py.bak-20261011-incoming. -
⚠️ Почему не штатный Codex Remote из ChatGPT: телефон к безголовому Linux не сопрягается — официально хостом может быть только macOS/Windows;
codex remote-control pairвыдаёт код, но и QR, и ручной ввод дают «Pair Failed», до демона попытка даже не доходит (проверено с debug-логом 2026-10-11). Рабочая альтернатива — ChatGPT Desktop на Mac → SSH-хостrpi-astra, но тогда Mac должен быть включён. -
/boot/firmware/cmdline.txt: добавленcfg80211.ieee80211_regdom=RU(бэкап.bak-20261011) — только чтобы/etc/profile.d/wifi-check.shне печатал в stdout login-shell предупреждение про rfkill: оно ломало бы stdio-протоколы (Codex app-server по SSH). Wi-Fi не используется. -
Доступ к Gitea — пользователь
astra(с 2026-10-11, вместо двух deploy-ключей): один SSH-ключ~astra/.ssh/gitea, коллаборатор с записью вruzzy/infra(~astra/infra) иruzzy/astra-bot(~astra/astra-bot), может создавать свои репо вastra/…(API-токен~astra/.config/gitea/token, 600, scopeswrite:repository,write:user, в Gitea —astra-rpi). Почему пользователь, а не deploy-ключи: deploy-ключом нельзя создавать репо, а права коллаборатора видны и меняются в настройках репо. Создавать репо от имениruzzyнельзя — он пользователь, не организация. git identityAstra (rpi) <astra@rpi.ruzzy.dev>, host key Gitea (RSA) закреплён. Автопулла нет. -
Профиль Поли (@Polli4ka303), 10 лет, сохранён в инструкциях 2026-10-11: простые короткие ответы без технических терминов; источник astra-bot
88b88a5. Детская печать уточнена: единый PDF → «Печатай» / «Печатай на двух сторонах» → печать без системных кнопок. Доступ добавлен 2026-10-11: Telegram ID6310034441внесён в TG_ALLOWED_IDS (ранее только владелец607015), профиль закреплён за ID вместо username; astra-bot2d761d3. Настройка применяется после перезапуска бота. -
Постоянная сессия и журнал Поли добавлены 2026-10-11, astra-bot
8b3400a. После авторизации её чат сохраняется в state.child_chats, тред возобновляется после перезапуска; служебные slash-команды не сбрасывают разговор и не показывают справку администратора. Бот передаёт возраст и текущий chat_id в контекст, отправляет только итоговый ответ. Входящие сообщения, метаданные/пути вложений и текстовые ответы пишутся в ~/.local/share/astra-bot/conversations/<chat_id>.jsonl (файл 600, каталог 700); PDF, отправленный отдельным скриптом, в этот журнал не записывается. Имя пользователя выбирает профиль только после проверки TG_ALLOWED_IDS и не предоставляет доступ. Проверка: 37 тестов; резервный код /opt/astra-bot/bot.py.bak-20261011-child-session. ⚠️ При невозможности resume бот создаёт новый тред; локальный журнал остаётся, автоматического импорта журнала в контекст нет.
Роутер Huawei HG8245X6 — скилл router (с 2026-10-11)
-
Роутер — OptiXstar HG8245X6-10, оптический терминал Cyta (GPON), ПО V5R022C10S110,
192.168.10.254. Интернет — PPPoE1_INTERNET_R_VID_42(публичный IP динамический, на 2026-10-11 — 46.199.208.45); ещё WAN TR069, VOIP, IPTV. За LAN3 — mesh-точки M15/E15 (Wi-Fi-клиенты за ними видны какlan3), на LAN4 — малина. -
Управление — Codex-скилл Astra
router, код вruzzy/astra-bot(codex/skills/router/), команда/usr/local/bin/router. Креды веб-интерфейса —/etc/router.env(root:astra 640), в git нет. Умеет: статус/WAN, клиенты (IPv4 из аренд DHCP, сигнал Wi-Fi), трафик по интерфейсам, DHCP static add/del, проброс портов add/del (через WAN INTERNET), Wi-Fi — только чтение. Изменения — только--yesи кнопкой (codex/rules/router.rulesразрешает лишь чтение). -
⚠️ 3 неудачных входа подряд блокируют вход в роутер (
errloginlockNum = '3').login.cgiразбирает поля позиционно — порядок как у браузера (UserName, PassWord, Language, x.X_HW_Token), иначе вход «неудачный». login не ретраится. Веб-сервер однопоточный и рвёт соединения при частых запросах — чтение ретраится с паузой; выход (logout.cgi) всегда отвечает обрывом, это норма. После каждой операции — выход, чтобы не забивать лимит сессий и не выбивать человека из веб-интерфейса. -
⚠️ Трафик по устройствам прошивка не считает (поля
TrafficRecvRate/SendRateвсегда 0) — только по интерфейсам:wan(сумма GEM Ethernet),iptv,lan1..4,wifi-2.4,wifi-5. -
⚠️ Запись Wi-Fi не сделана сознательно: SSID 2.4/5 ГГц связаны (WifiCover/band steering), запрос — десятки полей; ошибка отключит весь дом. Делать отдельно, в согласованное окно.
-
router-watch.timer(5 мин, root): снимок/var/lib/router-watch/state.json(читает astra без сети),seen.json(все MAC с первым появлением; база — 22 устройства на 2026-10-11 15:57),known.json(имена от пользователя),events.log. Новый MAC → Telegram ботом @rasp_contol_bot с флагами (случайный MAC, ночь, без имени, ≥3 новых за час). Метрикиrouter_*→ pushgateway (jobrouter) → алерты группыhome-network:RouterWatchStale(>20 мин),RouterDownloadSpike/RouterUploadSpike(WAN: 15-мин скорость >4× средней за неделю и >5 МБ/с ↓ / >1 МБ/с ↑, 30 мин). Дашборд https://mon.ruzzy.dev/d/home-net. -
DLNA и FTP на USB-диске роутера выключены 2026-10-11 (по решению владельца; включали в тот же день с Mac
.17при настройке диска): DLNA (X_HW_DmsService, ShareAllPath, порт 56002) без пароля отдавал всей домашней сети содержимое диска — а там копия OneDrive; FTP (21, root) не нужен. SFTP :8022 (LAN only, WAN выкл) оставлен — через негоrouter-backup. Управление —router usb status|dlna|ftp. -
Проверено на живом роутере 2026-10-11: чтение всех разделов;
dhcp add/del(тестовая привязка 02:00:00:00:00:01 → .250 создана и удалена),portmap add/del(TCP 59999 → rpi создан и удалён). -
Статическая привязка DHCP
192.168.10.25↔dc:a6:32:db:b0:f9(малина) на роутере уже есть — единственная. Привязка192.168.10.101↔8e:a9:3a:4e:69:baудалена 2026-10-11: устройства с таким MAC нет ни в сети, ни в истории роутера (вероятно, старый телефон со сменившимся случайным MAC). -
Свободная беседа, интернет-поиск, объяснение школьного материала, поиск и генерация картинок для Поли разрешены 2026-10-11; правила установлены в ~/.codex/AGENTS.md, источник astra-bot
95a2867. Содержание подбирается для 10 лет, материалы 16+/18+ исключаются; выбранные картинки проверяются перед отправкой. Это инструкции агента, не отдельный сетевой фильтр. Разрешение не распространяется на управление сервером и доступами. -
Голосовые Telegram добавлены 2026-10-11 (ранее отклонялись как неподдерживаемые): astra-bot
e0fc9dc, исходники установки и распознавания voice/. Установлен ffmpeg 7.1.5 с зависимостями; python3-venv уже был. Vosk 0.3.45 в /opt/astra-voice/venv, русская модель vosk-model-small-ru-0.22 и helper /opt/astra-voice/transcribe.py, всего 115 МБ. OGG/Opus скачивается через Telegram (600), распознаётся локально без стороннего API, до 5 минут / 20 МиБ, таймаут 180 с; одна запись обрабатывается, до трёх в работе/ожидании, основной цикл бота свободен. Расшифровка идёт в существующий чат, пересылки остаются цитатами; для Поли пишется в журнал. ⚠️ Модель небольшая: шум, имена и сложная речь дают ошибки; пустой результат вызывает просьбу записать заново. Исходные записи автоматически не удаляются. Проверка: 43 теста и настоящий OGG с тишиной (модель запускается, пустая расшифровка); качество живой русской речи ещё предстоит проверить голосовым пользователя. Предыдущий бот — /opt/astra-bot/bot.py.bak-20261011-voice; обновление установлено, перезапуск через restart-check.py после текущего ответа. -
Распознавание голосовых заменено 2026-10-11 на whisper.cpp v1.7.6 + многоязычную base (141 МиБ), astra-bot
c5c488f, установка —voice/setup-whisper.shв репозитории бота. Причина: Vosk услышал «кастовой голосовой» в записи «тестовое голосовое» и поддерживал только русский; Whisper на той же записи получил «тестовый голосовое» (ошибка окончания остаётся). Русский, английский и греческий выбираются автоматически, перевода нет, обработка локальная. Бинарник/opt/astra-voice/whisper-cli, модель/opt/astra-voice/ggml-base.bin, helper запускается системным Python; установлен CMake 3.31.6 для сборки. Два потока CPU, таймаут бота увеличен с 180 до 900 с. ⚠️ На Pi обработка медленнее, короткие и смешанные фразы могут ошибаться; качество греческой речи ещё не проверено реальной записью. Проверки: 43 теста бота, пользовательский OGG, английский образец JFK распознан правильно, тишина даёт пустой текст. Прежний Vosk сохранён, helper —transcribe.py.vosk-bak-20261011, предыдущий бот —/opt/astra-bot/bot.py.bak-20261011-whisper. Перезапуск черезrestart-check.pyпосле ответа. -
Индикатор работы добавлен 2026-10-11: astra-bot
20a8ffc. Раньше typing отправлялся один раз и пропадал через несколько секунд; теперь при распознавании голосовых и выполнении задачи отдельное тихое сообщение с машинкой 🚗 редактируется каждые 4 с, typing обновляется. Один индикатор на чат, перекрывающиеся задачи учитываются; после окончания сообщение удаляется. Проверки: 46 тестов, включая перекрытие задач, редактирование/удаление и неудачную отправку. Резервная копия/opt/astra-bot/bot.py.bak-20261011-waiting-car; установка выполнена, перезапуск черезrestart-check.pyпосле ответа.
Разговорный навык Маруси (подготовлен 2026-10-11)
- Установлен и включён
astra-marusia.service, код — astra-bot27e39ea,/opt/astra-marusia/server.py; юнит и инструкция —stacks/astra-marusia/. Это отдельная беседа без инструментов управления сервером; семейные ответы для 10 лет. История до 16 реплик на user_id в памяти, очищается после перезапуска/суток простоя; тексты не пишутся в access log. - Слушает только
127.0.0.1:8788,/healthпроверен. Секрет пути webhook —/etc/astra-marusia.env(root 600),MARUSIA_SKILL_IDпока пуст: POST закрыты до регистрации навыка. Публичного HTTPS URL, туннеля и привязки колонки ещё нет. ⚠️ Это готовая локальная часть, не подключённая колонка. - Используется существующая авторизация Codex/ChatGPT через read-only bind
~astra/.codex/auth.jsonв отдельный CODEX_HOME/var/lib/astra-marusia; пользовательские config/rules, shell/apps/browser и проектные инструкции отключены. systemdProtectHome=tmpfs,ProtectSystem=strict,NoNewPrivileges=yes; рабочий StateDirectory 700. ⚠️ Read-only привязка auth может потребовать повторной проверки после обновления/refresh авторизации; не выдавать колонке административный тред Telegram. - Проверки: 50 тестов бота/навыка, настоящий ответ модели «Два плюс два — четыре» (7 с), успешный запуск сервиса. Webhook ждёт модель до 2 с, затем предлагает спросить «готово?»; повтор session_id/message_id идемпотентен. До двух запросов к модели одновременно, до 50 разговоров. Короткое ожидание нужно из-за задержки модели; реальное время ожидания/tts и формат платформы проверить в отладчике VK.
- Осталось владельцу: зарегистрировать приватный навык VK и прислать skill_id; для публичного адреса нужен ограниченный SSH-туннель к fr1 + HTTPS-прокси. С rpi у astra есть только ключ Gitea, доступа SSH на fr1 нет. Шаблон nginx подготовлен, на fr1 не установлен.
Открытые хвосты (на 2026-10-11)
-
USB3-хаб с питанием — теперь только ради скорости: WD Elements 1 ТБ работает второй копией в роутере (~10 МБ/с); на малине через хаб было бы ~100 МБ/с (обновлено 2026-10-11, было «копия одна»).
-
Нет node-exporter (CPU/RAM/диск самой малины в Prometheus не видны) — пуш через pushgateway для node-метрик неудобен; решить, нужен ли.
-
Первый прогон бэкапа стартовал до появления
ExecStopPost— его итог может не дойти в метрики;backup_last_success_timestampпоявится с первого прогона по таймеру. До этогоBackupStaleмолчит (серии нет). -
⏳
codex-remote.service(демонcodex remote-controlсRUST_LOG=debug) всё ещё включён и работает, хотя сопряжение не взлетело — убрать или оставить ждать поддержки Linux от OpenAI (решение за пользователем). -
Токен бота передавался через чат с ассистентом — при желании перевыпустить в @BotFather (
/revoke) и вписать в/etc/astra-bot.env. -
⚠️ Закрытый ключ age бэкапа серверов — одна копия, на Mac. Положить вторую вне малины и вне Mac (менеджер паролей/распечатка), иначе потеря Mac = бэкапы fr1/ru1 бесполезны.
-
Разово скопировать на малину
~rus/backups(5.4 ГБ) и~tgclaude/backups(4.2 ГБ) с fr1 — тогда их можно убрать с fr1. -
Пробное восстановление бэкапа серверов — раз в квартал (следующее ~январь 2027), см.
stacks/server-backup/README.md. -
Через неделю снять SMART и посчитать реальный прирост Start_Stop/Load_Cycle — прогноз ресурса пока оценочный.
-
⏳ Определить хранение входящих фото: сейчас автоматически не удаляются ради ссылок в старых тредах; очередь сообщений только в памяти и теряется при перезапуске.
-
Медиацентр: проброс 6881 tcp/udp на роутере (раздача/скорость); пароль SFTP роутера слабый (только LAN) — сменить; Kinozal и OpenSubtitles — аккаунты пользователя; решить про автообновление образов.