Deploy Bot a6492fc1b9 feat: add Docker-based RustDesk Server (hbbs/hbbr) for VPS
- Add docker-compose.vps.yml with hbbs + hbbr services
- Update rustdesk-dummy.service with corrected binary path (/usr/share/...)
- Update xorg-dummy.service without -nolisten local (fixes socket access)
- Update install.sh for dummy driver + EDID fallback approach
- Update README with dual setup (host + VPS) and server instructions
- VPS: RustDesk Server runs via Docker on ports 21115-21119
- Public key: 5PxKX27ZTJGlu9KjU7YByXQDIw6zS8pKlvqxXsZiw8M=
2026-05-15 20:09:30 +01:00

RDtop — RustDesk Headless Display Setup

Автоматический виртуальный дисплей для RustDesk без подключенного HDMI монитора. Работает на любой Linux машине (Intel iGPU, AMD, NVIDIA, CPU-only VPS).


Содержание

  1. Проблема
  2. Решение
  3. Файлы проекта
  4. Установка
  5. Как это работает
  6. Проверка
  7. Troubleshooting
  8. Откат

Проблема

Оборудование: Intel Alder Lake-N (i915), Ubuntu 24.04, X11 (GDM/GNOME).

Что происходит

  1. При подключенном HDMI — Xorg инициализирует HDMI-1 на отдельный CRTC.
  2. Когда кабель отключают — CRTC уничтожается.
  3. У Xorg не остается активного выхода. Может остаться черный экран или fallback 8×8.
  4. RustDesk все еще подключен, но захватывает Screen 0 — и видит либо черный экран, либо 8×8 пикселей.

Почему стандартные способы не помогли

Способ Результат
Option "VirtualHeads" "1" (intel driver) Работает только с кабелем на момент загрузки. Без HDMI — VIRTUAL1 не создается.
modesetting driver Создает VIRTUAL1 через randr, но после reboot пропадает.
NoOutputInitialSize Требует пересборки xorg или патчей.
Dummy plug (аппаратный) Работает, но нужно покупать.

Решение

Хост: Dummy driver + kernel EDID fallback

Работает без кабеля HDMI на момент загрузки — dummy driver не зависит от физических выходов.

+------------------------------------------------------------------------+
|   Xorg Dummy Driver (1920×1080)                                        |
|   +-------------------------+                                           |
|   |   DUMMY0 = primary      |   ← RustDesk --server захватывает       |
|   |   1920×1080 @ 60Hz     |                                           |
|   +-------------------------+                                           |
|                                                                         |
|   При подключении HDMI кабеля:                                          |
|   скрипт hdmi-fallback.sh клонирует HDMI1 на DUMMY0                     |
|   При отключении: HDMI1 off, DUMMY0 остается primary                    |
+------------------------------------------------------------------------+

Kernel EDID fallback (дополнительно)

Параметры ядра:

video=HDMI-A-1:1920x1080@60 drm.edid_firmware=HDMI-A-1:edid/samsung.bin

Это заставляет ядро i915 инициализировать HDMI-A-1 с сохраненным EDID даже без кабеля. Если dummy driver не сработает (редкий случай), ядро все равно создаст виртуальный framebuffer.

VPS (CPU-only): Dummy driver + Xorg + RustDesk

Тот же dummy driver, но без GPU. Работает на любом VPS.

+------------------------------------------------------------------------+
|   Xorg Dummy Driver (1920×1080)                                         |
|   +-------------------------+                                           |
|   |   DUMMY0 = primary      |   ← RustDesk --server захватывает       |
|   |   1920×1080 @ 60Hz     |                                           |
|   +-------------------------+                                           |
|   Нет GPU, нет DRM — работает на любом VPS                             |
+------------------------------------------------------------------------+

Файлы проекта

Файл репозитория Назначение Системный путь
bin/hdmi-fallback.sh Мониторинг HDMI-A-1 и авто-fallback на DUMMY0/VIRTUAL1 ~/.local/bin/hdmi-fallback.sh
bin/vps-start-xorg.sh Стартер Xorg с dummy driver на VPS /usr/local/bin/start-xorg-dummy.sh
config/x11-host/20-dummy-headless.conf Dummy driver headless config /etc/X11/xorg.conf.d/20-dummy-headless.conf
config/x11-host/20-intel-virtual.conf.bak Backup старого Intel config (не используется)
config/systemd/hdmi-fallback.service systemd user unit (host) ~/.config/systemd/user/hdmi-fallback.service
config/vps/xorg-dummy.service systemd system unit (VPS Xorg) /etc/systemd/system/xorg-dummy.service
config/vps/rustdesk-dummy.service systemd system unit (VPS RustDesk) /etc/systemd/system/rustdesk-dummy.service
install.sh Установщик для хоста (запускается один раз)

Установка

Хост (Desktop с GPU)

bash -c "$(curl -fsSL https://git.softuniq.eu/NW/RDtop/raw/branch/main/install.sh)"

После установки перезагрузить компьютер:

sudo reboot

Вручную:

# 1. Клонируем
git clone https://git.softuniq.eu/NW/RDtop.git ~/RDtop && cd ~/RDtop

# 2. Dummy driver config (главный способ)
sudo cp config/x11-host/20-dummy-headless.conf /etc/X11/xorg.conf.d/

# 3. Удалить старые конфиги если были
sudo rm -f /etc/X11/xorg.conf.d/20-intel-virtual.conf
sudo rm -f /etc/X11/xorg.conf.d/90-fallback.conf

# 4. Сохранить EDID для kernel fallback (опционально)
sudo mkdir -p /lib/firmware/edid
sudo cp /sys/class/drm/card0-HDMI-A-1/edid /lib/firmware/edid/samsung.bin

# 5. Обновить GRUB для kernel EDID fallback
sudo sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=".*"|GRUB_CMDLINE_LINUX_DEFAULT="quiet splash video=HDMI-A-1:1920x1080@60 drm.edid_firmware=HDMI-A-1:edid/samsung.bin"|' /etc/default/grub
sudo update-grub

# 6. Скрипт мониторинга
chmod +x bin/hdmi-fallback.sh
cp bin/hdmi-fallback.sh ~/.local/bin/

# 7. systemd unit
mkdir -p ~/.config/systemd/user
cp config/systemd/hdmi-fallback.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now hdmi-fallback.service

# 8. Перезагрузка
sudo reboot

Вариант Б: CPU-only VPS

# 1. Установить Xorg + dummy
apt-get update
apt-get install -y xserver-xorg xserver-xorg-video-dummy rustdesk

# 2. Копировать конфиги
git clone https://git.softuniq.eu/NW/RDtop.git /tmp/rdtop
cd /tmp/rdtop
sudo cp config/vps/20-dummy-headless.conf /etc/X11/xorg.conf.d/
sudo cp config/vps/xorg-dummy.service /etc/systemd/system/
sudo cp config/vps/rustdesk-dummy.service /etc/systemd/system/
sudo cp bin/vps-start-xorg.sh /usr/local/bin/start-xorg-dummy.sh
chmod +x /usr/local/bin/start-xorg-dummy.sh

# 3. Остановить конфликтующий gdm
systemctl stop gdm.service 2>/dev/null || true
systemctl disable gdm.service 2>/dev/null || true

# 4. Запустить
systemctl daemon-reload
systemctl enable --now xorg-dummy.service
systemctl enable --now rustdesk-dummy.service

# 5. Проверить
export DISPLAY=:0
xrandr --listmonitors
# Должно показать: DUMMY0 primary 1920x1080

Как это работает

Хост (Intel iGPU)

  1. Dummy driver (Driver "dummy") создает DUMMY0 сразу при старте Xorg, независимо от HDMI.
  2. Kernel EDID fallback (drm.edid_firmware) — если dummy каким-то образом не сработает, ядро i915 инициализирует HDMI-A-1 с сохраненным EDID.
  3. Скрипт hdmi-fallback.sh при старте:
    • Всегда активирует DUMMY0 как primary
    • Если HDMI connected — делает HDMI1 clone (--same-as)
    • Если HDMI disconnected — выключает HDMI1, DUMMY0 остается primary
  4. RustDesk захватывает DUMMY0 (primary).

VPS (CPU-only)

  1. Dummy driver (Driver "dummy") не требует GPU, работает на чистом CPU.
  2. Xorg запускается без DRM, создает DUMMY0 1920×1080.
  3. RustDesk --server захватывает DUMMY0 через X11 screen capture.
  4. Нет GUI оболочки по умолчанию — если нужен рабочий стол, установить xfce4 + tightvncserver.

Проверка

Хост (после reboot без HDMI)

# Должно показать DUMMY0 как primary
xrandr --listmonitors
# Ожидаемый вывод:
#   0: +*DUMMY0 1920/508x1080/286+0+0  DUMMY0   [PRIMARY]

# Если HDMI подключен:
#   1: +HDMI-1  1920/508x1080/286+0+0  HDMI-1   [CLONE]

Сервис

systemctl --user status hdmi-fallback.service

Логи

cat ~/.local/logs/drm-hotplug.log

VPS

export DISPLAY=:0
xrandr --listmonitors
# Должно быть:
#   0: +*DUMMY0 1920x... DUMMY0   [PRIMARY]

# RustDesk
ps aux | grep rustdesk
# /usr/lib/rustdesk/rustdesk --server должен быть запущен

Troubleshooting

DUMMY0 не появляется после reboot

# Проверить dummy driver:
grep "Loading.*dummy" /var/log/Xorg.0.log
# Должно быть: (II) Loading /usr/lib/xorg/modules/drivers/dummy_drv.so

# Проверить конфиг:
ls /etc/X11/xorg.conf.d/20-dummy-headless.conf
# Должен существовать

# Если intel driver загружается вместо dummy:
# Убедиться что нет других конфликтующих xorg.conf:
ls /etc/X11/xorg.conf 2>/dev/null || echo "OK: no xorg.conf"

RustDesk черный экран

# Проверить primary:
xrandr --verbose | grep primary
# Должно быть: DUMMY0 connected primary

# Если primary не DUMMY0:
xrandr --output DUMMY0 --mode "1920x1080" --primary
xrandr --output HDMI-1 --auto --same-as DUMMY0

VPS: RustDesk не видит DUMMY0

# Проверить что Xorg запущен:
ls /tmp/.X11-unix/X0
# Должен быть сокет

# Если нет — запустить вручную:
/usr/local/bin/start-xorg-dummy.sh

Откат

# Хост
sudo rm -f /etc/X11/xorg.conf.d/20-dummy-headless.conf
sudo rm -f /etc/X11/xorg.conf.d/20-intel-virtual.conf
sudo rm -f /etc/X11/xorg.conf.d/90-fallback.conf
systemctl --user disable --now hdmi-fallback.service
rm -f ~/.local/bin/hdmi-fallback.sh

# Вернуть стандартный GRUB:
sudo sed -i 's|GRUB_CMDLINE_LINUX_DEFAULT=".*"|GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"|' /etc/default/grub
sudo update-grub

# VPS
systemctl disable --now xorg-dummy.service
systemctl disable --now rustdesk-dummy.service
sudo rm -f /etc/systemd/system/xorg-dummy.service
sudo rm -f /etc/systemd/system/rustdesk-dummy.service

Технические детали

Почему dummy driver, а не intel с VirtualHeads?

intel driver + VirtualHeads=1 работает только если HDMI подключен при загрузке. Без кабеля — ядро не создает connector/CRTC для HDMI-A-1, и VirtualHeads не помогает. Dummy driver не зависит от физических выходов.

Почему kernel EDID fallback?

Параметры video=HDMI-A-1:1920x1080@60 и drm.edid_firmware=HDMI-A-1:edid/samsung.bin заставляют ядро i915 инициализировать connector с фиктивным EDID. Это "страховка": если dummy driver по какой-то причине не загрузится (например, обновление Xorg удалит его), ядро все равно создаст выход.

Почему клон, а не extended desktop?

--same-as клонирует framebuffer. При disconnect HDMI clone просто перестает рендериться, но primary (DUMMY0) не затрагивается — Xorg не теряет framebuffer.

Dummy driver на VPS

Не требует GPU, не использует DRM. Работает на любом Linux с xorg-server. RustDesk использует software capture через X11 API.


Авторы

  • Deploy via AI Agent (Kilo Code Orchestrator)
  • Target hardware: Intel Alder Lake-N (i915), Ubuntu 24.04
  • VPS: CPU-only, Ubuntu 24.04, Hetzner/DigitalOcean/Linode

Ссылки

  • Репозиторий: https://git.softuniq.eu/NW/RDtop
  • Установщик: bash -c "$(curl -fsSL https://git.softuniq.eu/NW/RDtop/raw/branch/main/install.sh)"
Description
RustDesk headless setup for Intel iGPU with HDMI fallback
Readme 105 KiB
Languages
Shell 100%