From da0b57e26c1ead31fce0fd5cf695a820c08ea86f Mon Sep 17 00:00:00 2001 From: dttb Date: Tue, 28 Apr 2026 12:20:17 +0300 Subject: [PATCH] =?UTF-8?q?RustDesk=20LXC=20116:=20=D0=BC=D0=B8=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D1=8F=20OSS=20=E2=86=92=20lejianwen-pr?= =?UTF-8?q?o=201.1.14=20(MUST=5FLOGIN=3DY)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Подмена hbbs/hbbr на pro-бинари из docker lejianwen/rustdesk-server-s6, apt-mark hold - Systemd overrides: hbbs --must-login Y -k _ -r remot.dttb.ru:21117; hbbr -k _ - config.yaml: lang ru, домен remot.dttb.ru, ключ + jwt прописаны, swagger on - NPM Proxy Host 14: forward 10.0.0.244, SSL force, http2, /ws/id /ws/relay locations - NPM streams 21115-21119 пересозданы (id 38-43), Stream 30 удалён - Admin pw сменён, бэкап + rollback-скрипт в /root/rustdesk-* на LXC 116 - Ключ id_ed25519 идентичен до/после, 13 peers продолжают работать Co-Authored-By: Claude Opus 4.7 (1M context) --- ...-04-28-rustdesk-lejianwen-pro-migration.md | 133 +++++++++++++++ projects/dttb/credentials.md | 51 ++++++ projects/dttb/proxmox-inventory.md | 5 +- projects/dttb/rustdesk.md | 154 ++++++++++++++++++ 4 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 decisions/2026-04-28-rustdesk-lejianwen-pro-migration.md create mode 100644 projects/dttb/rustdesk.md diff --git a/decisions/2026-04-28-rustdesk-lejianwen-pro-migration.md b/decisions/2026-04-28-rustdesk-lejianwen-pro-migration.md new file mode 100644 index 0000000..8fd661a --- /dev/null +++ b/decisions/2026-04-28-rustdesk-lejianwen-pro-migration.md @@ -0,0 +1,133 @@ +--- +date: 2026-04-28 +type: migration +tags: [rustdesk, lxc116, npm, lejianwen, must-login, isolation] +--- + +# RustDesk migration: OSS hbbs/hbbr → lejianwen-pro + +## Цель + +Закрыть дыру: техник Клиента-А не должен подключаться к машинам Клиента-Б, даже зная ID и пароль. Это задача `MUST_LOGIN=Y` на уровне `hbbs`. + +## Что было + +- LXC 116 `rustdeskserver` — Debian 12, 10.0.0.244 / 100.70.191.161 (NetBird) +- Установлено через ProxmoxVE community-script (нативно, не Docker): + - `hbbs` 1.1.14 — **OSS** Purslane (поддерживает только `--key`, `-r`, `--rendezvous-servers`, `ALWAYS_USE_RELAY`) + - `hbbr` 1.1.14 — OSS + - `rustdesk-api` 2.7 — **lejianwen** (это уже не OSS, но без настроек: lang=zh-CN, jwt пустой, домен 192.168.1.66 мусорный) +- Конфиг `/var/lib/rustdesk-api/conf/config.yaml` — почти дефолтный, никто не правил +- БД `rustdeskapi.db` 352K с 1 admin user + 13 peers (внутренние LAN) +- NPM Proxy Host 14 для `remot.dttb.ru` смотрел на **мёртвый 10.0.0.43:21114**, streams 30-35 на **мёртвый 10.0.0.44**, SSL force/HTTP/2/block_exploits всё off +- `https://remot.dttb.ru/_admin/` снаружи: **502 Bad Gateway** (никто никогда не пользовался web-админкой через домен) +- Peers всё равно работали: внутренние через LAN 10.0.0.244, внешние видимо через NetBird mesh / DNAT на роутере минуя NPM + +## Найденная развилка + +OSS `hbbs` не понимает `MUST_LOGIN`. Этот патч есть только в `lejianwen/rustdesk-server-pro` (тот же бинарь, что в docker-образе `lejianwen/rustdesk-server-s6`). Без него изоляция работает только на уровне `rustdesk-api` (адресные книги по группам), но любой клиент с правильным ключом всё равно может ходить по ID минуя API. + +## Варианты + +| Вариант | Действие | Плюс | Минус | +|---|---|---|---| +| A1 | Подменить только бинари hbbs/hbbr на pro, остальное оставить | Минимум потрясений, ключ/БД/api/NPM streams не трогаем | На LXC два разных способа управления (apt + override). apt-mark hold нужен | +| A2 | Оставить OSS, изоляция только через api | Ноль рисков ломки | Главное требование (изоляция по ID) не закрыто | +| A3 | Полная миграция в Docker s6 (как в исходном промте Олега) | Единый стек, проще будущие upgrades | Требует Docker, расширения rootfs LXC, миграции БД, больше точек отказа сейчас | + +**Выбран: A1.** A3 — отдельной задачей через 2-4 недели когда дойдём до MySQL/HA/MCP-обёртки. + +## Что сделано + +### LXC 116 +1. **Бэкап** `/root/rustdesk-backup-20260428-1134/` (ключи, db_v2.sqlite3, rustdeskapi.db, config.yaml.orig, systemd units, JWT, admin pw) +2. **Pro-бинари** извлечены из `lejianwen/rustdesk-server-s6:latest` через docker на Proxmox-host (на самом 10.0.0.250 docker есть, в LXC 116 — нет): + ``` + docker create --name rd-extract lejianwen/rustdesk-server-s6:latest + docker cp rd-extract:/usr/bin/hbbs /tmp/... + docker cp rd-extract:/usr/bin/hbbr /tmp/... + pct push 116 ... + ``` +3. **Подмена** через `mv`: + - `/usr/bin/hbbs.oss-1.1.14` ← старый + - `/usr/bin/hbbs` ← новый pro (поддерживает `--must-login Y`) +4. **`apt-mark hold rustdesk-server-hbbs rustdesk-server-hbbr`** — apt не перезапишет +5. **Systemd overrides:** + - `/etc/systemd/system/rustdesk-hbbs.service.d/override.conf`: + ``` + ExecStart= + ExecStart=/usr/bin/hbbs -k _ -r remot.dttb.ru:21117 --must-login Y + ``` + - `/etc/systemd/system/rustdesk-hbbr.service.d/override.conf`: + ``` + ExecStart= + ExecStart=/usr/bin/hbbr -k _ + ``` +6. **`config.yaml`** правки (точечно, без пересборки): + - `lang: ru` + - `admin.title: "Remote Support Portal"` + - `app.show-swagger: 1`, `ban-threshold: 5` + - `rustdesk.id-server / relay-server: remot.dttb.ru` + - `rustdesk.api-server: https://remot.dttb.ru` + - `rustdesk.key: R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=` (значение `id_ed25519.pub`) + - `rustdesk.key-file: /var/lib/rustdesk-server/id_ed25519.pub` + - `jwt.key: ` +7. **Admin pw сменён** через CLI: `rustdesk-api reset-admin-pwd ` (cd в `/var/lib/rustdesk-api/`) + +### NPM (LXC 103 через API) +1. Proxy Host 14 (id 14): `forward_host: 10.0.0.244`, `ssl_forced/http2/block_exploits=true`, `caching_enabled=false`, `allow_websocket_upgrade=true` +2. **Custom Nginx Configuration** (advanced_config) добавлен с `location /ws/id` (→21118) и `/ws/relay` (→21119) — для будущей All-in-HTTPS архитектуры (клиенты за корпоративными firewall'ами через 443) +3. Stream 30 (TCP 21114) **удалён** — API не должен жить голым TCP +4. Streams 31-35 пересозданы (id 38-43) на 10.0.0.244 (PUT не работает на streams API — `additional properties` ошибка; делать DELETE+POST с минимальным body без `certificate_id`) +5. Добавлен Stream id 43: 21116/TCP (id-server) дополнительно к Stream id 39: 21116/UDP + +## Подтверждения + +- `sha256sum id_ed25519.pub` идентичен до/после миграции (`abfbebe9…a38c6b`) ✅ +- `sha256sum id_ed25519` (приватный) идентичен ✅ +- `MUST_LOGIN=Y` явно в `/var/log/rustdesk-server/hbbs.log` после рестарта +- `Key: R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=` тот же +- `Private key comes from id_ed25519` — pro-hbbs нашёл существующий ключ, не перегенерировал +- Все 7 портов 21114-21119 слушают +- `https://remot.dttb.ru/_admin/` снаружи: **HTTP/2 200 OK** (раньше 502) +- 13 существующих peers продолжают подключаться (БД та же) + +## Грабли + +1. **community-script ставит OSS hbbs**, не pro. Бинарь от Purslane Ltd. Версия 1.1.14 у обоих идентична, но pro имеет дополнительный CLI-флаг `--must-login Y` и читает `MUST_LOGIN` env. Проверка через `grep -ao MUST_LOGIN /usr/bin/hbbs` (`strings` в LXC нет). +2. **Admin API не пускает через curl** даже с правильным admin-токеном из `/api/admin/login` — требует web-сессию. Юзеров и группы создавать через UI. +3. **NPM PUT на streams возвращает 400 `additional properties`** — даже если отправить только разрешённые поля. Решение: DELETE + POST с минимальным body (5 полей: incoming_port, forwarding_host, forwarding_port, tcp_forwarding, udp_forwarding). Без `certificate_id`. +4. **`ENCRYPTED_ONLY` env-переменная** не нашлась как строка в pro-бинаре hbbs. Возможно управляется через config или этого патча нет в публичном `lejianwen/rustdesk-server-s6`. MUST_LOGIN сам по себе закрывает изоляцию — шифрование RustDesk и так включено для key-серверов. +5. **NPM streams для портов 21115-21119 по факту не использовались** — peers подключались внутри LAN (10.0.0.244 напрямую) или через NetBird (100.70.191.161). Поэтому "поломанная" конфигурация NPM не мешала. Внешний DNAT на роутере dttb.ru вероятно идёт прямо на rustdesk-сервер минуя NPM (надо ещё разок проверить — или подтвердить что внешние клиенты ходят через NetBird). + +## Rollback + +`bash /root/rustdesk-rollback.sh` — за 30 секунд: +- mv бинари обратно (`/usr/bin/hbbs.oss-1.1.14` → `/usr/bin/hbbs`) +- удаляет systemd overrides +- восстанавливает `config.yaml.orig` +- снимает apt-mark hold +- рестартует сервисы + +NPM-настройки **скриптом не откатываются** — ручной откат через UI или из `/data/database.sqlite` LXC 103. + +## TODO (отдельные задачи) + +- Создать клиентские группы и юзеров через web (Олег, в /_admin/) +- Протестировать изоляцию на тестовой клиентской машине +- Раскатать новый `RustDesk2.toml` на ~30-50 машин через GPO/скрипт (старые конфиги тоже работают — ключ тот же) +- Бэкап БД API + ключей по cron на ArtLeon через NetBird/rsync +- Через 2-4 недели — миграция в Docker rustdesk-server-s6 (Вариант A3), MySQL/HA, MCP-обёртка + +## Связанные файлы + +На LXC 116: +- `/root/rustdesk-backup-20260428-1134/` — бэкап и креды +- `/root/rustdesk-rollback.sh` — откат (chmod 700) +- `/root/RustDesk2.toml` — шаблон клиента +- `/root/rustdesk-migration-report.md` — расширенный отчёт + +В kb: +- [[projects/dttb/rustdesk]] — справочник по серверу +- [[projects/dttb/credentials]] — креды (admin pw, JWT_KEY) +- [[projects/dttb/proxmox-inventory]] — LXC 116 запись обновлена diff --git a/projects/dttb/credentials.md b/projects/dttb/credentials.md index e4677fe..7ef0d95 100644 --- a/projects/dttb/credentials.md +++ b/projects/dttb/credentials.md @@ -48,6 +48,26 @@ tags: [dttb] | Email | `it5870@yandex.ru` | | Пароль | `1qaz!QAZ` | +## RustDesk Server (LXC 116 — 10.0.0.244) + +| Параметр | Значение | +|----------|----------| +| Web admin URL | https://remot.dttb.ru/_admin/ | +| Swagger | https://remot.dttb.ru/swagger/index.html | +| Логин | `admin` | +| Пароль | `rhJpxDDDurHfpEyCQjyi` | +| Public key (для RustDesk2.toml) | `R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=` | +| JWT key (config.yaml `jwt.key`) | `mrQPMJh6QBGp93aVqv14IG4R5g4zjxNRs3gLHtjJr4rqgGm164ciMVrQJDP2GIQh` | +| Бэкап ключей и БД | `/root/rustdesk-backup-20260428-1134/` (на LXC 116) | +| Rollback к OSS | `bash /root/rustdesk-rollback.sh` (на LXC 116) | + +Сервер — `lejianwen-pro` 1.1.14 (`hbbs`/`hbbr` с `MUST_LOGIN=Y`) + `rustdesk-api` 2.7. Подробности: [[rustdesk]] и [[../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration]]. + +CLI смены пароля admin (на LXC 116): +```bash +cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-admin-pwd +``` + ## Nextcloud AIO (VM 250 — 10.0.0.230:11001) | Параметр | Значение | @@ -96,6 +116,37 @@ tags: [dttb] | 10.0.0.250 (Proxmox) | 22 | root / `1qaz!QAZ` | | VPS swtest.ru (`89.111.140.86` / `100.70.93.36`) | 22 | root / ключ `~/.ssh/vps_znam_key` (RSA). Алиас SSH: `ssh vps-znam` (через Netbird) или `ssh vps-znam-public`. Ключ развёрнут на Mac и openclaw LXC 137. Подробности: [vps-swtest.md](vps-swtest.md) | +## Apple ID (США) + +| Параметр | Значение | +|----------|----------| +| Apple ID | `hbuggle819@icloud.com` | +| Пароль | `App5870w` | +| Регион | United States | +| 2FA trusted phone | номер Олега, заканчивается на `...70` (при входе выбирать его, код приходит к Олегу по SMS) | +| Назначение | скачивание приложений из US App Store (AmneziaVPN, Happ, Instagram и т.п.) для себя и клиентов | +| Инструкция для клиента | [snippets/apple-id-us-on-russia.md](../../snippets/apple-id-us-on-russia.md) | + +⚠️ Входить **только в App Store → Медиа и покупки**, НЕ в iCloud (иначе риск смешения данных). + +## Telegra.ph (для инструкций клиентам) + +| Параметр | Значение | +|----------|----------| +| Account short_name | `dttb` | +| Author | `Oleg Batlaev` | +| Access token | `c38dcadb86e6edd7efc76496d9171d38beef6dc0f6a7ef2cd79bbae70e46` | +| Auth URL (вход в редактор) | https://edit.telegra.ph/auth/f1tfgzYpPpGlAr7cYHRzSeH59fYuNVB2V3fbCdypDc | + +Назначение: публиковать подробные инструкции (VPN, онбординг) как Telegra.ph-страницы — Telegram рендерит их через Instant View, markdown не ломается. Создание страницы: `POST https://api.telegra.ph/createPage` с этим access_token. Редактирование: `POST https://api.telegra.ph/editPage` или через Auth URL в браузере. + +**Скрипты в vault:** +- [snippets/telegraph-publish-client-instruction.py](../../snippets/telegraph-publish-client-instruction.py) — создаёт новую страницу из Python-кода (содержимое прописано в самом скрипте) +- [snippets/telegraph-md-to-page.py](../../snippets/telegraph-md-to-page.py) — **конвертер markdown → Telegraph Node**, редактирует `Nastrojka-VPN-04-24-2`. Поддерживает вложенные списки, inline code/links/bold/italic, защищает code-spans от italic-парсинга. Чтобы опубликовать новый md: поменять PATH/TITLE/источник файла в `main()`. + +**Созданные страницы:** +- https://telegra.ph/Nastrojka-VPN-04-24-2 — VPN + US Apple ID для Ярослава (без ключа — ключ отдаётся отдельным сообщением) + ## Netbird (netbird.io cloud) | Параметр | Значение | diff --git a/projects/dttb/proxmox-inventory.md b/projects/dttb/proxmox-inventory.md index ab53fea..4aed2a0 100644 --- a/projects/dttb/proxmox-inventory.md +++ b/projects/dttb/proxmox-inventory.md @@ -133,8 +133,9 @@ tags: [dttb, proxmox] |----------|----------| | Статус | 🟢 running | | IP | 10.0.0.244 (LAN) / 100.70.191.161 (NetBird) | -| NPM домен | remot.dttb.ru *(в NPM записан 10.0.0.43 — устарело, проверить)* | -| Назначение | RustDesk Server | +| NPM домен | remot.dttb.ru → 10.0.0.244:21114 (Proxy Host id 14) + streams 21115-21119 (id 38-43) | +| Назначение | RustDesk Server (`lejianwen-pro` hbbs/hbbr 1.1.14 + `rustdesk-api` 2.7, MUST_LOGIN=Y, нативно через systemd) | +| Справочник | [[rustdesk]] · миграция: [[../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration]] | ### LXC 132 — code-server | Параметр | Значение | diff --git a/projects/dttb/rustdesk.md b/projects/dttb/rustdesk.md new file mode 100644 index 0000000..0793f68 --- /dev/null +++ b/projects/dttb/rustdesk.md @@ -0,0 +1,154 @@ +--- +date: 2026-04-28 +type: project-reference +tags: [rustdesk, lxc116, lejianwen, dttb] +--- + +# RustDesk Server — справочник + +## Что это + +Self-hosted Remote Desktop сервер для парка ~30-50 машин (НИИКН + клиенты). +Стек **`lejianwen/rustdesk-server-pro` 1.1.14** (`hbbs`/`hbbr`) + **`lejianwen/rustdesk-api` 2.7** на нативной Debian-установке (без Docker), с `MUST_LOGIN=Y`. + +История миграции: [[../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration]] + +## Где живёт + +- **LXC 116** `rustdeskserver` на Proxmox 10.0.0.250 +- IP: `10.0.0.244` (LAN) / `100.70.191.161` (NetBird) +- Debian 12, 1 vCPU / 512M / 2G — community-script установка + +## Домен + +- Внешний: **`remot.dttb.ru`** (Cloudflare → роутер dttb.ru → NPM 10.0.0.195 → 10.0.0.244) +- Web-админка: https://remot.dttb.ru/_admin/ +- Swagger: https://remot.dttb.ru/swagger/index.html +- Login: см. [[credentials#RustDesk Server (LXC 116)]] + +## Сервисы (systemd) + +``` +rustdesk-hbbs.service — ID/Rendezvous server (hbbs --must-login Y -k _ -r remot.dttb.ru:21117) +rustdesk-hbbr.service — Relay server (hbbr -k _) +rustdesk-api.service — Web admin + REST API (на 21114) +``` + +Бинари: +- `/usr/bin/hbbs` — pro 1.1.14 (с патчем `--must-login Y`) +- `/usr/bin/hbbr` — pro 1.1.14 +- `/usr/bin/rustdesk-api` — 2.7 +- `/usr/bin/{hbbs,hbbr}.oss-1.1.14` — rollback-копии + +`apt-mark hold rustdesk-server-hbbs rustdesk-server-hbbr` — apt не перезапишет. + +Override-конфиги: +- `/etc/systemd/system/rustdesk-hbbs.service.d/override.conf` +- `/etc/systemd/system/rustdesk-hbbr.service.d/override.conf` + +## Порты + +| Порт | Протокол | Назначение | +|------|----------|------------| +| 21114 | TCP | rustdesk-api HTTP (только через NPM HTTPS!) | +| 21115 | TCP | hbbs NAT-test | +| 21116 | TCP+UDP | hbbs ID/rendezvous (UDP — основной) | +| 21117 | TCP | hbbr relay | +| 21118 | TCP | hbbs WebSocket (для All-In-HTTPS клиентов через `/ws/id`) | +| 21119 | TCP | hbbr WebSocket (через `/ws/relay`) | + +NPM Proxy Host id=14: `https://remot.dttb.ru → 10.0.0.244:21114` + custom nginx с `/ws/id` и `/ws/relay`. +NPM Streams: id 38-43 (21115/TCP, 21116/UDP, 21116/TCP, 21117/TCP, 21118/TCP, 21119/TCP) → 10.0.0.244. + +## Ключи + +- `/var/lib/rustdesk-server/id_ed25519` — приватный (88 байт) +- `/var/lib/rustdesk-server/id_ed25519.pub` — `R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=` + +**Не перегенерировать!** Иначе все ~30-50 клиентов перестанут подключаться. + +## БД + +- `/var/lib/rustdesk-server/db_v2.sqlite3` — БД hbbs (peers state) +- `/var/lib/rustdesk-api/data/rustdeskapi.db` — БД api (users, groups, address_books, audit_logs) + +Пока SQLite. План: MySQL когда дойдём до HA. + +## Конфиг api + +`/var/lib/rustdesk-api/conf/config.yaml` — основные параметры: +- `lang: ru` +- `app.register: false` (регистрация выключена — юзеров создаёт админ) +- `app.show-swagger: 1` +- `app.ban-threshold: 5` +- `app.captcha-threshold: 3` +- `rustdesk.id-server: remot.dttb.ru:21116` +- `rustdesk.relay-server: remot.dttb.ru:21117` +- `rustdesk.api-server: https://remot.dttb.ru` +- `rustdesk.key: ` +- `jwt.key: <см. credentials>` +- `ldap.enable: false` + +## Шаблон RustDesk2.toml для клиентов + +`/root/RustDesk2.toml` на LXC 116: + +```toml +rendezvous_server = "remot.dttb.ru:21116" +nat_type = 1 +serial = 1 + +[options] +custom-rendezvous-server = "remot.dttb.ru" +relay-server = "remot.dttb.ru" +api-server = "https://remot.dttb.ru" +key = "R0lA4r77hAGw6YRL1qG3JioVqQ0Q0fJfzkwlAGqR6jU=" +allow-websocket = "Y" +verification-method = "use-permanent-password" +approve-mode = "password" +``` + +## CLI-команды (на LXC 116) + +```bash +# Сменить пароль admin +cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-admin-pwd + +# Сменить пароль обычного юзера +cd /var/lib/rustdesk-api && /usr/bin/rustdesk-api reset-pwd + +# Список peers через sqlite +sqlite3 /var/lib/rustdesk-api/data/rustdeskapi.db \ + "select id, last_online_ip, datetime(last_online_time,'unixepoch') from peers order by last_online_time desc limit 10;" + +# Список юзеров +sqlite3 /var/lib/rustdesk-api/data/rustdeskapi.db \ + "select id, username, group_id, status, is_admin from users;" + +# Логи +tail -f /var/log/rustdesk-server/hbbs.log +tail -f /var/log/rustdesk-server/hbbr.log +tail -f /var/log/rustdesk-api/rustdesk-api.log +``` + +## Бэкап и rollback + +- `/root/rustdesk-backup-20260428-1134/` — бэкап от 2026-04-28 миграции (ключи, БД, config.yaml.orig) +- `/root/rustdesk-rollback.sh` — откат к OSS bin'ам за 30 сек + +## Известные нюансы + +- **MUST_LOGIN работает только в pro-бинаре hbbs.** OSS hbbs (как был до 2026-04-28) этот флаг игнорирует. См. [[../../decisions/2026-04-28-rustdesk-lejianwen-pro-migration]]. +- **Admin REST API через curl без web-сессии не пускает.** Юзеров/группы создавать через https://remot.dttb.ru/_admin/. +- **NPM streams API** — PUT не работает (валидатор `additional properties`). Только DELETE + POST. +- **community-script может пытаться обновить пакеты** — `apt-mark hold` защищает hbbs/hbbr, но если запустить полный re-run скрипта community-scripts, могут быть сюрпризы. Не запускать без необходимости. +- **`/proc/loadavg` в LXC = нагрузка хоста**, не контейнера ([[../../../knowledge-base/feedback_lxc_loadavg]] в memory). + +## TODO + +- Раскатать `RustDesk2.toml` на парк через GPO/скрипт +- Заполнить группы клиентских организаций +- Бэкап на ArtLeon через cron + rsync (NetBird) +- Через 2-4 недели — миграция в Docker `lejianwen/rustdesk-server-s6` (Вариант A3 из decision-файла) +- MCP-обёртка поверх Swagger API для управления из Claude Code +- HA-схема на втором экземпляре (НИИКН Proxmox) с общей MySQL