Привет Хабр! С вами снова ServerFlow, и сегодня мы хотим поговорить об удалённом доступе к графическим приложениям на Linux-серверах. Тема эта стала особенно актуальной в последнее время – всё больше задач требует работы с GPU на удалённых машинах. Будь то рендеринг в Blender на мощном сервере, работа с нейросетями или даже облачный гейминг.

X11 Forwarding: начинаем с простого

В нашей практике мы часто сталкиваемся с ситуациями, когда клиентам нужен доступ к графическому интерфейсу на сервере. Кому-то нужна GPU-ферма для рендеринга 3D графики, другим важно тестировать свои приложения в изолированной среде. А некоторые просто хотят организовать себе удалённое рабочее место с графическим ускорением. Сегодня разберём три популярных способа организации такого доступа – от простого к сложному.

Самый простой способ запустить графическое приложение с сервера – это X11 forwarding через SSH. Для этого даже не нужно ничего дополнительно устанавливать на сервер, достаточно базового пакета openssh.

Подключаемся к серверу командой:

ssh -X -p 47645 serverflow@IP_SSH_Сервера

Флаг -X включает проброс X11. Теперь можно запустить, например, Firefox прямо из консоли:

firefox &
Firefox проброшенный через SSH с открытым Хабром
Firefox проброшенный через SSH с открытым Хабром

На первый взгляд всё работает, но... При запуске браузера сразу становятся заметны подтормаживания интерфейса. Не говоря о том что интерфейс и пользовательский ввод отображаются на экране с очень заметной задержкой измеряемой даже не секундами, а порой минутами. С чем это связано? X11 forwarding работает напрямую с примитивами отрисовки, передавая по сети каждое действие с окном, почти никак не оптимизируя и не сжимая передаваемые данные, которых при передаче видео весьма не мало. На медленном соединении это создаёт заметные задержки.
Даже простая прокрутка веб-страницы генерирует тысячи X11-команд, которые должны быть переданы по сети. А теперь представьте, что происходит при воспроизведении видео или работе с 3D-графикой. Протокол просто не был рассчитан на такие сценарии использования.
Впрочем, винить за это мы X11 не будем, так как создавался он ещё в 1980х, для куда более простых графических интерфейсов, в куда меньших разрешениях и предназначался в основном для академической и корпоративной работы с мэинфреймами.

RDP в Docker: серьёзный подход

Примерная архитектура протокола RDP
Примерная архитектура протокола RDP

Перейдём к более современному решению – 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 (это стандартные данные для образа, рекомендуем сменить после первого входа)

    Интерфейс Remmina на вкладке Basic
    Интерфейс Remmina на вкладке Basic

Переходим на вкладку "SSH Tunnel" и включаем туннелирование:

  • Enable SSH tunnel: включаем

  • Custom: выбираем этот вариант

  • SSH Server: вводим наш адрес сервера – IP_SSH_Сервера:47645

  • Username: serverflow

  • Authentication: выбираем Password или SSH key, если используете ключи

    Интерфейс Remmina на вкладке SSH Tunnel
    Интерфейс Remmina на вкладке SSH Tunnel

После сохранения профиля можно подключаться. При первом подключении Remmina спросит про сертификат RDP – соглашаемся и сохраняем его. Через несколько секунд мы увидим рабочий стол XFCE.

В чём преимущество такой схемы подключения через SSH туннель? Во-первых, это безопасность – весь RDP трафик шифруется SSH. Во-вторых, нам не нужно открывать порт RDP наружу, что снижает риски взлома. Ну и в-третьих, SSH умеет сжимать трафик, что иногда помогает на медленных каналах связи.

Remmina с запущенным удалённым рабочим столом
Remmina с запущенным удалённым рабочим столом

Теперь проверим работает ли проброс GPU в контейнер, для начала обновим систему через консоль и установим nvtop–

sudo pacman -Syu
sudo pacman -S nvtop
Remmina с запущенным в консоли nvtop
Remmina с запущенным в консоли 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 $!

Remmina с запущенным в консоли бенчмарком glmark2 и nvtop для мониторинга
Remmina с запущенным в консоли бенчмарком glmark2 и nvtop для мониторинга

Как можно заметить, для рендеринга glmark2 использует видеокарту и нагружает её на ~4-5%.

Подводим итоги

В итоге у нас получился полноценный удаленный рабочий стол с поддержкой GPU, работающий в изолированном контейнере. Производительность на высоте – можно комфортно работать с браузером, запускать требовательные приложения и даже смотреть видео без задержек. Во многом это заслуга RDP протокола, который гораздо эффективнее X11 forwarding в плане передачи графики по сети.

Контейнеризация дает нам гибкость – можно быстро развернуть такой же рабочий стол на другом сервере или сделать бэкап всех настроек. А поддержка GPU открывает интересные возможности, например для рендеринга 3D графики или работы с нейросетями прямо через удалённый доступ.

Конечно, настройка получилась чуть сложнее чем простой проброс X11, зато результат того стоит. К тому же, разобравшись один раз, повторить процесс уже гораздо проще.

В следующей статье мы пойдём дальше и покажем, как на базе этого решения сделать свой домашний игровой стрим-сервис. Окажется, что облачный гейминг в духе GeForce Now – это не сложнее чем VDI по RDP. Нужно будет только добавить поддержку геймпадов и настроить передачу звука. Так что оставайтесь на связи!

А пока делитесь в комментариях – как вы решаете задачу удаленного доступа к графическим приложениям? Может быть есть интересные кейсы использования GPU на удаленных серверах? До встречи в следующей статье!

Комментарии (36)


  1. SF_author
    23.10.2024 11:40

    Статья конечно интересная, но зачем городить весь этот огород с Docker? Поставил себе RDP-сервер на хостовую систему напрямую и живи спокойно. Производительность выше будет, да и настройка проще.


    1. OrkBiotechnologist
      23.10.2024 11:40

      Смею предположить, что всё таки куда проще использовать уже готовый контейнер и переносить его между разными серверами, чем проверять каждый раз что сломалось в случае конфликта зависимостей или их отсутствия в официальных репозиториях.


      1. VenbergV
        23.10.2024 11:40

        Для начала контейнер надо будет приготовить вручную под каждую задачу и под каждый Descktop/VDI. Т.к. у каждого потребителя графика нужна под свои задачи. Кому-то Blender. Кому-то Firefox, или Chrome нужной версии, с ворохом именно "вот таких вот" плагинов. С пробросом звука может быть отдельная эпопея.
        Потом еще на все натянуть автоматизацию пересборки всех контейнеров при выходе очередных патчей безопасности в тех же браузерах.
        А если попытаетесь запихнуть "все и сразу" в один контейнер, то сможете сильно удивится от его размеров.
        В бытность развертывания терминальных серверов Windows, индивидуальная "подстройка" рабочих столов, занимала 80% времени от внедрения самого терминального сервера. А если ее не делать, то только ресурсов каждый терминальный клиент выедал в 2-3 раза больше, чем с оптимизацией.


  1. Playa13
    23.10.2024 11:40

    Лично у меня, после всех этих махинаций Firefox почему-то все равно тупит. Пытался менять разные настройки - увы, не помогает.

    Может кто сталкивался с подобными ситуациями ?


    1. VenbergV
      23.10.2024 11:40

      А его настройки и изменения пишутся в ~/rdesktop-data/config?
      Проблем со скоростью чтения и записи нет?


  1. unreal_undead2
    23.10.2024 11:40

    X11 Forwarding: начинаем с простого

    И развлекаемся с настройками X11 клиента (шрифты и прочее), скажем, на лаптопе с виндой. vnc явно проще.


    1. SF_author
      23.10.2024 11:40

      А если клиент это тоже линуксовая машина с X11, либо Wayland?
      Да и если кому-то понадобился так срочно проброс видео, что он делает его через проброс иксов, мне кажется, что качество шрифтов вряд ли будет беспокоить.


      1. unreal_undead2
        23.10.2024 11:40

        Уж vnc клиент есть подо всё что движется )

        если кому-то понадобился так срочно проброс видео

        Мне обычно нужен десктоп целиком.


        1. SF_author
          23.10.2024 11:40

          Уж vnc клиент есть подо всё что движется )

          Соглашусь, но настраивать его всё таки дольше, чем 1 команду для проброса иксов. Как передаёт автор этого поста, до того как он решил прибегнуть к готовым контейнерам, он собирался сначался на хостовый сервер сам установить VNC. Но цитируя его «Уж вроде бы наконец-то подключился через Remmina, но на выходе тупо чёрный экран. Проклял всё и пошёл искать готовые контейнеры.».

          Мне обычно нужен десктоп целиком.

          В таком случае да, из того что мне дали потыкать во время тестов, проброс иксов слабо совместим с полноценной работой где нужен доступ ко всему десктопу, да и к отдельным приложениям.


          1. Fox_exe
            23.10.2024 11:40

            настраивать его всё таки дольше, чем 1 команду

            Окей, две команды (Ну или чуть больше, если надо кастомное шифрование и авторизацию)

            apt install x11vnc
            x11vnc -display :0

            В вашем случае надо ставить докер, к нему примочку от NVidia/AMD/Intel, кастомный конфиг контейнера прописать, запустить... Явно больше 2х команд, не считаете? (Естественно, речь о голой/домашней системе, а не о сервере, на котором уже крутится докер с кучей контейнеров)


  1. avereshagina
    23.10.2024 11:40

    Интересная статья, а можно поподробнее про настройку звука в таком контейнере? У меня была проблема с pulseaudio когда пытался сделать нечто подобное.


  1. gsaw
    23.10.2024 11:40

    SSH умеет сжимать трафик, что иногда помогает на медленных каналах связи.

    Не думаю, что это поможет с RDP, c X11 да, существенно помогает, а в RDP же и так все сжимается, причем как раз алгоритмами под графику, а не zlib.


  1. kenomimi
    23.10.2024 11:40

    Использую kvm + spice - результат отличный, можно работать без лагов, даже видео пролетает на ура. Собственно, уже года два на такой схеме сижу, это офигенно. Минус - дай по видяхе на виртуалку, или ставь теслу которая в системе определяется как несколько карт. Еще есть гриды, но там подписка на дрова (да-да, так бывает) миллиард золотом в секунду, потому вариант отпадает.

    VNC тормозит, лаги прямо сильно заметны. RDP хорошо работает на винде, на линуксе так себе, присутствуют глюки и нестабильность.


    1. azzii
      23.10.2024 11:40

      Отличное решение , тоже использую. Плюс usbredirect. Правда неизвестно, как будет дальше развиваться spice с учетом позиции красношляпных.


    1. azzii
      23.10.2024 11:40

      Правда адекватного варианта работы с видеокартой нет.


    1. VenbergV
      23.10.2024 11:40

      А у вас под рукой нет адекватного современного сравнения RDP и spice под Windows и Linux соответственно на медленных каналах?
      Задумываемся начать перевод клиентов со старого RDP Windows на Терминальную систему под Linux. Но пять лет назад очень огорчило тестирование на каналах в 1-2Мбит. Терминальный сервер Windows работал вполне приемлемо. А вот Linux с RDP, в роли терминального сервера, был неприемлем для офисной работы. При этом клиенты Remmina вполне сносно работали с Windows терминальным сервером.


      1. SF_author
        23.10.2024 11:40

        Интересная тема, а не подскажете пожалуйста, какую методологию использовали для замеров в тестах?

        Чисто визуально или условно замеряли секундомером/как-то программно сколько занимает время на отклик, на рендер каких-то объектов, сколько пакетов и какого веса идёт по канал через Wireshark?


        1. VenbergV
          23.10.2024 11:40

          К сожалению, чисто визуально. Ставили два ПК рядом.
          Но гоняли с неделю. Пока подопытные пользователи не взвыли.
          Простая офисная работа. Открытие окон браузера с локальной почтой. Офисные документы. Да тонкий клиент 1С. Никакого видео и даже анимации в работе у пользователей не предусмотрено.
          На родном RDP все происходит четче и плавнее. Особенно было заметно при попытке прокрутки офисных документов и в 1С.
          Скорость канала была 2Мбит/с.


      1. kenomimi
        23.10.2024 11:40

        Пробовал через сотовую связь (LTE-модем в ноуте) - и то, и то визуально работает одинаково. Правда, spice не любит обрывы связи - подвисает и выпадает, когда как у RDP есть адекватное переподключение.


        1. VenbergV
          23.10.2024 11:40

          А RDP сервер был Windows или Linux?


  1. Dr_Lenin
    23.10.2024 11:40

    Подскажите пожалуйста, а как в этой схеме можно организовать автоматическое переподключение если связь с сервером пропала? В Remmina вроде нет встроенных средств для этого.

    С любопытством жду следующую статью про облачный гейминг. Хотелось бы узнать, как решается вопрос с задержкой ввода при таком подходе.


  1. DmitryZlobec
    23.10.2024 11:40

    Во многом это заслуга RDP протокола, который гораздо эффективнее X11 forwarding в плане передачи графики по сети.

    Слона то Вы и не заметили, X11 на вашем терминале это сервер, а RDP клиент. В случае с X11 вы можете с приложениями на разных хостах работать, в этом его сила.


    1. SF_author
      23.10.2024 11:40

      Спасибо за замечание! Учтём!
      Для нас в силу специфики проброс графики тема не специфичная, наша задача железо больше продавать, а не разворачивать на нём инфру, с VDI конкретно вовсе крайне редко взаимодействовали, так как всё обычно и так под рукой.


  1. robert_ayrapetyan
    23.10.2024 11:40

    Для справки следовало бы указать, что в клауд гейминге используется исключительно WebRTC, и описать захват кадров из X11 доступными способами для передачи в любой поток.


  1. Ryav
    23.10.2024 11:40

    Ожидал рабочий вариант с Wayland.


    1. SF_author
      23.10.2024 11:40

      С Wayland по идее RDP ещё стабильнее должен работать, но готовых к работе контейнеров не находили. В следующий раз можем отдельно на локальной машине эту тему покрыть.


    1. okhsunrog
      23.10.2024 11:40

      wayvnc у меня работает на swaywm. но он только для wlroots-based композиторов


      1. unreal_undead2
        23.10.2024 11:40

        но он только для wlroots-based композиторов

        Вот эту вещь (безотносительно темы статьи) в Wayland вообще не понимаю. В иксах иногда тоже бывают проблемы какого-нибудь софта с конкретным window manager - но это скорее баги, в целом можно выбирать любой по вкусу. А тут бывают принципиально разные композиторы...


        1. OrkBiotechnologist
          23.10.2024 11:40

          Это к сожалению, вся суть Wayland.
          Вместо централизация и стандартизации большая часть всего функционала доступного в иксах они отдают на индивидуальную реализацию для тех кто занимается оконными менеджерами, окружениями рабочего стола.
          Самое шизофреничное на мой взгляд это весь этот бред про заботу о безопасности из-за чего они выпилили нормальную поддержку глобальных комбинаций клавиш с жестами. И у KDE своя реализация, жёстко вшитая в исходники без нормального API для стороннего взаимодействия, у GNOME своя и т.д.


  1. Johan_Palych
    23.10.2024 11:40

    Xpra
    https://github.com/Xpra-org/xpra/
    X2Go
    https://wiki.x2go.org/doku.php
    Wprs - аналог Xpra для систем на базе Wayland
    https://github.com/wayland-transpositor/wprs


  1. Rubicj
    23.10.2024 11:40

    Подскажите плиз , я в Linux новичок , никак не могу победить какой то баг в Ubuntu 24.04 ... когда перевожу комп в ждущий/спящий режим .. Гаснет монитор , системный блок продолжает работать , клавиатура и мышь не отвечают .. только перегруз и соответственно потеря всего что делал... В настройках все "блокировки" выключены .. "Отключение монитора при бездействии" стоит на 12 минут , но с этим он работает нормуль . Подозреваю что-то связанное с драйверами видео ..

    Помню , что в Windows по всем подключенным устройствам можно было запретить пробуждение по электропитанию ..


    1. SF_author
      23.10.2024 11:40

      Не совсем наша тема, а подскажите, какое у вас окружение рабочего стола, какая видеокарта, драйвер проприетарный или открытый?

      Повторяется ли эта проблема в других дистрибутивах, не пробовали что-то ещё ставить? Мы всем обычно для домашнего использования EndeavoursOS с KDE Plasma советуем.
      https://endeavouros.com/


    1. dot22
      23.10.2024 11:40

      "Ждущий режим" и "спящий режим" - это, мягко говоря, слегка разное. Несколько лет назад в Ubuntu, мне помнится, были проблемы с гибернацией (т.е. "спящим режимом") - система некорректно его отрабатывала и, чтобы вернуть компьютер к работе, приходилось его жестко перезагружать. Не знаю, с тех пор починили этот баг или нет (я недавно пробовал по одному из гайдов включить таки гибернацию на своем ноуте с Минт - так и не завелось, а разбираться мне, честно говоря, было лень), но попробуйте отключить гибернацию и\или использовать только ждущий режим.


      1. VenbergV
        23.10.2024 11:40

        Гибернацию надо отдельно настраивать на Ubuntu 20-24. И она имела особенности с некоторыми драйверами видео.


  1. vk6677
    23.10.2024 11:40

    Как то написал для интереса свою утилиту для удаленного управления в локальной сети.

    Gstreamer захватывал экран и h264/265 кодеком сжимал данные. Проброс клавиатуры и мыши сделал на xcb.

    Работало следующим образом. Заходил на удаленный компьютер по ssh и запускал там свою утилиту. Со своей стороны аналогичного клиента.

    Из плюсов - в локальной сети можно было даже в шутеры играть (сам удивился). Из минусов - при работе с текстом иногда проскакивали кадры с артефактами.

    Думал даже опубликовать исходные коды, но забросил проект.


  1. camojiet
    23.10.2024 11:40

    ШаломЪ православные!
    С GPU и spice сейчас в proxmox из коробки вроде работает. Но в моих серверах нигде GPU нет.
    Находил вот такую полезную ссылку о том как добиться от XRDP скорости без GPU, но не пробовал:
    https://gist.github.com/Nexarian/df58c572d4e8549ad57195093d7cad82
    Если кто пробовал - напишите, пожалуйста.