# dsm-mini [English](README.md) · **Русский** · [Español](README_ES.md) · [Português](README_PT.md) · [Deutsch](README_DE.md) · [Français](README_FR.md) · [Italiano](README_IT.md) · [Türkçe](README_TR.md) · [Українська](README_UK.md) · [Polski](README_PL.md) [![Проверки](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml/badge.svg)](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml) [![Лицензия MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) Telegram-бот с Mini App для управления домашним NAS Synology: закачки Download Station и файлы File Station прямо из мессенджера, без VPN и веб-интерфейса DSM. Кинули magnet-ссылку в чат — бот спросил кнопками, куда качать, и поставил в очередь. Открыли приложение — видно, что качается, сколько осталось, что лежит на дисках и как себя чувствует NAS.

Обзор NAS Загрузки Задача Файлы Хранилище

> Работает: бот, Mini App и уведомления. Нужен DSM 7 или новее — на DSM 6 > пакет не встанет, и там его никто не проверял. Проверено на DSM 7.2.2 с > Download Station 4.1.2 и File Station 1.4.4. ## Что это умеет **Загрузки** - Список задач: прогресс, скорость, оставшееся время, сиды и пиры - Пауза, возобновление, удаление - Добавление magnet-ссылкой, прямой ссылкой и файлом `.torrent` - Выбор папки назначения с настраиваемым списком быстрого доступа - Выбор файлов внутри раздачи и их приоритета - Сообщение в чат, когда задача завершилась или упала **Файлы** - Обзор папок, предпросмотр, загрузка на NAS - Переименование, копирование, перенос, удаление **Состояние NAS** - Загрузка процессора и памяти, время работы, сеть - Диски, пулы и тома: температура, занятое место, здоровье - Виртуальные машины и контейнеры: запуск и остановка - Журнал событий DSM **Уведомления и настройки** - То, о чём сообщает сам DSM — советник по безопасности, диски, обновления, — приходит в чат - Выбор, что бот может присылать: ничего, только загрузки, всё - Свой экран в главном меню DSM: там пакет настраивается после установки и там же потом меняется любая настройка, без перезапуска **Язык** Приложение и бот говорят на языке, выбранном в Telegram: английский, русский, испанский, португальский, немецкий, французский, итальянский, турецкий, украинский, польский. Незнакомый язык получает английский. --- ## Установка Полчаса, и большая часть уйдёт на сертификат, а не на сам сервис. Нужен NAS Synology с DSM 7 и Download Station; больше ничего заранее ставить не надо. > **Публичный адрес нужен только для Mini App.** Telegram открывает Mini App > только по `https://` с настоящим сертификатом — локальный `192.168.…` и > самоподписанный не откроются. Без адреса бот работает сам по себе — ссылки, > файлы `.torrent`, `/status` и уведомления, — и открывать NAS наружу не нужно. > Три способа получить адрес — в шаге 4, два из них обходятся без проброса > портов на роутере. **1. Создать бота.** [@BotFather](https://t.me/BotFather) → `/newbot` → имя и логин, заканчивающийся на `bot`. В ответ придёт токен; сохраните его, это пароль от вашего бота. **2. Узнать свой номер.** [@userinfobot](https://t.me/userinfobot) → Start. Он ответит строкой `Id`. **3. Завести пользователя DSM для службы.** Панель управления → Пользователь и группа → Создать. Доступ только к Download Station и File Station, без двухэтапной проверки — одноразовый код неоткуда взять в файле настроек. Администратора не давайте: служба умеет удалять файлы. Хватает ли этой учётной записи прав, покажет кнопка **Проверить учётную запись** в окне DSM mini (шаг 6): она входит от имени этого пользователя и перечисляет, что DSM ему разрешает. **4. Получить адрес для Mini App** — или пропустите этот шаг, и бот будет работать сам по себе. Адрес должен открываться по `https://` на телефоне, где у вас Telegram. Способов три. Первый — через DSM, с пробросом портов на роутере; его можно пропустить, если у NAS уже есть домен с действующим сертификатом: - Панель управления → Внешний доступ → DDNS → Добавить, поставщик `Synology` — получится что-то вроде `alex-nas.synology.me`. - На роутере пробросьте на NAS порты **80** и **443**. Без 80 не выпустится сертификат, без 443 не откроется приложение. - Панель управления → Безопасность → Сертификат → Добавить → от Let's Encrypt, на то же имя. Проверьте с телефона по мобильному интернету: `https://alex-nas.synology.me:5001` должен открыть DSM без предупреждений. Второй — **Cloudflare Tunnel**, без проброса портов; нужен домен, DNS которого в Cloudflare. Создайте туннель в панели Cloudflare, поставьте пакет **Cloudflare Tunnel** из [SynoCommunity](https://synocommunity.com) с токеном этого туннеля и добавьте туннелю публичное имя — скажем, `mini.example.com` — со службой `http://localhost:58080`. Третий — **Tailscale**, только для своих устройств. Поставьте Tailscale на NAS и на телефон, включите сертификаты HTTPS в настройках DNS своей сети Tailscale и выполните на NAS `sudo tailscale serve --bg 58080`: он выдаст адрес вида `https://nas.tail1234.ts.net`. Приложение будет открываться, пока телефон подключён к Tailscale. **5. Установить пакет.** Центр пакетов → Настройки → Источники пакетов → Добавить, имя `dsm-mini` и адрес по вашей архитектуре: - Intel и AMD, большинство моделей: `https://alexlnos.github.io/dsm-mini/amd64.json` - ARM, бюджетные модели: `https://alexlnos.github.io/dsm-mini/arm64.json` Дальше Настройки → Общие → Доверенный уровень → **Любой издатель**, и поставьте **DSM mini — Telegram Mini App** из раздела **Сообщество**. Не уверены в архитектуре? Пробуйте `amd64`: неподходящий пакет просто не поставится. При установке ничего не спрашивается. Либо поставьте `.spk` из [релизов](https://github.com/alexlnos/dsm-mini/releases) вручную, через Центр пакетов → Ручная установка. **6. Настроить.** Откройте **DSM mini** в главном меню DSM или нажмите **Открыть** в Центре пакетов — он и сам подскажет это после установки. Заполните значения, собранные на шагах выше, — окно объяснит каждое, — а в разделе **Доступ к Mini App** выберите способ из шага 4 или **Только бот, без Mini App**. Нажмите **Сохранить**, а затем **Запустить** вверху окна. Статус там покажет, когда ответили DSM и бот, а если не ответили — что не так. Для первого способа правило обратного прокси окно создаёт само: впишите имя в поле **Направить имя в службу**. Вручную это Панель управления → Портал входа → Дополнительно → Обратный прокси-сервер → Создать. Источник: `HTTPS`, ваше имя, порт `443`. Назначение: `HTTP`, `localhost`, порт `58080`. С туннелем или Tailscale выберите **Другой способ** и впишите адрес, который они выдали. > Порт **80** для этого имени не проксируйте: через него DSM продлевает > сертификат, и перехват сломает продление через три месяца. **7. Проверить.** Если адрес есть, `https://ваш-адрес/healthz` в браузере должен ответить `{"status":"ok"}`. Без подписи Telegram наружу ничего не отдаётся. **8. Открыть приложение.** Найдите бота по логину, нажмите Start — рядом с полем ввода появится кнопка **Загрузки**. Пришлите ему любую magnet-ссылку, он предложит папки кнопками. Без адреса кнопки не будет — ссылки просто присылайте боту в чат. ## Если что-то пошло не так | Что видите | В чём дело | Что делать | |---|---|---| | Бот молчит на `/start` | Бот выключен или не настроен, либо неверный токен | Откройте **DSM mini** в главном меню DSM: статус вверху скажет, что именно, а **Запустить** включит бота | | «Доступ к этому боту закрыт» | Вашего ID нет в списке | Впишите номер из шага 2 в разрешённые ID в окне **DSM mini** | | Кнопки приложения нет | Публичный адрес пуст — тогда работает только бот — или не `https://` | Окно **DSM mini**, раздел **Доступ к Mini App** | | Кнопка есть, приложение не открывается | Не работает обратный прокси или сертификат | Откройте `https://ваш-адрес/healthz` в браузере | | «Откройте приложение через бота» | Приложение открыто прямой ссылкой в браузере | Так и задумано: открывайте из бота | | «Доступ закрыт: вашего Telegram ID…» | Сервис вас не узнал | В разрешённых ID только цифры, через запятую | | Окно пишет, что DSM не принял вход | Пароль, 2FA или права пользователя | Шаг 3: пароль без опечаток, 2FA выключена, приложения разрешены | | Окно пишет, что Download Station не запущена | Она не установлена или запрещена пользователю | Центр пакетов и права из шага 3 | | Пакет останавливается сразу после запуска | Его порт занят чем-то другим — журнал так и скажет | Поменяйте `LISTEN_ADDR` в `config.env` по SSH (см. ниже) | Первое, куда смотреть, — строка состояния вверху окна **DSM mini**: она говорит, ответили ли DSM и Telegram, а если нет — почему. Подробности — в журнале пакета, `/var/packages/dsm-mini/var/dsm-mini.log`, он же открывается из Центра пакетов. Журнал ведётся по-английски, окно, интерфейс и сообщения бота — на вашем языке. ### Поменять настройки **Откройте DSM mini в главном меню DSM** — там все настройки. Пароль и токен только на запись: оставьте поле пустым, и оно сохранит прежнее. Сохранение применяется сразу: служба сама перезапускается с новыми настройками, пакет перезапускать не нужно. Настройки лежат на NAS в одном файле `/var/packages/dsm-mini/var/config.env` с правами `600`. Его можно поправить и по SSH (Панель управления → Терминал и SNMP → включить SSH), а потом перезапустить пакет: ```bash sudo sed -i "s|^TELEGRAM_BOT_TOKEN=.*|TELEGRAM_BOT_TOKEN='ваш-новый-токен'|" /var/packages/dsm-mini/var/config.env sudo synopkg restart dsm-mini ``` Обновление файл не трогает, поэтому настройки его переживают. ## Обновление Если добавлен источник пакетов, Центр пакетов сам покажет обновление. Без источника — скачайте свежий `.spk` из [релизов](https://github.com/alexlnos/dsm-mini/releases) и поставьте поверх. Настройки и база в обоих случаях останутся: они лежат в каталоге `var` пакета, а его обновление не трогает. ## Где хранятся данные Всё в `/var/packages/dsm-mini/var/`: - `config.env` — настройки из окна DSM mini, права `600`; - `dsm-mini.db` — база SQLite: закреплённые папки, язык и последние известные статусы задач, по которым сервис понимает, о чём уже сообщал; - `dsm-mini.log` — журнал. Обновление пакета сохраняет все три. Удаление пакета — удаляет. ## Безопасность Сервис выставлен в интернет и умеет удалять файлы на NAS, поэтому: - **Отдельный пользователь DSM**, а не администратор (шаг 3). - **Без двухэтапной проверки** у этой учётной записи: одноразовый код в конфигурации работать не будет. - **Разрешённые ID — белый список.** Пустой список закрывает доступ всем, а не открывает. - Каждый запрос к `/api/` проверяется дважды: подпись `initData` ключом от токена бота и идентификатор в списке разрешённых. Подпись доказывает лишь то, что человек открыл бота, — открыть его может любой. - Наружу отдаётся общая фраза, подробности — в журнал: сообщение о том, что именно не сошлось в подписи, подсказывало бы, как её подобрать. - Токен бота и пароль DSM живут только в `config.env` на самом NAS с правами `600` и в журнал не попадают: при отказе пишется причина, но не значение. - Служба слушает только `127.0.0.1` — то есть с самого NAS. Всё снаружи идёт через то, что обслуживает публичный адрес, — обратный прокси DSM, туннель или Tailscale, — он же разбирает TLS. Без адреса снаружи до неё не доходит ничего. ## Разработка ```bash cd web && npm install && npm run build # Mini App попадёт в internal/web/dist cd .. && go build ./cmd/dsm-mini # бинарник со встроенным приложением go test ./... ``` Фронтенд отдельно, с автообновлением: ```bash cd web && npm run dev # ходит в бэкенд на localhost:58080 ``` Локальный запуск бэкенда читает `config.env` из `STATE_DIR`, как и пакет, а переменные окружения дополняют то, чего в файле нет. Удобно держать их в файле: ```bash cp .env.example .env # заполните set -a; . ./.env; set +a go run ./cmd/dsm-mini ``` Собранный интерфейс лежит в репозитории (`internal/web/dist`) — его забирает `go:embed`. После правок фронтенда пересоберите и закоммитьте результат, иначе проверки не пройдут. Интеграционные тесты работают против настоящего NAS и по умолчанию пропускаются: ```bash DSM_URL=https://192.168.1.10:5001 DSM_USER=... DSM_PASSWORD=... \ DSM_INSECURE_TLS=true go test -tags=integration ./... ``` Тесты, которые меняют состояние NAS, требуют отдельного разрешения: `DSM_TEST_MUTATIONS=1`, а для файловых операций ещё и `DSM_TEST_FOLDER` — папку, внутри которой можно создавать временные файлы. Всё созданное они удаляют за собой. Новый язык интерфейса — один файл словаря на каждой стороне: `web/src/i18n/<код>.ts` и `internal/i18n/<код>.go`. Пропустить строку не выйдет: на фронтенде за этим следит тип, на сервере — тест. Код, комментарии и журнал в проекте — по-английски; русский живёт только в словарях перевода. Подробности — в [CLAUDE.md](CLAUDE.md). ## Особенности Synology API Web API Synology местами ведёт себя не так, как написано в документации: одно и то же действие отвечает в трёх разных форматах, `limit = -1` роняет File Station, а `_sid` при загрузке файла нужно передавать иначе, чем везде. Всё, что выяснено на живом NAS, собрано в [docs/synology-api.md](docs/synology-api.md). ## Лицензия [MIT](LICENSE)