English · Русский · Español · Português · Deutsch · Français · Italiano · Türkçe · Українська · Polski
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.
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.
Downloads
- The task list: progress, speed, time left, seeds and peers
- Pause, resume, delete
- Adding by magnet link, by direct link and by
.torrentfile - 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.
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 local192.168.…or a self-signed one will not open. Without an address the bot works on its own — links,.torrentfiles,/statusand 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 → /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 → 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 likealex-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 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 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.
| 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.
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:
sudo sed -i "s|^TELEGRAM_BOT_TOKEN=.*|TELEGRAM_BOT_TOKEN='your-new-token'|" /var/packages/dsm-mini/var/config.env
sudo synopkg restart dsm-miniAn upgrade leaves the file alone, which is why the settings survive an update.
If the package source was added, Package Center shows the update itself. Without
a source, download the fresh .spk from the
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.
Everything is in /var/packages/dsm-mini/var/:
config.env— the settings from the DSM mini window, mode600;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.
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: theinitDatasignature 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.envon the NAS, mode600, and never reach the log: on a refusal the reason is written, never the value. - The service listens on
127.0.0.1only — 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.
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:
cd web && npm run dev # talks to the backend on localhost:58080Running 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:
cp .env.example .env # fill it in
set -a; . ./.env; set +a
go run ./cmd/dsm-miniThe 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:
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.
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.




