Files
knowledge-base/notes/claude/2026-04-28-232613-промт-для-claude-code-развёртывание-rustdesk-api-s.md

256 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2026-04-28
type: claude-session
session_id: 3ccbd317-34fd-4954-ade5-01248b0bfd07
started: 2026-04-28T08:27:41.560Z
ended: 2026-04-28T20:26:13.193Z
messages: 21
tools: [Bash, Edit, Read, TodoWrite, ToolSearch, Write, mcp__Claude_in_Chrome__list_connected_browsers, mcp__Claude_in_Chrome__switch_browser]
tags: [claude, session]
---
# # Промт для Claude Code: развёртывание RustDesk API Server (lejianwen)
## Запрос
# Промт для Claude Code: развёртывание RustDesk API Server (lejianwen)
## Контекст
Я системный администратор. У меня уже работает Proxmox VE на домене [dttb.ru](http://dttb.ru) с следующей инфраструктурой:
- **LXC-контейнер с RustDesk OSS Server** (hbbs + hbbr) — текущая рабочая инсталляция, `id_ed25519` и `id_[ed25519.pub](http://ed25519.pub)` в `/data/rustdesk/server/` (примерно, путь уточни через ls)
- **LXC с Nginx Proxy Manager** на [dttb.ru](http://dttb.ru) — управляет всеми reverse-proxy и Let's Encrypt сертификатами
- **Домен**: `[remot.dttb.ru](http://remot.dttb.ru)` уже настроен и работает (проброс TCP/UDP стримами на hbbs/hbbr)
- **NetBird VPN-mesh** между площадками для админ-доступа
- **DNS** управляется через Cloudflare
- Клиенты RustDesk развёрнуты на ~30-50 машинах (НИИКН + несколько клиентских организаций)
## Цель
Мигрировать с базового RustDesk OSS Server на **stack от lejianwen** (https://github.com/lejianwen/rustdesk-api + парный rustdesk-server-s6) для получения:
1. **Жёсткой изоляции клиентов** через `MUST_LOGIN=Y` — техник Клиента-А не должен иметь возможности подключиться к машинам Клиента-Б даже зная ID и пароль
2. **Адресных книг и групп** — каждый техник видит только свои устройства
3. **Аудит-логов** (login, connection, file_transfer)
4. **All-In-HTTPS+WebSocket** архитектуры — весь трафик через 443/HTTPS, чтобы работать из-за корпоративных фаерволов клиентов
5. **REST API + Swagger** для автоматизации через Claude Code и потенциальную MCP-интеграцию
**Критическое требование**: миграция должна сохранить существующий ключ сервера (`id_ed25519` / `id_[ed25519.pub](http://ed25519.pub)`), чтобы клиенты на местах продолжили работать без перенастройки. Это нужно проверить отдельно — НИ В КОЕМ СЛУЧАЕ не генерировать новый ключ, не удалять старый.
## Задачи
### Фаза 1: Аудит и подготовка
1. Подключись к Proxmox-хосту по SSH (узнай адрес у меня если нет в `~/.ssh/config`).
2. Найди LXC-контейнер с текущим RustDesk Server. Подскажи команду `pct list` и `pct config <id>` чтобы я понял какой именно.
3. **Проверь и зафиксируй**:
- Точный путь к `/data/rustdesk/server/` (где лежат `id_ed25519` и `id_[ed25519.pub](http://ed25519.pub)`)
- Содержимое текущего `compose.yml` или `docker run` параметров hbbs/hbbr
- Какие порты сейчас слушает hbbs (`ss -tulpn | grep -E '2111[4-9]'`)
- Версию текущего OSS-сервера
- Размер БД (если есть `db_v2.sqlite3`)
4. **Сделай полный бэкап** перед любыми изменениями:
- `tar` всей директории `/data/rustdesk/`
- Сохрани бэкап в `/root/rustdesk-backup-YYYYMMDD-HHMM.tar.gz`
- Дополнительно скопируй `id_ed25519*` отдельно в `/root/rustdesk-keys-backup/`
5. Покажи мне план действий и ЖДИ моего подтверждения перед фазой 2.
### Фаза 2: Развёртывание lejianwen stack
6. Останови текущий контейнер (`docker compose down` в текущей директории), но **не удаляй** ни том с ключами, ни саму директорию.
7. Создай новую директорию для нового стека: `/opt/rustdesk-lejianwen/` с подкаталогами `data/api/` и оставь существующий `/data/rustdesk/server/` нетронутым (новый стек будет смонтирован на него).
8. Сгенерируй случайный JWT-ключ длиной 32+ символов: `openssl rand -base64 48`. Сохрани его в файл `/opt/rustdesk-lejianwen/.env` с переменной `JWT_KEY=...`. Покажи мне, я сохраню его в свою password-store.
9. Создай `/opt/rustdesk-lejianwen/compose.yml` со следующим содержимым (проверь актуальный формат env-переменных в README — он мог обновиться):
```yaml
networks:
rustdesk-net:
external: false
services:
rustdesk:
image: lejianwen/rustdesk-server-s6:latest
container_name: rustdesk
environment:
- RELAY=remot.dttb.ru:21117
- ENCRYPTED_ONLY=1
- MUST_LOGIN=Y
- TZ=Europe/Moscow
- RUSTDESK_API_LANG=ru
- RUSTDESK_API_RUSTDESK_ID_SERVER=remot.dttb.ru:21116
- RUSTDESK_API_RUSTDESK_RELAY_SERVER=remot.dttb.ru:21117
- RUSTDESK_API_RUSTDESK_API_SERVER=https://remot.dttb.ru
- RUSTDESK_API_RUSTDESK_KEY_FILE=/data/id_[ed25519.pub](http://ed25519.pub)
- RUSTDESK_API_JWT_KEY=${JWT_KEY}
- RUSTDESK_API_APP_REGISTER=false
- RUSTDESK_API_APP_DISABLE_PWD_LOGIN=false
- RUSTDESK_API_APP_CAPTCHA_THRESHOLD=3
- RUSTDESK_API_APP_BAN_THRESHOLD=5
- RUSTDESK_API_ADMIN_TITLE=Remote Support Portal
volumes:
- /data/rustdesk/server:/data
- /opt/rustdesk-lejianwen/data/api:/app/data
networks:
- rustdesk-net
ports:
- "21114:21114"
- "21115:21115"
- "21116:21116"
- "21116:21116/udp"
- "21117:21117"
- "21118:21118"
- "21119:21119"
restart: unless-stopped
```
10. **Перед запуском убедись**:
- Файлы `/data/rustdesk/server/id_ed25519` и `id_[ed25519.pub](http://ed25519.pub)` существуют и не пустые
- Контейнер не будет генерировать новый ключ (если в логах после старта появится "generating new key" — это критическая ошибка, останавливай немедленно)
11. Запусти `docker compose up -d`, отслеживай логи: `docker compose logs -f rustdesk`. В логах должен появиться сгенерированный пароль `admin` — поймай его и сохрани в `/root/rustdesk-admin-initial-password.txt` с правами 600.
12. **Проверь работоспособность**:
- `curl -I http://localhost:21114/_admin/` — должен вернуть 200 или 301
- `curl http://localhost:21114/api/heartbeat` (если такой endpoint есть, иначе пропусти)
- `ss -tulpn | grep -E '2111[4-9]'` — все порты должны слушаться
- **Сравни `/data/rustdesk/server/id_[ed25519.pub](http://ed25519.pub)` с бэкапом** — должен быть идентичен. Если отличается — стоп, ключ перегенерировался, нужен rollback.
### Фаза 3: Настройка Nginx Proxy Manager
13. Подключись к LXC с NPM (или используй его API). Найди существующий Proxy Host для `[remot.dttb.ru](http://remot.dttb.ru)` (или Stream-секции).
14. **Текущая конфигурация со Stream'ами для портов 21115-21119 должна остаться** — это для совместимости со старыми клиентами без WebSocket.
15. **Обнови** Proxy Host для `[remot.dttb.ru](http://remot.dttb.ru)`:
- Forward Hostname: IP нового LXC с lejianwen-stack
- Forward Port: `21114`
- WebSocket Support: включить
- Block Common Exploits: включить
- SSL: уже должен быть Let's Encrypt, проверь что Force SSL и HTTP/2 включены
16. В **Advanced → Custom Nginx Configuration** добавь:
```nginx
location /ws/id {
proxy_pass http://IP_LXC:21118;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
location /ws/relay {
proxy_pass http://IP_LXC:21119;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}
```
(подставь реальный IP LXC вместо IP_LXC)
17. Проверь `nginx -t` внутри контейнера NPM, перезагрузи если ОК.
18. С внешней машины (попроси меня проверить или используй curl с другого хоста через NetBird):
- `curl -I https://remot.dttb.ru/_admin/` — должно отвечать 200/301
- `curl -I https://remot.dttb.ru/swagger/index.html` — Swagger доступен
### Фаза 4: Первичная настройка через web-консоль
19. Открой `https://remot.dttb.ru/_admin/`, залогинься admin / `<пароль из /root/rustdesk-admin-initial-password.txt>`.
20. Помоги мне сменить пароль admin'а (через `docker exec rustdesk ./apimain reset-admin-pwd <новый_пароль>` или через UI).
21. Создай начальную структуру (если возможно через API/CLI — сделай скриптом):
**Группы (shared):**
- `НИИКН-парк`
- `Клиент-template` (как образец, потом дублировать)
**Тестовые пользователи:**
- `niikn-admin` (полные права на группу НИИКН)
- `niikn-tech1` (только подключение)
- `test-client` (для проверки изоляции)
22. Создай шаблон `RustDesk2.toml` для клиентов:
```toml
rendezvous_server = 'remot.dttb.ru:21116'
nat_type = 1
serial = 1
[options]
custom-rendezvous-server = '[remot.dttb.ru](http://remot.dttb.ru)'
relay-server = '[remot.dttb.ru](http://remot.dttb.ru)'
api-server = 'https://remot.dttb.ru'
key = '<СЮДАОДСТАВЬ_СОДЕРЖИМОЕ_id_[ed25519.pub](http://ed25519.pub)>'
allow-websocket = 'Y'
verification-method = 'use-permanent-password'
approve-mode = 'password'
```
Прочитай актуальный публичный ключ из `/data/rustdesk/server/id_[ed25519.pub](http://ed25519.pub)`, подставь в шаблон. Сохрани готовый файл в `/root/RustDesk2.toml.template`.
### Фаза 5: Тестирование и rollback-план
23. Подними тестовый клиент (можешь использовать docker `rustdesk/rustdesk` или попросить меня запустить на тестовой машине). Проверь:
- Подключение к серверу проходит
- Без логина соединение **не устанавливается** (это ключевая проверка MUST_LOGIN)
- С логином `niikn-tech1` доступны только машины из его адресной книги
- С логином `test-client` машины НИИКН не видны и подключение к ним по ID отклоняется
24. **Подготовь rollback-скрипт** на случай провала: `/root/[rustdesk-rollback.sh](http://rustdesk-rollback.sh)`, который:
- Останавливает новый стек: `cd /opt/rustdesk-lejianwen && docker compose down`
- Восстанавливает из бэкапа `/root/rustdesk-backup-*.tar.gz`
- Поднимает старый OSS: возвращается в его директорию и `docker compose up -d`
- В NPM возвращает старую конфигурацию (тут лучше через бэкап настроек NPM `/data/database.sqlite` если NPM запущен в Docker)
25. Сделай финальный отчёт в `/root/[rustdesk-migration-report.md](http://rustdesk-migration-report.md)` со всем что сделано: пути, IP, пароли (хеши), команды для дальнейшего обслуживания, известные проблемы.
## Что важно соблюдать
- **Действуй пошагово**, после каждой фазы дожидайся моего подтверждения. Не уходи в Фазу 3 без ОК на Фазу 2.
- **Не удаляй ничего** до успешного теста новой системы. Старый OSS-стек должен оставаться на диске минимум 7 дней.
- **При любой ошибке с ключом сервера** (`id_[ed25519.pub](http://ed25519.pub)` изменился, hbbs его перегенерировал, не подхватил из volume) — немедленный stop и rollback. Это самый критичный риск всей миграции.
- Если что-то непонятно в моей инфраструктуре — спрашивай, не предполагай. Например, точный IP контейнеров, реальные пути в моём compose, версии Docker.
- Команды, требующие sudo, обязательно объясни перед запуском.
- **Не выкладывай в логи и не сохраняй в git** значения `JWT_KEY`, паролей и публичный домен в открытом виде в файлах, которые могут быть закоммичены.
- Всё, что меняется в системе, должно быть idempotent или иметь rollback. Никаких `rm -rf` без бэкапа на соседнем диске или площадке.
## Что НЕ делать
- НЕ переходить сразу на MySQL-схему с репликацией — это будет отдельная задача после стабилизации базового стека на SQLite
- НЕ настраивать LDAP/OIDC до того, как обычный логин/пароль протестирован и работает
- НЕ обновлять клиенты RustDesk на местах (это я делаю отдельно через свои существующие GPO/скрипты)
- НЕ трогать существующие VPN-конфигурации (NetBird, AmneziaVPN и прочее)
- НЕ менять DNS-записи в Cloudflare без моего явного согласия
- НЕ публиковать `_admin` интерфейс без аутентификации, не открывать его из публичного интернета без проверки fail2ban / bantreshold
## После завершения
Когда всё работает и протестировано, отдельной задачей мы:
1. Раскатаем новый `RustDesk2.toml` на парк через GPO/скрипт
2. Заведём полную структуру клиентских групп
3. Настроим бэкапы БД API + ключей на ArtLeon (cron + rsync через NetBird)
4. Поднимем второй экземпляр на НИИКН Proxmox с общей MySQL для отказоустойчивости
5. Напишем MCP-обёртку поверх Swagger API для работы из Claude Code
Начинай с Фазы 1, фиксируй всё в `/root/[rustdesk-migration-report.md](http://rustdesk-migration-report.md)` по ходу.
## Итог (последний ответ Claude, до 500 симв.)
Закоммичено в kb (`441491e`).
**Итого:** web-client инфраструктура готова и задокументирована, не дёргаем. Сейчас ты в админке — заведи юзеров/группы, и параллельно настрой Mac как desktop-клиент.
Когда Mac будет настроен и появится online + залогинен, можешь с **телефона** (Safari/Chrome на iPhone) открыть `https://remot.dttb.ru/webclient/` → ввести ID Mac'а → должно подключиться. Это и будет реальный тест web-client.
Жду пока настроишь Mac (или скриншот если что-то не складывается с Setting
---
*Автосохранено из session [`3ccbd317`](file:///Users/ai/.claude/projects/-Users-ai-knowledge-base/3ccbd317-34fd-4954-ade5-01248b0bfd07.jsonl) — 21 сообщ., тулы: Bash, Edit, Read, TodoWrite, ToolSearch, Write, mcp__Claude_in_Chrome__list_connected_browsers, mcp__Claude_in_Chrome__switch_browser*