Графическое исполнение.
См. Часть 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 update
1. Установка и настройка 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-openbsd
RDP по умолчанию использует порт 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> reboot
2. Тестирование графического режима
Ниже — несколько способов запуска и отладки 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: true
2. Автозапуск графической среды .xinitrc
Файл /home/user/.xinitrc
определяет, что запускается при старте X-сервера.
# Загрузить пользовательские настройки из .Xresources
xrdb -merge ~/.Xresources
# Установить стандартный курсор (стрелка)
xsetroot -cursor_name left_ptr
# Запустить xterm вместе с Midnight Commander
exec xterm -e mc
3. Настройка приглашения командной строки
Для удобства измените приглашение в терминале. В конце файла /home/user/.bashrc
необходимо добавить:
PS1='user> '
Теперь приглашение будет выглядеть как:
user>
4. Права доступа к файлам
Чтобы пользователь user
владел своими файлами:
root> chown -R user:user /home/user
5. Тестирование графического режима
Теперь можно запустить 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.usr
5: Графическое меню с 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
— запускает сессию от имени пользователяuser
ExecStart=...
— команда запуска 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.target
3. Включение автозапуска X-сессии
Активируйте сервис для первой виртуальной консоли:
root> systemctl enable xuser@tty1.service
За ненадобностью отключить приглашение входа getty
:
root> systemctl disable getty@tty1.service
4. Перезагрузка и проверка
Перезагрузите гостевую систему:
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 now
2. Сжатие образа (на хосте)
После выключения виртуальной машины выполните сжатие:
$ 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). Последняя версия позволяет грузить на клиентскую машину как тяжелое ядро системы, на которой установлен, так и малые образы. Предстоит развернуть систему и проверить различные варианты чтобы выбрать самый оптимальный.