Table of Contents

Для чего

Мне нужен headless LXC-контейнер с экономичным декстопным окружением, доступ к которому будет осуществляться по VNC, а лучше - по RDP.

Варианты решения

В качестве ОС контейнера выступает Ubuntu 16.04.
Для запуска иксов в headless-контейнере понадобится эмуляция видеоадаптера.
Для этих целей можно использовать либо xvfb (X Virtual Frame Buffer) либо xdummy. Оба пакета присутствуют в репозиториях большинства дистрибутивов, однако, более продвинутым является xdummy.
В данной заметке я рассмотрю настройку двух этих решений.
В качестве десктопного окружения я протестирую пару - Xfce и LXDE. Сразу скажу, что вариант с Xfce мне понравился гораздо больше.
Для доступа к графической оболочке я планирую использовать VNC или RDP (но можно использовать и другие протоколы). Например: SPICE - https://discuss.linuxcontainers.org/t/access-container-via-spice-sharing-clipboard/2544/3

Xfce + xdummy + xrdp

Установка необходимых компонент:

sudo apt-get -y install nano curl xserver-xorg-video-dummy xserver-xorg-core x11vnc xubuntu-desktop

Настройки X для работы с xdummy (файлик /etc/X11/xorg.conf):

 
# This xorg configuration file is meant to be used
# to start a dummy X11 server.
# For details, please see:
# https://www.xpra.org/xorg.conf

# Here we setup a Virtual Display of 1600x900 pixels

Section "Device"
    Identifier "Configured Video Device"
    Driver "dummy"
    #VideoRam 4096000
    #VideoRam 256000
    VideoRam 16384
EndSection

Section "Monitor"
    Identifier "Configured Monitor"
    HorizSync 5.0 - 1000.0
    VertRefresh 5.0 - 200.0
    Modeline "1600x900" 33.92 1600 1632 1760 1792 900 921 924 946
EndSection

Section "Screen"
    Identifier "Default Screen"
    Monitor "Configured Monitor"
    Device "Configured Video Device"
    DefaultDepth 24
    SubSection "Display"
        Viewport 0 0
        Depth 24
        Virtual 1600 900
    EndSubSection
EndSection

Список строчек для различных режимов:

    Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135
    Modeline "1680x1050" 20.08 1680 1712 1784 1816 1050 1075 1077 1103
    Modeline "1600x1200" 22.04 1600 1632 1712 1744 1200 1229 1231 1261
    Modeline "1600x900" 33.92 1600 1632 1760 1792 900 921 924 946
    Modeline "1440x900" 30.66 1440 1472 1584 1616 900 921 924 946
    ModeLine "1366x768" 72.00 1366 1414 1446 1494 768 771 777 803
    Modeline "1280x1024" 31.50 1280 1312 1424 1456 1024 1048 1052 1076
    Modeline "1280x800" 24.15 1280 1312 1400 1432 800 819 822 841
    Modeline "1280x768" 23.11 1280 1312 1392 1424 768 786 789 807
    Modeline "1360x768" 24.49 1360 1392 1480 1512 768 786 789 807
    Modeline "1024x768" 18.71 1024 1056 1120 1152 768 786 789 807

XRDP

Я буду использовать связку xrdp + xorgrdp. Раньше довольно популярным было использование x11rdp, однако его поддержки нужно пересобрать Xorg, а в случае с xorgrdp этого не требуется.
Xrdp можно установить из репозитория, однако он там довольно старый. Я предпочитаю собирать последнюю версию. Ставим средства для сборки:

sudo apt-get install git autoconf libtool pkg-config gcc g++ make  libssl-dev libpam0g-dev libjpeg-dev libx11-dev libxfixes-dev libxrandr-dev  flex bison libxml2-dev intltool xsltproc xutils-dev python-libxml2 g++ xutils libfuse-dev libmp3lame-dev nasm libpixman-1-dev xserver-xorg-dev

Скачиваем и собираем:

mkdir ./xrdp
cd xrdp/
wget https://github.com/neutrinolabs/xorgxrdp/releases/download/v0.2.1/xorgxrdp-0.2.1.tar.gz
wget https://github.com/neutrinolabs/xrdp/releases/download/v0.9.2/xrdp-0.9.2.tar.gz
tar -xvf ./xrdp-0.9.2.tar.gz 
cd ./xrdp-0.9.2
./bootstrap
./configure --enable-fuse --enable-rfxcodec --enable-mp3lame --enable-pixman --disable-painter --disable-ipv6
make
sudo make install
sudo ln -s /usr/local/sbin/xrdp{,-sesman} /usr/sbin
cd ..
tar xvfz xorgxrdp-0.2.1.tar.gz 
cd xorgxrdp-0.2.1
./bootstrap
./configure
make
sudo make install

Настройка XRDP

В принципе, достаточно просто включить сервис и уже можно подключаться.

sudo systemctl enable xrdp
sudo service xrdp start 

Однако, неплохо бы немного скорректировать список доступных при подключении опций - по умолчанию он избыточен.
Для этого открываем файлик /etc/xrdp/xrdp.ini и в нижней части в разделе Session types удаляем или комментируем все, кроме:

;
; Session types
;

[Xorg]
name=Xorg
lib=libxup.so
username=ask
password=ask
ip=127.0.0.1
port=-1
code=20

lightdm

/etc/lightdm/lightdm.conf

[Seat:*]
xserver-allow-tcp=false
xserver-command=X -nolisten tcp

Проблемы

После обновления контейнера Ubutnu 16.04 до 18.04 перестал работать xrdp.
После ввода логина и пароля он долго тупит, а потом выдает:

login successful for display 10
started connecting
connection problem, giving up
some problem

В логе /var/log/xrdp.log ошибки:

[DEBUG] Closed socket 19 (AF_UNIX)

В логе /var/log/xrdp-sesman.log ошибка:

[ERROR] X server for display 10 startup timeout

В директории пользователя, который логинится в файле ~/.xorgxrdp.XX.log такое:

[  4034.806] (II) LoadModule: "xorgxrdp"
[  4034.807] (II) Loading /usr/lib/xorg/modules/libxorgxrdp.so
[  4034.807] (II) Module XORGXRDP: vendor="X.Org Foundation"
[  4034.807]    compiled for 1.18.4, module version = 1.0.0
[  4034.807]    ABI class: X.Org Video Driver, version 20.0
[  4034.807] (EE) xorgxrdp: module ABI major version (20) doesn't match the server's version (23)
[  4034.807] (II) UnloadModule: "xorgxrdp"
[  4034.807] (II) Unloading xorgxrdp
[  4034.807] (EE) Failed to load module "xorgxrdp" (module requirement mismatch, 0)

Причина - несоответствие ABI собранного вручную модуля xorgxrdp и текущего Xorg.
Решение - пересобрать xorgxrdp с текущими библиотеками xserver-xorg-dev и переустановить его.

LXDE + Xvfb + x11vnc

В качестве ОС контейнера выступает Ubuntu 16.04, а в качестве DE - пакет lubuntu-desktop.

sudo apt-get update && sudo apt-get -y upgrade
sudo apt-get -y install nano curl xvfb xserver-xorg-core x11vnc lubuntu-desktop

Дальше план такой - в скрипт /etc/X11/xinit/xserverrc прописываем запуск Xvfb - в результате у нас будет дисплей :0 и прописываем в конфигурацию lightdm запуск этого скрипта (вместо дефолтной команды X). В результате при старте lightdm у нас запустится Xvfb. Потом создадим сервис x11vnc и настроим его автозапуск.
Поехали.
Настраиваем lightdm, чтобы он запускал при старте иксов /etc/X11/xinit/xserverrc, а не дефолтную команду xserver-command=X . Для этого в файлик /etc/lightdm/lightdm.conf пишем вот что:

[SeatDefaults]
greeter-session=lightdm-gtk-greeter
user-session=Xubuntu
xserver-command=/etc/X11/xinit/xserverrc

Cкорректируем /etc/X11/xinit/xserverrc, чтобы запускался Xvfb

#!/bin/sh

#exec /usr/bin/X -nolisten tcp "$@"
exec Xvfb :0 -screen 0 1024x768x24

Теперь нужно организовать автоматический запуск x11vnc. Это можно сделать двумя путями. Либо прописать строку запуска в /etc/rc.local, либо создать сервис в systemd. Создадим сервис. В файлик /lib/systemd/system/x11vnc.service напишем такое:

[Unit]
Description=Remote control service x11vnc
After=graphical.target

[Service]
Restart=always
RestartSec=5
Type=simple
ExecStart=-/usr/bin/x11vnc -display :0 -auth "/var/run/lightdm/root/:0" -rfbauth /etc/x11vnc.pass -o /var/log/x11vnc.log
User=x11vnc
Group=x11vnc

[Install]
WantedBy=graphical.target

Создадим пользователя для запуска этого сервиса, создадим файлик с логами и дадим на него права:

sudo useradd x11vnc --system
sudo touch /var/log/x11vnc.log
sudo chown -R x11vnc /var/log/x11vnc.log 

Включаем и запускаем сервис:

sudo systemctl enable x11vnc.service
sudo systemctl start x11vnc.service

Проверяем статус сервиса:

sudo systemctl status x11vnc.service

И, наконец, задаем пароль для VNC:

sudo x11vnc -storepasswd yourVNCpasswordHERE /etc/x11vnc.pass
sudo chown x11vnc /etc/x11vnc.pass