Ctrl K
ComunidadGuías…

README.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<img src="docs/icon.png" width="88" alt="">

# dsm-mini

**English** · [Русский](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) · [Українська](README_UK.md) · [Polski](README_PL.md)

[![Checks](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml/badge.svg)](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml)
[![MIT license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

A Telegram bot with a Mini App for running a home Synology NAS: Download Station
downloads and File Station files straight from the messenger, with no VPN and no
DSM web interface.

Drop a magnet link into the chat — the bot asks with buttons where to put it and
queues it. Open the app — you see what is downloading, how long is left, what is
on the disks and how the NAS is feeling.

<p align="center">
  <img src="docs/screenshots/en-home.webp" width="19%" alt="NAS overview">
  <img src="docs/screenshots/en-downloads.webp" width="19%" alt="Downloads">
  <img src="docs/screenshots/en-task.webp" width="19%" alt="A task">
  <img src="docs/screenshots/en-files.webp" width="19%" alt="Files">
  <img src="docs/screenshots/en-storage.webp" width="19%" alt="Storage">
</p>

> Working: the bot, the Mini App and notifications. Requires DSM 7 or newer —
> the package will not install on DSM 6, and it has never been tested there.
> Checked on DSM 7.2.2 with Download Station 4.1.2 and File Station 1.4.4.

## What it can do

**Downloads**

- The task list: progress, speed, time left, seeds and peers
- Pause, resume, delete
- Adding by magnet link, by direct link and by `.torrent` file
- Choosing the destination folder, with a configurable quick-access list
- Choosing the files inside a torrent and their priority
- A message in the chat when a task finishes or fails

**Files**

- Browsing folders, previews, uploading to the NAS
- Rename, copy, move, delete

**NAS state**

- CPU and memory load, uptime, network
- Disks, pools and volumes: temperature, space used, health
- Virtual machines and containers: start and stop
- The DSM event log

**Notifications and settings**

- What DSM announces itself — the security advisor, disks, updates — reaches the chat
- A choice of what the bot may send: nothing, downloads only, everything
- A screen of its own in the DSM main menu: the package is set up there after installation, and every setting is changed there later, without a restart

**Language**

The app and the bot speak the language chosen in Telegram: English, Russian,
Spanish, Portuguese, German, French, Italian, Turkish, Ukrainian, Polish. An
unknown language gets English.

---

## Installation

Half an hour, most of it spent on the certificate rather than on the service.
You need a Synology NAS with DSM 7 and Download Station; nothing else has to be
installed beforehand.

> **The public address is only for the Mini App.** Telegram opens a Mini App
> only over `https://` with a real certificate — a local `192.168.…` or a
> self-signed one will not open. Without an address the bot works on its own —
> links, `.torrent` files, `/status` and notifications — with nothing on the NAS
> reachable from outside. Step 4 has three ways to get one, two of them with no
> ports opened on the router.

**1. Create the bot.** [@BotFather](https://t.me/BotFather) → `/newbot` → a name
and a username ending in `bot`. It answers with a token; keep it, it is the
password to your bot.

**2. Find out your number.** [@userinfobot](https://t.me/userinfobot) → Start.
It answers with the `Id` line.

**3. Make a DSM user for the service.** Control Panel → User & Group → Create.
Access to Download Station and File Station only, no two-factor verification — a
one-time code cannot be typed in from a configuration file. Do not give it an
administrator: the service can delete files. Whether the account is enough, the
**Check the account** button in the DSM mini window (step 6) shows: it signs in
as this user and lists what DSM lets it do.

**4. Get an address for the Mini App** — or skip this step and use the bot on
its own. The address has to open over `https://` on the phone you use Telegram
on. There are three ways. The first goes through DSM and needs ports forwarded
on the router; skip it if the NAS already has a domain with a valid certificate:

- Control Panel → External Access → DDNS → Add, provider `Synology` — that
  gives something like `alex-nas.synology.me`.
- On the router, forward ports **80** and **443** to the NAS. Without 80 the
  certificate will not be issued, without 443 the app will not open.
- Control Panel → Security → Certificate → Add → from Let's Encrypt, for that
  same name.

Check it from a phone on mobile internet: `https://alex-nas.synology.me:5001`
should open DSM with no warnings.

The second is **Cloudflare Tunnel**, with no ports opened; it needs a domain
whose DNS is on Cloudflare. Create a tunnel in the Cloudflare dashboard, install
the **Cloudflare Tunnel** package from
[SynoCommunity](https://synocommunity.com) with the tunnel's token, and give the
tunnel a public hostname — say `mini.example.com` — with the service
`http://localhost:58080`.

The third is **Tailscale**, for your own devices only. Install Tailscale on the
NAS and on the phone, turn on HTTPS certificates in your tailnet's DNS settings,
and run `sudo tailscale serve --bg 58080` on the NAS: it prints an address like
`https://nas.tail1234.ts.net`. The app then opens while the phone is connected
to Tailscale.

**5. Install the package.** Package Center → Settings → Package Sources → Add,
name `dsm-mini` and the address for your architecture:

- Intel and AMD, most models: `https://alexlnos.github.io/dsm-mini/amd64.json`
- ARM, budget models: `https://alexlnos.github.io/dsm-mini/arm64.json`

Then Settings → General → Trust Level → **Any publisher**, and install
**DSM mini — Telegram Mini App** from the **Community** section. Not sure about
the architecture? Try `amd64`: a package that does not fit is simply refused.

Nothing is asked during installation. Or install the `.spk` from the
[releases](https://github.com/alexlnos/dsm-mini/releases) by hand, through
Package Center → Manual Install.

**6. Set it up.** Open **DSM mini** from the DSM main menu, or press **Open** in
Package Center — it says so itself when the installation is done. Fill in the
values collected in the steps above — the window explains each one — and under
**Mini App access** pick the way from step 4, or **The bot only, no Mini App**.
Press **Save**, then **Start** at the top of the window. The status there says
when DSM and the bot have answered, and what is wrong if they have not.

For the first way, the window creates the reverse proxy rule itself: type your
name under **Point a name at the service**. By hand it is Control Panel → Login
Portal → Advanced → Reverse Proxy → Create. Source: `HTTPS`, your name, port
`443`. Destination: `HTTP`, `localhost`, port `58080`. With a tunnel or
Tailscale, pick **Another way** and enter the address they gave.

> Do not proxy port **80** for this name: DSM renews the certificate through it,
> and intercepting it breaks the renewal three months later.

**7. Check.** With an address, `https://your-address/healthz` in a browser
should answer `{"status":"ok"}`. Nothing is given away without a Telegram
signature.

**8. Open the app.** Find the bot by its username, press Start, and a
**Downloads** button appears next to the input field. Send it any magnet link —
it offers folders as buttons. Without an address there is no such button: send
the links to the bot in the chat.

## If something went wrong

| What you see | What it is | What to do |
|---|---|---|
| The bot is silent on `/start` | The bot is switched off or not set up, or the token is wrong | Open **DSM mini** in the DSM main menu: the status at the top says which, and **Start** switches the bot on |
| "Access to this bot is closed" | Your ID is not on the list | Add the number from step 2 to the allowed IDs in the **DSM mini** window |
| There is no app button | The public address is empty — the bot on its own — or not `https://` | The **DSM mini** window, **Mini App access** |
| The button is there, the app does not open | The reverse proxy or the certificate is not working | Open `https://your-address/healthz` in a browser |
| "Open the app through the bot" | The app was opened by a direct link in a browser | That is intended: open it from the bot |
| "Access denied: your Telegram ID…" | The service did not recognise you | The allowed IDs take digits only, comma separated |
| The window says DSM refused the sign-in | The password, 2FA or the user's permissions | Step 3: password without typos, 2FA off, applications allowed |
| The window says Download Station is not running | It is not installed, or is denied to the user | Package Center and the permissions from step 3 |
| The package stops right after starting | Its port is taken by something else — the log says so | Change `LISTEN_ADDR` in `config.env` over SSH (see below) |

The first place to look is the status line at the top of the **DSM mini**
window: it says whether DSM and Telegram have answered and, if not, why. The
details are in the package log, `/var/packages/dsm-mini/var/dsm-mini.log`, which
also opens from Package Center.

### Changing the settings

**Open DSM mini in the DSM main menu** — every setting is there. The password
and the token are write-only: leave a field empty and it keeps what it had. A
save applies at once: the service starts again with it by itself, and the
package does not have to be restarted.

The settings live in one file on the NAS,
`/var/packages/dsm-mini/var/config.env`, mode `600`. It can also be edited over
SSH (Control Panel → Terminal & SNMP → Enable SSH); restart the package
afterwards:

```bash
sudo sed -i "s|^TELEGRAM_BOT_TOKEN=.*|TELEGRAM_BOT_TOKEN='your-new-token'|" /var/packages/dsm-mini/var/config.env
sudo synopkg restart dsm-mini
```

An upgrade leaves the file alone, which is why the settings survive an update.

## Updating

If the package source was added, Package Center shows the update itself. Without
a source, download the fresh `.spk` from the
[releases](https://github.com/alexlnos/dsm-mini/releases) and install it over the
old one.

The settings and the database survive either way: they live in the package's
`var` directory, which an upgrade does not touch.

## Where the data is kept

Everything is in `/var/packages/dsm-mini/var/`:

- `config.env` — the settings from the DSM mini window, mode `600`;
- `dsm-mini.db` — an SQLite database: the pinned folders, the language and the
  last known task statuses, from which the service knows what it has already
  reported;
- `dsm-mini.log` — the log.

An upgrade of the package keeps all three. Uninstalling removes them.

## Security

The service is exposed to the internet and can delete files on the NAS, so:

- **A separate DSM user**, not an administrator (step 3).
- **No two-factor verification** on that account: a one-time code cannot work
  from a configuration file.
- **The allowed IDs are an allow list.** An empty list closes access to everyone,
  it does not open it.
- Every request to `/api/` is checked twice: the `initData` signature with a key
  derived from the bot token, and the id against the allowed list. The signature
  only proves that a person opened the bot — and anyone can open it.
- The outside gets a generic phrase, the details go to the log: a message saying
  exactly what did not match in the signature would be a hint on how to forge it.
- The bot token and the DSM password live only in `config.env` on the NAS, mode
  `600`, and never reach the log: on a refusal the reason is written, never the
  value.
- The service listens on `127.0.0.1` only — from the NAS itself. Everything from
  outside comes through whatever serves the public address — the DSM reverse
  proxy, a tunnel or Tailscale — which also terminates TLS. With no address,
  nothing from outside reaches it at all.

## Development

```bash
cd web && npm install && npm run build   # the Mini App lands in internal/web/dist
cd .. && go build ./cmd/dsm-mini         # a binary with the app embedded
go test ./...
```

The frontend on its own, with hot reload:

```bash
cd web && npm run dev    # talks to the backend on localhost:58080
```

Running the backend locally reads `config.env` in `STATE_DIR`, the way the
package does, and environment variables fill in what the file does not say. It
is convenient to keep them in a file:

```bash
cp .env.example .env     # fill it in
set -a; . ./.env; set +a
go run ./cmd/dsm-mini
```

The built interface is in the repository (`internal/web/dist`) — `go:embed`
picks it up. After changing the frontend, rebuild and commit the result,
otherwise the checks will not pass.

Integration tests run against a real NAS and are skipped by default:

```bash
DSM_URL=https://192.168.1.10:5001 DSM_USER=... DSM_PASSWORD=... \
  DSM_INSECURE_TLS=true go test -tags=integration ./...
```

Tests that change the state of the NAS need separate permission:
`DSM_TEST_MUTATIONS=1`, and for file operations also `DSM_TEST_FOLDER` — the
folder inside which temporary files may be created. They delete everything they
created.

A new interface language is one dictionary file on each side:
`web/src/i18n/<code>.ts` and `internal/i18n/<code>.go`. You cannot miss a string:
on the frontend the type watches for that, on the server a test does.

## Synology API quirks

The Synology Web API behaves differently from its documentation in places: one
and the same action answers in three different shapes, `limit = -1` takes File
Station down, and `_sid` during a file upload has to be passed differently from
everywhere else. Everything learned on a live NAS is collected in
[docs/synology-api.md](docs/synology-api.md).

## License

[MIT](LICENSE)