Привет Хабр! С вами снова ServerFlow, и сегодня мы хотим поговорить об удалённом доступе к графическим приложениям на Linux-серверах. Тема эта стала особенно актуальной в последнее время – всё больше задач требует работы с GPU на удалённых машинах. Будь то рендеринг в Blender на мощном сервере, работа с нейросетями или даже облачный гейминг.
X11 Forwarding: начинаем с простого
В нашей практике мы часто сталкиваемся с ситуациями, когда клиентам нужен доступ к графическому интерфейсу на сервере. Кому-то нужна GPU-ферма для рендеринга 3D графики, другим важно тестировать свои приложения в изолированной среде. А некоторые просто хотят организовать себе удалённое рабочее место с графическим ускорением. Сегодня разберём три популярных способа организации такого доступа – от простого к сложному.
Самый простой способ запустить графическое приложение с сервера – это X11 forwarding через SSH. Для этого даже не нужно ничего дополнительно устанавливать на сервер, достаточно базового пакета openssh.
Подключаемся к серверу командой:
ssh -X -p 47645 serverflow@IP_SSH_Сервера
Флаг -X включает проброс X11. Теперь можно запустить, например, Firefox прямо из консоли:
firefox &
На первый взгляд всё работает, но... При запуске браузера сразу становятся заметны подтормаживания интерфейса. Не говоря о том что интерфейс и пользовательский ввод отображаются на экране с очень заметной задержкой измеряемой даже не секундами, а порой минутами. С чем это связано? X11 forwarding работает напрямую с примитивами отрисовки, передавая по сети каждое действие с окном, почти никак не оптимизируя и не сжимая передаваемые данные, которых при передаче видео весьма не мало. На медленном соединении это создаёт заметные задержки.
Даже простая прокрутка веб-страницы генерирует тысячи X11-команд, которые должны быть переданы по сети. А теперь представьте, что происходит при воспроизведении видео или работе с 3D-графикой. Протокол просто не был рассчитан на такие сценарии использования.
Впрочем, винить за это мы X11 не будем, так как создавался он ещё в 1980х, для куда более простых графических интерфейсов, в куда меньших разрешениях и предназначался в основном для академической и корпоративной работы с мэинфреймами.
RDP в Docker: серьёзный подход
Перейдём к более современному решению – RDP-серверу в контейнере Docker с поддержкой GPU. В отличие от X11, протокол RDP изначально проектировался для работы с удалённым рабочим столом через сеть. Он использует умные алгоритмы сжатия, кэширование элементов интерфейса и различные оптимизации специально для графики.
Например, при прокрутке веб-страницы RDP не передаёт каждый кадр целиком. Вместо этого он может передать команду "возьми область экрана X и сдвинь её на Y пикселей вниз", а затем досылает только изменившуюся часть. При воспроизведении видео включаются специальные алгоритмы сжатия, похожие на те, что используются в современных видеокодеках.
Но прежде чем мы запустим наш RDP-сервер, нужно правильно настроить поддержку GPU в Docker. Начнём с установки драйверов и тулкита:
sudo pacman -S nvidia nvidia-container-toolkit
После установки настраиваем Docker для работы с GPU:
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Nvidia Container Toolkit добавляет специальный рантайм для Docker, который умеет правильно пробрасывать драйверы и библиотеки CUDA в контейнер. Без этого слоя графическое ускорение работать не будет, так как контейнер по умолчанию изолирован от железа.
Теперь самое интересное – запуск контейнера с RDP-сервером. Мы используем образ от LinuxServer.io с предустановленным XFCE. Создаём директорию для настроек и запускаем:
mkdir -p ~/rdesktop-data
docker run -d \
--name=rdesktop-arch-xfce \
--gpus "device=0" \
--runtime=nvidia \
--security-opt seccomp=unconfined \
-e PUID=1000 \
-e PGID=1000 \
-e TZ=Europe/Moscow \
-p 3389:3389 \
-v ~/rdesktop-data:/config \
--device /dev/dri:/dev/dri \
--shm-size="1gb" \
--restart unless-stopped \
lscr.io/linuxserver/rdesktop:arch-xfce
Разберем каждый параметр, потому что от их правильной настройки зависит стабильность работы нашего удаленного рабочего стола:
Флаг -d запускает контейнер в фоновом режиме. Это значит, что даже если мы закроем терминал, контейнер продолжит работать. Удобно для долгоживущих сервисов вроде нашего RDP-сервера.
--name=rdesktop-arch-xfce даёт контейнеру понятное имя. Потом будет проще найти его в списке контейнеров или перезапустить при необходимости.
Следующие два параметра отвечают за работу с GPU:
--gpus "device=0" указывает какую именно видеокарту использовать, если их несколько
--runtime=nvidia включает специальный режим работы Docker для поддержки GPU
--security-opt seccomp=unconfined отключает некоторые ограничения безопасности. Обычно Docker сильно ограничивает что может делать приложение в контейнере, но для графического интерфейса и работы с GPU нам нужно больше свободы. Да, это немного снижает безопасность, но без этого параметра наш рабочий стол просто не запустится.
Далее идут переменные окружения:
PUID=1000 и PGID=1000 задают ID пользователя и группы внутри контейнера. Важно чтобы они совпадали с вашим пользователем на основной системе, иначе будут проблемы с правами доступа к файлам
TZ=Europe/Moscow устанавливает часовой пояс. Не забудьте поменять на свой, если живёте в другом регионе
-p 3389:3389 пробрасывает порт для RDP. Первое число – порт на вашей машине, второе – внутри контейнера. Можно изменить первое число если порт 3389 уже занят.
-v ~/rdesktop-data:/config монтирует директорию с настройками. Все изменения в рабочем столе будут сохраняться на вашем диске и переживут перезапуск контейнера. Очень удобно для бэкапов.
--device /dev/dri:/dev/dri даёт контейнеру прямой доступ к графическому оборудованию для аппаратного ускорения. Без этого параметра графика будет работать только через программный рендеринг.
--shm-size="1gb" увеличивает размер разделяемой памяти. По умолчанию он всего 64 мегабайта, чего явно мало для современных браузеров и других приложений. Гигабайт обычно хватает с запасом.
--restart unless-stopped говорит Docker'у перезапускать контейнер если он вдруг упадёт или сервер перезагрузится. Единственное исключение – если вы сами остановили контейнер командой stop.
Наконец, lscr.io/linuxserver/rdesktop:arch-xfce указывает какой образ использовать. Мы берём готовый образ от команды LinuxServer.io, который построен на базе Arch Linux и использует лёгкий рабочий стол XFCE.
Клиент для RDP – Remmina
После запуска контейнера нам понадобится RDP-клиент для подключения. В Linux одним из лучших вариантов является Remmina – он поддерживает множество протоколов, включая RDP, и умеет работать через SSH-туннель.
Сначала создаем туннель до нашего сервера:
ssh -L 3389:127.0.0.1:3389 -p 47645 serverflow@IP_SSH_Сервера
Запускаем Remmina и создаём новое подключение. В появившемся окне настройки выставляем следующие параметры:
На вкладке "Basic":
Name: любое удобное название
Protocol: RDP
Server: localhost:3389
Username: abc
-
Password: abc (это стандартные данные для образа, рекомендуем сменить после первого входа)
Переходим на вкладку "SSH Tunnel" и включаем туннелирование:
Enable SSH tunnel: включаем
Custom: выбираем этот вариант
SSH Server: вводим наш адрес сервера – IP_SSH_Сервера:47645
Username: serverflow
-
Authentication: выбираем Password или SSH key, если используете ключи
После сохранения профиля можно подключаться. При первом подключении Remmina спросит про сертификат RDP – соглашаемся и сохраняем его. Через несколько секунд мы увидим рабочий стол XFCE.
В чём преимущество такой схемы подключения через SSH туннель? Во-первых, это безопасность – весь RDP трафик шифруется SSH. Во-вторых, нам не нужно открывать порт RDP наружу, что снижает риски взлома. Ну и в-третьих, SSH умеет сжимать трафик, что иногда помогает на медленных каналах связи.
Теперь проверим работает ли проброс GPU в контейнер, для начала обновим систему через консоль и установим nvtop–
sudo pacman -Syu
sudo pacman -S nvtop
И как можно заметить система видит установленную в сервер видеокарту от Nvidia, Tesla P100.
Чтобы точно проверить всё ли работает, воспользуемся простой утилитой для базового бенчмарка - glmark2. Для начала установим её –
sudo pacman -S glmark2
И запустим –
nvidia-smi --query-gpu=utilization.gpu,temperature.gpu,memory.used --format=csv -l 1 & glmark2 && kill $!
Как можно заметить, для рендеринга glmark2 использует видеокарту и нагружает её на ~4-5%.
Подводим итоги
В итоге у нас получился полноценный удаленный рабочий стол с поддержкой GPU, работающий в изолированном контейнере. Производительность на высоте – можно комфортно работать с браузером, запускать требовательные приложения и даже смотреть видео без задержек. Во многом это заслуга RDP протокола, который гораздо эффективнее X11 forwarding в плане передачи графики по сети.
Контейнеризация дает нам гибкость – можно быстро развернуть такой же рабочий стол на другом сервере или сделать бэкап всех настроек. А поддержка GPU открывает интересные возможности, например для рендеринга 3D графики или работы с нейросетями прямо через удалённый доступ.
Конечно, настройка получилась чуть сложнее чем простой проброс X11, зато результат того стоит. К тому же, разобравшись один раз, повторить процесс уже гораздо проще.
В следующей статье мы пойдём дальше и покажем, как на базе этого решения сделать свой домашний игровой стрим-сервис. Окажется, что облачный гейминг в духе GeForce Now – это не сложнее чем VDI по RDP. Нужно будет только добавить поддержку геймпадов и настроить передачу звука. Так что оставайтесь на связи!
А пока делитесь в комментариях – как вы решаете задачу удаленного доступа к графическим приложениям? Может быть есть интересные кейсы использования GPU на удаленных серверах? До встречи в следующей статье!
Комментарии (36)
Playa13
23.10.2024 11:40Лично у меня, после всех этих махинаций Firefox почему-то все равно тупит. Пытался менять разные настройки - увы, не помогает.
Может кто сталкивался с подобными ситуациями ?
VenbergV
23.10.2024 11:40А его настройки и изменения пишутся в ~/rdesktop-data/config?
Проблем со скоростью чтения и записи нет?
unreal_undead2
23.10.2024 11:40X11 Forwarding: начинаем с простого
И развлекаемся с настройками X11 клиента (шрифты и прочее), скажем, на лаптопе с виндой. vnc явно проще.
SF_author
23.10.2024 11:40А если клиент это тоже линуксовая машина с X11, либо Wayland?
Да и если кому-то понадобился так срочно проброс видео, что он делает его через проброс иксов, мне кажется, что качество шрифтов вряд ли будет беспокоить.unreal_undead2
23.10.2024 11:40Уж vnc клиент есть подо всё что движется )
если кому-то понадобился так срочно проброс видео
Мне обычно нужен десктоп целиком.
SF_author
23.10.2024 11:40Уж vnc клиент есть подо всё что движется )
Соглашусь, но настраивать его всё таки дольше, чем 1 команду для проброса иксов. Как передаёт автор этого поста, до того как он решил прибегнуть к готовым контейнерам, он собирался сначался на хостовый сервер сам установить VNC. Но цитируя его «Уж вроде бы наконец-то подключился через Remmina, но на выходе тупо чёрный экран. Проклял всё и пошёл искать готовые контейнеры.».
Мне обычно нужен десктоп целиком.
В таком случае да, из того что мне дали потыкать во время тестов, проброс иксов слабо совместим с полноценной работой где нужен доступ ко всему десктопу, да и к отдельным приложениям.
Fox_exe
23.10.2024 11:40настраивать его всё таки дольше, чем 1 команду
Окей, две команды (Ну или чуть больше, если надо кастомное шифрование и авторизацию)
apt install x11vnc x11vnc -display :0
В вашем случае надо ставить докер, к нему примочку от NVidia/AMD/Intel, кастомный конфиг контейнера прописать, запустить... Явно больше 2х команд, не считаете? (Естественно, речь о голой/домашней системе, а не о сервере, на котором уже крутится докер с кучей контейнеров)
avereshagina
23.10.2024 11:40Интересная статья, а можно поподробнее про настройку звука в таком контейнере? У меня была проблема с pulseaudio когда пытался сделать нечто подобное.
gsaw
23.10.2024 11:40SSH умеет сжимать трафик, что иногда помогает на медленных каналах связи.
Не думаю, что это поможет с RDP, c X11 да, существенно помогает, а в RDP же и так все сжимается, причем как раз алгоритмами под графику, а не zlib.
kenomimi
23.10.2024 11:40Использую kvm + spice - результат отличный, можно работать без лагов, даже видео пролетает на ура. Собственно, уже года два на такой схеме сижу, это офигенно. Минус - дай по видяхе на виртуалку, или ставь теслу которая в системе определяется как несколько карт. Еще есть гриды, но там подписка на дрова (да-да, так бывает) миллиард золотом в секунду, потому вариант отпадает.
VNC тормозит, лаги прямо сильно заметны. RDP хорошо работает на винде, на линуксе так себе, присутствуют глюки и нестабильность.
azzii
23.10.2024 11:40Отличное решение , тоже использую. Плюс usbredirect. Правда неизвестно, как будет дальше развиваться spice с учетом позиции красношляпных.
VenbergV
23.10.2024 11:40А у вас под рукой нет адекватного современного сравнения RDP и spice под Windows и Linux соответственно на медленных каналах?
Задумываемся начать перевод клиентов со старого RDP Windows на Терминальную систему под Linux. Но пять лет назад очень огорчило тестирование на каналах в 1-2Мбит. Терминальный сервер Windows работал вполне приемлемо. А вот Linux с RDP, в роли терминального сервера, был неприемлем для офисной работы. При этом клиенты Remmina вполне сносно работали с Windows терминальным сервером.SF_author
23.10.2024 11:40Интересная тема, а не подскажете пожалуйста, какую методологию использовали для замеров в тестах?
Чисто визуально или условно замеряли секундомером/как-то программно сколько занимает время на отклик, на рендер каких-то объектов, сколько пакетов и какого веса идёт по канал через Wireshark?
VenbergV
23.10.2024 11:40К сожалению, чисто визуально. Ставили два ПК рядом.
Но гоняли с неделю. Пока подопытные пользователи не взвыли.
Простая офисная работа. Открытие окон браузера с локальной почтой. Офисные документы. Да тонкий клиент 1С. Никакого видео и даже анимации в работе у пользователей не предусмотрено.
На родном RDP все происходит четче и плавнее. Особенно было заметно при попытке прокрутки офисных документов и в 1С.
Скорость канала была 2Мбит/с.
Dr_Lenin
23.10.2024 11:40Подскажите пожалуйста, а как в этой схеме можно организовать автоматическое переподключение если связь с сервером пропала? В Remmina вроде нет встроенных средств для этого.
С любопытством жду следующую статью про облачный гейминг. Хотелось бы узнать, как решается вопрос с задержкой ввода при таком подходе.
DmitryZlobec
23.10.2024 11:40Во многом это заслуга RDP протокола, который гораздо эффективнее X11 forwarding в плане передачи графики по сети.
Слона то Вы и не заметили, X11 на вашем терминале это сервер, а RDP клиент. В случае с X11 вы можете с приложениями на разных хостах работать, в этом его сила.
SF_author
23.10.2024 11:40Спасибо за замечание! Учтём!
Для нас в силу специфики проброс графики тема не специфичная, наша задача железо больше продавать, а не разворачивать на нём инфру, с VDI конкретно вовсе крайне редко взаимодействовали, так как всё обычно и так под рукой.
robert_ayrapetyan
23.10.2024 11:40Для справки следовало бы указать, что в клауд гейминге используется исключительно WebRTC, и описать захват кадров из X11 доступными способами для передачи в любой поток.
Ryav
23.10.2024 11:40Ожидал рабочий вариант с Wayland.
SF_author
23.10.2024 11:40С Wayland по идее RDP ещё стабильнее должен работать, но готовых к работе контейнеров не находили. В следующий раз можем отдельно на локальной машине эту тему покрыть.
okhsunrog
23.10.2024 11:40wayvnc у меня работает на swaywm. но он только для wlroots-based композиторов
unreal_undead2
23.10.2024 11:40но он только для wlroots-based композиторов
Вот эту вещь (безотносительно темы статьи) в Wayland вообще не понимаю. В иксах иногда тоже бывают проблемы какого-нибудь софта с конкретным window manager - но это скорее баги, в целом можно выбирать любой по вкусу. А тут бывают принципиально разные композиторы...
OrkBiotechnologist
23.10.2024 11:40Это к сожалению, вся суть Wayland.
Вместо централизация и стандартизации большая часть всего функционала доступного в иксах они отдают на индивидуальную реализацию для тех кто занимается оконными менеджерами, окружениями рабочего стола.
Самое шизофреничное на мой взгляд это весь этот бред про заботу о безопасности из-за чего они выпилили нормальную поддержку глобальных комбинаций клавиш с жестами. И у KDE своя реализация, жёстко вшитая в исходники без нормального API для стороннего взаимодействия, у GNOME своя и т.д.
Johan_Palych
23.10.2024 11:40Xpra
https://github.com/Xpra-org/xpra/
X2Go
https://wiki.x2go.org/doku.php
Wprs - аналог Xpra для систем на базе Wayland
https://github.com/wayland-transpositor/wprs
Rubicj
23.10.2024 11:40Подскажите плиз , я в Linux новичок , никак не могу победить какой то баг в Ubuntu 24.04 ... когда перевожу комп в ждущий/спящий режим .. Гаснет монитор , системный блок продолжает работать , клавиатура и мышь не отвечают .. только перегруз и соответственно потеря всего что делал... В настройках все "блокировки" выключены .. "Отключение монитора при бездействии" стоит на 12 минут , но с этим он работает нормуль . Подозреваю что-то связанное с драйверами видео ..
Помню , что в Windows по всем подключенным устройствам можно было запретить пробуждение по электропитанию ..
SF_author
23.10.2024 11:40Не совсем наша тема, а подскажите, какое у вас окружение рабочего стола, какая видеокарта, драйвер проприетарный или открытый?
Повторяется ли эта проблема в других дистрибутивах, не пробовали что-то ещё ставить? Мы всем обычно для домашнего использования EndeavoursOS с KDE Plasma советуем.
https://endeavouros.com/
dot22
23.10.2024 11:40"Ждущий режим" и "спящий режим" - это, мягко говоря, слегка разное. Несколько лет назад в Ubuntu, мне помнится, были проблемы с гибернацией (т.е. "спящим режимом") - система некорректно его отрабатывала и, чтобы вернуть компьютер к работе, приходилось его жестко перезагружать. Не знаю, с тех пор починили этот баг или нет (я недавно пробовал по одному из гайдов включить таки гибернацию на своем ноуте с Минт - так и не завелось, а разбираться мне, честно говоря, было лень), но попробуйте отключить гибернацию и\или использовать только ждущий режим.
VenbergV
23.10.2024 11:40Гибернацию надо отдельно настраивать на Ubuntu 20-24. И она имела особенности с некоторыми драйверами видео.
vk6677
23.10.2024 11:40Как то написал для интереса свою утилиту для удаленного управления в локальной сети.
Gstreamer захватывал экран и h264/265 кодеком сжимал данные. Проброс клавиатуры и мыши сделал на xcb.
Работало следующим образом. Заходил на удаленный компьютер по ssh и запускал там свою утилиту. Со своей стороны аналогичного клиента.
Из плюсов - в локальной сети можно было даже в шутеры играть (сам удивился). Из минусов - при работе с текстом иногда проскакивали кадры с артефактами.
Думал даже опубликовать исходные коды, но забросил проект.
camojiet
23.10.2024 11:40ШаломЪ православные!
С GPU и spice сейчас в proxmox из коробки вроде работает. Но в моих серверах нигде GPU нет.
Находил вот такую полезную ссылку о том как добиться от XRDP скорости без GPU, но не пробовал:
https://gist.github.com/Nexarian/df58c572d4e8549ad57195093d7cad82
Если кто пробовал - напишите, пожалуйста.
SF_author
Статья конечно интересная, но зачем городить весь этот огород с Docker? Поставил себе RDP-сервер на хостовую систему напрямую и живи спокойно. Производительность выше будет, да и настройка проще.
OrkBiotechnologist
Смею предположить, что всё таки куда проще использовать уже готовый контейнер и переносить его между разными серверами, чем проверять каждый раз что сломалось в случае конфликта зависимостей или их отсутствия в официальных репозиториях.
VenbergV
Для начала контейнер надо будет приготовить вручную под каждую задачу и под каждый Descktop/VDI. Т.к. у каждого потребителя графика нужна под свои задачи. Кому-то Blender. Кому-то Firefox, или Chrome нужной версии, с ворохом именно "вот таких вот" плагинов. С пробросом звука может быть отдельная эпопея.
Потом еще на все натянуть автоматизацию пересборки всех контейнеров при выходе очередных патчей безопасности в тех же браузерах.
А если попытаетесь запихнуть "все и сразу" в один контейнер, то сможете сильно удивится от его размеров.
В бытность развертывания терминальных серверов Windows, индивидуальная "подстройка" рабочих столов, занимала 80% времени от внедрения самого терминального сервера. А если ее не делать, то только ресурсов каждый терминальный клиент выедал в 2-3 раза больше, чем с оптимизацией.