Графическое исполнение.
См. Часть 1
Введение
Клиент RDP — это программное обеспечение, которое позволяет подключиться к терминальному серверу с использованием протокола удалённого рабочего стола (Remote Desktop Protocol).
Технология RDP позволяет применять малопроизводительные компьютеры в качестве терминалов (так называемых тонких клиентов). Все необходимые функции, включая рабочую систему, офисные программы и современный браузер, будут выполняться на сервере.
Поэтому создаём свой легковесный образ на на основе Debian 12, используя проверенные пакеты. Готовый образ можно будет записать как на USB-флешку, так и на жесткий диск. А в перспективе такой образ можно будет загружать на тонкий клиент через сеть.
Постановка задачи
В предыдущей части было дана инструкция, как сделать загрузочный образ. В этой части установим и настроим пакеты для подключения к удаленному рабочему столу.
План действий:
установить необходимые пакеты
настроить разрешения для учётной записи user
настроить графическую среду
организовать диалоговое окно для авторизации
настроить автозагрузку графической системы
записать образ на USB-носитель.
В статье приведены примеры консольных команд, которые необходимо выполнять в зависимости от задачи в хостовой или гостевой системе. Чтобы различать эти команды, перед ними будет отображаться приглашение:
$ — команды, выполняемые в хостовой системе.root> — команды, выполняемые в гостевой системе от имени root.user> — команды, выполняемые в гостевой системе от имени user.
Хостовая система — система, на которой запускаются виртуальные машины.
Гостевая система — система, которая работает внутри виртуальной машины.
Допустим, что RDP-сервер настроен по адресу 192.168.10.2. К нему будем подключаться для проверки системы.
Запуск виртуальной машины
Перед началом работы с виртуальной машиной рекомендуется создать резервную копию образа.
Скрипт запуска виртуальной машины:
#!/bin/bash
qemu-system-x86_64 \
-name "usb-debian" \
-m 2048M \
-enable-kvm \
-cpu host \
-smp 2 \
-machine type=q35 \
-bios OVMF.fd \
-net nic -net user,hostfwd=tcp::2222-:22 \
-drive file=image.qcow2 \
&После старта виртуальной машины рекомендую подключиться к гостевой системе по SSH:
$ ssh -p 2222 root@localhostРабота по SSH позволяет использовать буфер обмена, что облегчает набор команд.
Установка необходимых пакетов
Гостевая система была настроена так, что после каждого её выключения обнуляется кеш доступных пакетов. Поэтому обновите кеш:
root> apt update1. Установка и настройка sudo
Для управления системой от имени обычного пользователя установите пакет:
root> apt install -y sudoТеперь предоставим пользователю user возможность выполнять команды управления питанием без ввода пароля. В конец файла /etc/sudoers необходимо добавить строку:
user ALL=NOPASSWD: /sbin/halt, /sbin/reboot, /sbin/poweroffЭто позволит пользователю user выполнять команды без ввода пароля:
user> sudo halt # выключение
user> sudo reboot # перезагрузка
user> sudo poweroff # выключение2. Установка netcat для диагностики сети
В виртуальной среде QEMU по умолчанию не поддерживается ICMP-трафик, поэтому команда ping не работает или возвращает ошибку, даже если сеть функционирует корректно.
Для проверки доступности серверов вместо ping рекомендуется использовать netcat — утилиту для тестирования TCP/UDP-портов.
Установите netcat (OpenBSD-версия):
root> apt install netcat-openbsdRDP по умолчанию использует порт 3389. Проверим его на нашем сервере:
root> nc -zv -w 1 192.168.10.2 3389-z— режим проверки порта (без передачи данных)-v— подробный вывод-w 1— таймаут в 1 секунду
Ожидаемый результат:
Connection to 192.168.10.2 3389 port [tcp/ms-wbt-server] succeeded!3. Установка графической подсистемы X.Org
Для запуска графического RDP-клиента установим минимальную реализацию X-сервера:
root> apt install -y --no-install-recommends xorgОбъём занимаемого дискового пространства 275 МБ
Флаг
--no-install-recommendsпредотвращает установку рекомендуемых пакетов, экономя около 10 МБ.
В интернете встречаются советы по установке более урезанных конфигураций X.Org. Лучше всё же использовать стандартный xorg. Это обеспечивает максимальную совместимость с различным оборудованием и предотвращает проблемы с разрешением экрана или драйверами на чужих компьютерах.
4. Установка RDP-клиента на базе FreeRDP
Рекомендую установить стабильную и проверенную версию FreeRDP 2:
root> apt install -y --no-install-recommends freerdp2-x11Занимаемый объем: 147 МБ
Если требуется более новая версия с улучшенной поддержкой протокола FreeRDP 3, добавьте репозиторий unstable в файл /etc/apt/sources.list:
deb https://deb.debian.org/debian/ unstable mainУстановите freerdp3-x11:
root> apt update
root> apt install -y --no-install-recommends freerdp3-x11Графический режим
1. Отключение автологина в консоль
Если ранее был настроен автоматический вход в систему от имени root, то сейчас его надо отключить. Он будет нам мешать тестированию графического режима от имени user.
В файле сервиса /usr/lib/systemd/system/getty@.service необходимо вернуть старое значение ExecStart:
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear - $TERMПримените изменения, перезагрузив гостевую систему:
root> reboot2. Тестирование графического режима
Ниже — несколько способов запуска и отладки GUI-приложений.
Рекомендуемая схема работы:
В окне QEMU входите под пользователем
userПараллельно подключайтесь по SSH (под
rootилиuser) для выполнения административных команд и копирования файлов
Способ 1: X11-перенаправление через SSH
SSH поддерживает перенаправление графического интерфейса (X11 forwarding). Это позволяет запускать графические приложения на гостевой системе, но отображать их на хосте.
Подключитесь с флагом -X:
$ ssh -X -p 2222 root@localhostТеперь любое GUI-приложение будет отображаться на экране хостовой системы:
user> xcalc
Калькулятор откроется на вашем основном рабочем столе, не в окне QEMU.
Способ 2: Запуск графической среды в окне QEMU
Самый наглядный способ — запустить X-сервер непосредственно в окне QEMU.
После входа в консоль гостевой системы выполните:
user> startxБудет запущена графическая среда с xterm. Вы увидите её в окне QEMU. Этот способ полезен для:
Проверки разрешения экрана
Тестирования отображения шрифтов и интерфейса
Отладки проблем с драйверами или окружением
Способ 3: Ручное перенаправление в запущенный X-сессию
Если графическая среда уже запущена (через startx), вы можете отправлять в неё GUI-приложения из SSH-сессии. Установите переменную окружения DISPLAY:
root> export DISPLAY=:0Теперь любое графическое приложение будет отображаться в сессии X-сервера в QEMU:
user> xclock
user> xeyesПопробуйте все три варианта — они дополняют друг друга и облегчат отладить графическую среду на разных этапах настройки.
3. Тестирование RDP-клиента
Теперь можно протестировать подключение к RDP-серверу:
user> startx
user> xfreerdp /u:user /p:12345678 /v:192.168.10.2 /cert:ignore/u:user— Учётная запись пользователя на RDP-сервере/p:12345678— Пароль для аутентификации/v:192.168.10.2— IP-адрес RDP-сервера/cert:ignore— Игнорирует предупреждения о самоподписанных или недоверенных сертификатах

Настройка графического режима для пользователя user
Задача портативного RDP-клиента проста: отобразить интерфейс подключения к удалённому рабочему столу и обеспечить доступ к терминалу.
Установка полноценного графического менеджера окон (например, XFCE, LXDE или GNOME) избыточна — он добавит ненужные компоненты: шрифты, панели, рабочие столы, горячие клавиши, которые не только увеличат размер образа, но и будут мешать автоматизации.
Если же вы хотите более гибкий интерфейс, можно рассмотреть лёгкие менеджеры, такие как BlackBox или Openbox. А для портативного RDP-клиента проще и надёжнее обойтись без них.
1. Настройка внешнего вида терминала xterm
Создайте файл конфигурации графических параметров /home/user/.Xresources:
! Открытие терминала в полноэкранном режиме
xterm*maximized: true
! Цветовая схема: тёмный фон, светлый текст
xterm*background: #111111
xterm*foreground: #dddddd
! Шрифт и размер
xterm*faceName: Monospace
xterm*faceSize: 12
! Прокрутка: сохранять до 10 000 строк, прокрутка по клавише
xterm*saveLines: 10000
xterm*scrollKey: true2. Автозапуск графической среды .xinitrc
Файл /home/user/.xinitrc определяет, что запускается при старте X-сервера.
# Загрузить пользовательские настройки из .Xresources
xrdb -merge ~/.Xresources
# Установить стандартный курсор (стрелка)
xsetroot -cursor_name left_ptr
# Запустить xterm вместе с Midnight Commander
exec xterm -e mc3. Настройка приглашения командной строки
Для удобства измените приглашение в терминале. В конце файла /home/user/.bashrc необходимо добавить:
PS1='user> 'Теперь приглашение будет выглядеть как:
user>4. Права доступа к файлам
Чтобы пользователь user владел своими файлами:
root> chown -R user:user /home/user5. Тестирование графического режима
Теперь можно запустить X-сервер:
user> startx
Создание скрипта запуска RDP-клиента
Чтобы превратить систему в удобный терминал, необходимо создать надёжный и понятный интерфейс подключения к RDP-серверу. Ниже — пошаговое построение скрипта, от простого подключения до полноценного меню.
Этап 1: Базовое подключение
Начнём с минимальной команды для подключения:
xfreerdp /u:user /p:12345678 /v:192.168.10.10 \
/f /bpp:16 /network:auto /sec:rdp /cert:ignore \
/sound +clipboardПояснение параметров:
/f— полноэкранный режим/bpp:16— 16-битная глубина цвета (экономия трафика)/network:auto— автоматическая настройка под сеть/sec:rdp— использование стандартного шифрования RDP/cert:ignore— игнорировать предупреждения сертификатов (для тестов)+clipboard— общий буфер обмена
Этап 2: Простой скрипт
Создайте файл rdp.sh:
#!/bin/bash
# Конфигурация подключения
XAPP='xfreerdp'
XSERVER='192.168.10.10'
XPORT='3389'
XPARAMS='/f /bpp:16 /network:auto /sec:rdp /cert:ignore /sound +clipboard'
XUSER='user'
XPASS='12345678'
XTIMEOUT=10
# Подключение
cmd="$XAPP /u:$XUSER /p:$XPASS /v:$XSERVER:$XPORT $XPARAMS"
$cmd > /dev/null 2>&1Сделайте скрипт исполняемым:
chmod +x rdp.shРекомендуется сначала тестировать скрипт на хостовой системе, а затем переносить в гостевую.

Этап 3: Проверка доступности сервера
Добавим проверку, включён ли RDP-сервер:
do_wait_server() {
local sec=0
while (( sec <= XTIMEOUT )); do
if nc -z -w 1 $XSERVER $XPORT > /dev/null 2>&1; then
return 0
fi
((sec++))
sleep 1
done
return 1
}Интеграция в скрипт:
do_wait_server
if (( $? == 0 )); then
$cmd > /dev/null 2>&1
else
echo "Сервер не доступен!"
fiЭтап 4: Ввод логина и пароля
Чтобы не хранить пароль в открытом виде, добавим ввод с клавиатуры и сохранение логина:
# Загрузка сохранённого логина
if [[ -f ./rdp.usr ]]; then
XUSER=$(cat ./rdp.usr)
fi
# Ввод
read -p "Логин ($XUSER): " input; [[ "$input" ]] && XUSER=$input
read -p "Пароль: " XPASS
# Сохранение
echo "$XUSER" > ./rdp.usr5: Графическое меню с whiptail
Для удобства пользователя внедрим диалоговое меню на базе whiptail — утилиты, входящей в стандартные дистрибутивы.
Финальный скрипт: rdp.sh:
Скрытый текст
#!/bin/bash
#========================================
# Конфигурация
#========================================
# RDP-сервер
XSERVER='172.16.4.230'
XPORT='3389'
# Таймаут проверки сервера (сек)
XTIMEOUT=5
# програма для подключения
XAPP='xfreerdp'
# параметры для подключения к RDP-серверу
XPARAMS='/f /bpp:16 /network:auto /sec:rdp /cert:ignore /sound +clipboard'
# файл для сохранения настроек
XCONFIG='./rdp.usr'
# Оперативные данные
XUSER='user'
XPASS=''
XEXEC=0
# Команды
cmd_set_pass=1
cmd_set_name=2
cmd_poweroff=3
cmd_terminal=4
cmd_exit=5
cmd_menu=100
cmd_connect=101
#========================================
# Функции
#========================================
#----------------------------------------
# Загрузить сохраненные параметры
do_load() {
if [[ -f $XCONFIG ]]; then
XUSER=`<"$XCONFIG"`
XEXEC=$cmd_set_pass
else
XUSER='user'
XEXEC=$cmd_set_name
fi
}
#----------------------------------------
# Сохранить параметры
do_save() {
printf "%s\n" $XUSER > $XCONFIG
}
#----------------------------------------
# Вывести сообщение
do_message() {
whiptail --msgbox "$1" 8 40 \
--backtitle "RDP-клиент" \
--ok-button "Принял"
}
#----------------------------------------
# Показать главное меню
do_menu() {
local data
data=$(whiptail \
--title "RDP-клиент: $XUSER" \
--backtitle "RDP-клиент" \
--nocancel \
--ok-button "Выбрать" \
--menu "" 12 45 4 \
"$cmd_set_pass" "Подключится к серверу" \
"$cmd_set_name" "Новое имя пользователя" \
"$cmd_poweroff" "Выключить компьютер" \
"$cmd_terminal" "Открыть Терминал" \
3>&1 1>&2 2>&3)
if (( $? == 0 )); then
XEXEC=$data
else
XEXEC=$cmd_menu
fi
}
#----------------------------------------
# Показать окно для ввода имени пользователя
do_set_user() {
local data
data=$(whiptail --title "Авторизация: $XUSER" \
--backtitle "RDP-клиент" \
--ok-button "Далее" \
--inputbox "Имя:" 8 30 "$XUSER" \
3>&1 1>&2 2>&3)
if (( $? == 0 )); then
XUSER=$data
XEXEC=$cmd_set_pass
else
XEXEC=$cmd_menu
fi
}
#----------------------------------------
# Показать окно для ввода пароля
do_set_pass() {
data=$(whiptail \
--title "Авторизация: $XUSER" \
--backtitle "RDP-клиент" \
--ok-button "Вход" \
--cancel-button "Омена" \
--passwordbox "Пароль:" 8 40 \
3>&1 1>&2 2>&3)
if (( $? == 0 )); then
if [[ "$data" != "" ]]; then
XPASS=$data
XEXEC=$cmd_connect
else
XEXEC=$cmd_set_pass
fi
else
XEXEC=$cmd_menu
fi
}
#----------------------------------------
# Ожидать доступности сервера
do_wait_server() {
local step=$((10/$XTIMEOUT))
local value=0
# из-за использования pipe во временном файле буду хранить статус
local ftemp=$(mktemp)
echo 1 > $ftemp
while (($value<100));
do
((value+=step))
echo $value
# проверка порта
if timeout 0.1 nc -z $XSERVER $XPORT>/dev/null 2>&1; then
echo 0 > $ftemp
break
fi
done | whiptail --gauge "Ожидание сервера" 6 60 0
read -r result <$ftemp
rm $ftemp
return $result
}
#----------------------------------------
# Подключиться к серверу
do_connect() {
echo 'Подключение...'
# сохранить данные
do_save
# ожидать доступности сервера
do_wait_server
if (( $? == 0 )); then
local cmd="$XAPP /u:$XUSER /p:$XPASS /v:$XSERVER:$XPORT $XPARAMS"
$cmd > /dev/null 2>&1
else
do_message "❌ Сервер не доступен!"
fi
# следующая команда
XEXEC=$cmd_set_pass
}
#----------------------------------------
# Выключить компьютер
do_poweroff() {
echo 'Выключение компьютера...'
sudo poweroff
exit
}
#----------------------------------------
# Запустить терминал
do_terminal() {
local pass
pass=$(whiptail \
--title "Терминал: root" \
--backtitle "RDP-клиент" \
--ok-button "Вход" \
--cancel-button "Омена" \
--passwordbox "Пароль:" 8 40 \
3>&1 1>&2 2>&3)
if (( $? == 0 )) && [[ "$pass" != "" ]]; then
echo "$pass" | su -c 'uxterm -e bash /root/.profile'
fi
# следующая команда
XEXEC=$cmd_menu
}
#========================================
# Основной цикл
#========================================
clear
do_load
while true; do
case $XEXEC in
$cmd_menu) do_menu ;;
$cmd_connect) do_connect ;;
$cmd_set_pass) do_set_pass ;;
$cmd_set_name) do_set_user ;;
$cmd_poweroff) do_poweroff ;;
$cmd_terminal) do_terminal ;;
$cmd_exit) exit ;;
esac
done
Итоговое поведение:
При запуске появляется окно авторизации
При отмене авторизации пользователь в меню может:
Подключиться к RDP-серверу
Сменить имя пользователя
Открыть терминал (с правами root)
Выключить компьютер
Логин сохраняется для следующего сеанса
Перед подключением проверяется доступность сервера


6. Интеграция в автозапуск
Чтобы скрипт запускался автоматически при старте X-сервера, обновите файл /home/user/.xinitrc:
xrdb -merge ~/.Xresources
xsetroot -cursor_name left_ptr
exec xterm -e '/bin/bash ~/rdp.sh'7. Выбор утилит для создания диалоговых окон
Помимо Whiptail, реализующей псевдо-графику также есть графические утилиты для отображения диалоговых окон: Zenity и Yad. Основной недостаток графических утилит - установка дополнительных библиотек, утяжеляющих систему. Если уж сильно хочется их использовать, то в /home/user/.xinitrcможно запускать скрипт rdp.sh без терминала xterm.
xrdb -merge ~/.Xresources
xsetroot -cursor_name left_ptr
/bin/bash ~/rdp.shАвтозагрузка графического режима
Теперь, когда графическая подсистема и RDP-клиент настроены, пора автоматизировать запуск. Чтобы при загрузке с USB-носителя система автоматически переходила в графический режим и запускала интерфейс подключения к RDP-серверу.
Для этого воспользуемся systemd — менеджером служб в Linux.
1. Создание сервиса автозапуска X-сервера
Создайте файл сервиса /etc/systemd/system/xuser@.service с содержимым:
[Unit]
Description=X11 server on %I
After=graphical.target
[Service]
User=user
PAMName=login
WorkingDirectory=~
StandardOutput=tty
StandardInput=tty-fail
ExecStart=/usr/bin/xinit -- /usr/bin/Xorg -nolisten tcp :0 vt${XDG_VTNR}
Type=simple
Restart=always
RestartSec=0
UtmpIdentifier=:0
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
IgnoreSIGPIPE=no
[Install]
WantedBy=graphical.targetПояснение ключевых параметров:
User=user— запускает сессию от имени пользователяuserExecStart=...— команда запуска X-сервераType=simple+Restart=always— гарантирует перезапуск X-сервера при падении%I— подставляет имя экземпляра (например,tty1)
2. Включение графического режима по умолчанию
По умолчанию Debian загружается в multi-user.target (консольный режим). Нам нужно переключиться на graphical.target:
root> systemctl enable graphical.target --force
root> systemctl set-default graphical.target3. Включение автозапуска X-сессии
Активируйте сервис для первой виртуальной консоли:
root> systemctl enable xuser@tty1.serviceЗа ненадобностью отключить приглашение входа getty:
root> systemctl disable getty@tty1.service4. Перезагрузка и проверка
Перезагрузите гостевую систему:
root> rebootЕсли появилось окно авторизации — значит, система готова к использованию на реальном оборудовании.
Поддержка звука
FreeRDP поддерживает передачу звука с сервера на клиент. Для этого:
На RDP-сервере с
xrdpдолжен быть установленpulseaudio-module-xrdpНа клиенте необходимо уст��новить базовую аудиосистему
Выполните в гостевой системе:
root> apt update
root> apt install -y --no-install-recommends alsa-utilsЭтого достаточно для воспроизведения звука через локальные устройства.
🔊 Важно: в среде QEMU проверить звук не удастся. Необходимо проверять на физическом оборудовании.
Сжатие образа и запись на USB-носитель
После завершения настройки системы можно создать финальный образ и записать его на USB-носитель для использования в реальных условиях. Выполняем те же действия, как и в предыдущей части. И обязательно делаем резервную копию образа.
1. Обнуление свободного места (в гостевой системе)
Чтобы добиться максимального сжатия qcow2, заполните нулями всё свободное пространство на диске:
root> dd if=/dev/zero of=/root/zero ; rm -f /root/zero ; shutdown -h now2. Сжатие образа (на хосте)
После выключения виртуальной машины выполните сжатие:
$ qemu-img convert -p -O qcow2 -c image.qcow2 new.qcow2
$ mv new.qcow2 image.qcow2Итоговый размер: 522 МБ — компактный и готовый к развёртыванию.
3. Запись на USB-носитель
Определить носитель:
$ sudo fdisk -lЗаписать на флешку /dev/sdb:
$ sudo qemu-img convert -p image.qcow2 -O raw /dev/sdbДля загрузки системы с USB-носителя необходимо в биосе компьютера отключить Secure Boot.
4. Запись на жесткий диск
Если вы хотите установить RDP-клиент на жёсткий диск вместо использования флешки:
Загрузитесь с USB
Перейдите в меню «Открыть терминал»
Выполните клонирование:
root> dd if=/dev/sda of=/dev/sdb bs=4M status=progress && syncСтарые данные на жёстком диске будут уничтожены. После этого можно извлечь флешку и загружаться напрямую с жёсткого диска.
Итог
Создан универсальный загрузочный образ RDP-клиента на базе Debian 12
Образ занимает всего 522 МБ и подходит для USB-флешек 4 ГБ
Поддерживается автоматическая загрузка, авторизация и подключение к RDP-серверу
Доступны:
Меню пользователя
Ввод логина/пароля
Выключение и доступ к терминалу
Передача звука
Перспективы развития
Для массового развёртывания можно организовать сетевую загрузку через PXE, что полностью исключит необходимость в USB-носителях. Для этого предназначен проект LTSP (Linux Terminal Server Project). Последняя версия позволяет грузить на клиентскую машину как тяжелое ядро системы, на которой установлен, так и малые образы. Предстоит развернуть систему и проверить различные варианты чтобы выбрать самый оптимальный.
