Files
mypointvpn/docs/apps/rustdesk
protokeyandClaude Opus 5.5 fd4b05097a feat: публикация портов не-HTTP сервисами, проверка портов до деплоя, пример RustDesk
serverus: app_ports.py проверяет опубликованные порты приложения до
изменений - по docker compose config (переменные из .env подставлены)
против слушающих сокетов сервера и портов контейнеров других приложений.
Занятый порт больше не роняет up после замены файлов. Конвенция: только
мост; не-HTTP сервисы публикуют свои порты, 80 и 443 - у caddy;
bind-mount только своих файлов из data/<сервис>/ с :ro. Описано, что
упавший up после синхронизации файлы не откатывает.

App: uploads.check предупреждает о 80/443 вместо любых портов и о
bind-mount из папки приложения вне data/ или без :ro.

docs/apps/rustdesk: приложение (hbbs, hbbr, ключ генерируем сами),
genkey.py и check.py - проверка сервера по протоколу RustDesk снаружи.
Проверено на стенде Debian 13: деплой, повторный деплой, отказ второго
приложения на тех же портах до изменений, перезагрузка сервера.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 10:31:38 +04:00
..

RustDesk на docker-сервере

Свой сервер для RustDesk - удаленного доступа к компьютерам. Пример приложения по конвенции serverus.DockerHost (см. src/serverus/README.md): не-HTTP сервис, который публикует свои порты через мост.

Что внутри

Сервер RustDesk - две программы из образа rustdesk/rustdesk-server:

  • hbbs - сервер ID. Клиенты регистрируются в нем под своим ID; при подключении hbbs сводит двух клиентов и помогает им соединиться напрямую (пробивает NAT). Трафик сеанса через него не идет. Порты: 21116/tcp+udp, 21115/tcp (NAT-тест).
  • hbbr - relay. Если напрямую соединиться не вышло, весь трафик сеанса идет через него. Порт 21117/tcp.

hbbs сообщает клиентам адрес relay (-r ${RELAY_HOST}:21117). Оба запущены с -k _: работают только клиенты с нашим ключом. Websocket-порты (21118, 21119) не публикуются: они нужны только веб-клиенту.

Ключ генерируем мы и кладем в data/<сервис>/ (bind-mount :ro): он хранится в версии приложения и переживает переустановку ОС. Сгенерированный hbbs ключ жил бы в volume и пропал бы вместе с ним, а клиентов пришлось бы перенастраивать. База hbbs (db_v2.sqlite3) - в named volume.

Файлы

app/docker-compose.yaml   приложение
app/.env                  RELAY_HOST, из env_example
app/data/hbbs|hbbr/       ключ, из genkey.py
genkey.py                 ключ в формате hbbs/hbbr
check.py                  проверка сервера по протоколу RustDesk

app/.env и app/data/ в git не попадают.

Развернуть

cd docs/apps/rustdesk
cp env_example app/.env                      # RELAY_HOST - ip или домен сервера
../../../.venv/bin/python genkey.py          # печатает публичный ключ
make -C ../../.. serverus_app ip=<ip> action=deploy name=rustdesk dir=docs/apps/rustdesk/app

Через бота - архив содержимого app/ (вместе с .env и data/).

Проверить

python3 check.py <ip> "$(cat app/data/hbbs/id_ed25519.pub)"

Статус running и открытый порт ничего не доказывают: docker-proxy принимает tcp, даже когда контейнер лежит. check.py говорит с сервером по его протоколу снаружи, как клиент:

  1. UDP 21116: регистрация клиента - ответ RegisterPeerResponse: udp доходит до hbbs и обратно.
  2. TCP 21115: NAT-тест - hbbs возвращает порт, с которого мы пришли. Совпадает с нашим - hbbs видит настоящий адрес клиента, прямые соединения возможны.
  3. TCP 21116: запрос соединения с несуществующим ID - с нашим ключом ID_NOT_EXIST, с чужим LICENSE_MISMATCH: сервер работает с нашим ключом.
  4. TCP 21117: два соединения с одним uuid - hbbr сводит их, байты идут в обе стороны. С чужим ключом соединение закрывается.

Выход 0 - все прошло. В логах hbbs (make serverus_app ... action=logs name=rustdesk) должно быть Private key comes from id_ed25519 и Key: с нашим публичным ключом.

Проверено на стенде (Debian 13): деплой, повторный деплой без изменений, отказ второго приложения на тех же портах до изменений, перезагрузка сервера.

Клиент

Настройки - Сеть - ID-сервер: адрес сервера, Key: публичный ключ. Relay клиент получит от hbbs.