# dsm-mini
[English](README.md) · [Русский](README_RU.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) · **Українська** · [Polski](README_PL.md)
[](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml)
[](LICENSE)
Telegram-бот з Mini App для керування домашнім NAS Synology: завантаження
Download Station і файли File Station просто з месенджера, без VPN і
вебінтерфейсу DSM.
Кинули magnet-посилання в чат — бот кнопками запитав, куди качати, і поставив у
чергу. Відкрили застосунок — видно, що завантажується, скільки лишилося, що
лежить на дисках і як почувається 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)