Skip to content

Instantly share code, notes, and snippets.

@tarruda
Last active April 8, 2024 23:13
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tarruda/25bca9aa192a2a9ee690054c0b23aa08 to your computer and use it in GitHub Desktop.
Save tarruda/25bca9aa192a2a9ee690054c0b23aa08 to your computer and use it in GitHub Desktop.
LXD: Full Debian KDE desktop

Intro

This script will create a local LXD image that has a full KDE desktop environment with Xspice as the display server.

Instructions

./setup-debian-kde-desktop-xspice.sh    
lxc init debian-kde-desktop-xspice kde
lxc config device add kde xspicesocket proxy bind=host listen=unix:/tmp/kde.unix connect=unix:/run/xspice/spice.unix uid=1000 gid=1000
lxc start kde
remote-viewer spice+unix:///tmp/kde.unix
#!/bin/bash
set -eu -o pipefail
new_image_name=debian-kde-desktop-xspice
help() {
echo "Create new instance with something like:"
echo "\"lxc init $new_image_name kde\""
echo "\"lxc config device add kde xspicesocket proxy bind=host listen=unix:/tmp/kde.unix connect=unix:/run/xspice/spice.unix uid=1000 gid=1000\""
echo "\"lxc start kde\""
echo "Connect virt-viewer with:"
echo "\"remote-viewer spice+unix:///tmp/kde.unix\""
}
if lxc image info local:$new_image_name &> /dev/null; then
help
exit
fi
BASE_IMAGE_NAME=images:debian/bullseye
USERNAME=debian
GECOS="Debian User"
initial_dir=$(pwd)
tmpdir=$(mktemp -d /tmp/imgbuildXXXXXXX)
echo $tmpdir
cd $tmpdir
instance_name=$(basename $tmpdir)
cleanup() {
cd $initial_dir
rm -rfv $tmpdir
lxc stop $instance_name &> /dev/null || true
lxc delete $instance_name
}
trap cleanup EXIT TERM INT
# first we create an instance for building the required patched binaries
lxc launch $BASE_IMAGE_NAME $instance_name
# patch logind to allow creating a session on seat0 without a real vt
cat > f << "EOF"
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c
index d85f897..34b743a 100644
--- a/src/login/logind-dbus.c
+++ b/src/login/logind-dbus.c
@@ -768,6 +768,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
"Console TTY specified but VT number is not 0");
}
+ vtnr = 0;
if (seat) {
if (seat_has_vts(seat)) {
if (vtnr <= 0 || vtnr > 63)
EOF
lxc file push f $instance_name/systemd.diff
# fix a bug in spice-vdagentd where it doesn't recognize messages for resizing monitor
cat > f << "EOF"
diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c
index 3e59331..1a16968 100644
--- a/src/vdagentd/vdagentd.c
+++ b/src/vdagentd/vdagentd.c
@@ -208,7 +208,7 @@ static void do_client_monitors(VirtioPort *vport, int port_nr,
/* Store monitor config to send to agents when they connect */
size = sizeof(VDAgentMonitorsConfig) +
new_monitors->num_of_monitors * sizeof(VDAgentMonConfig);
- if (message_header->size != size) {
+ if (message_header->size < size) {
syslog(LOG_ERR, "invalid message size for VDAgentMonitorsConfig");
return;
}
EOF
lxc file push f $instance_name/vdagent.diff
# patch xserver-xspice to support unix socket as the listen address
cat > f << "EOF"
diff --git a/src/spiceqxl_spice_server.c b/src/spiceqxl_spice_server.c
index 1a138b5..465ec48 100644
--- a/src/spiceqxl_spice_server.c
+++ b/src/spiceqxl_spice_server.c
@@ -222,7 +222,9 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
}
addr_flags = 0;
- if (ipv4) {
+ if (addr && addr[0] == '/') {
+ addr_flags |= SPICE_ADDR_FLAG_UNIX_ONLY;
+ } else if (ipv4) {
addr_flags |= SPICE_ADDR_FLAG_IPV4_ONLY;
} else if (ipv6) {
addr_flags |= SPICE_ADDR_FLAG_IPV6_ONLY;
EOF
lxc file push f $instance_name/xspice.diff
# install build dependencies and setup an user to build packages
lxc exec $instance_name -- bash << EOF
sed -n -e 'p;s/^deb\b/deb-src/p' -i /etc/apt/sources.list
export DEBIAN_FRONTEND=noninteractive
echo waiting for network configuration...
sleep 5
apt update
apt upgrade -y
apt build-dep -y systemd spice-vdagent xserver-xspice
apt install -y fakeroot
adduser --disabled-password --gecos "$GECOS" $USERNAME
mkdir -p /output
chown 1000:1000 /output
EOF
# patch and build packages
lxc exec $instance_name -- su $USERNAME << "EOF"
cd
apt source systemd spice-vdagent xserver-xspice
cd systemd-*
patch -p1 < /systemd.diff
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -b -uc -us
cp -v debian/systemd/lib/systemd/systemd-logind /output
cd
cd spice-vdagent-*
patch -p1 < /vdagent.diff
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -b -uc -us
cp -v debian/spice-vdagent/usr/sbin/spice-vdagentd /output
cd
cd xserver-xorg-video-qxl-*
patch -p1 < /xspice.diff
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -b -uc -us
cp -v debian/xserver-xspice/usr/lib/xorg/modules/drivers/spiceqxl_drv.so /output
EOF
# copy patched binaries
lxc file pull $instance_name/output/systemd-logind .
lxc file pull $instance_name/output/spice-vdagentd .
lxc file pull $instance_name/output/spiceqxl_drv.so .
# delete temp image
lxc stop $instance_name
lxc delete $instance_name
# create a new one where we will build the final image
lxc launch $BASE_IMAGE_NAME $instance_name
lxc exec $instance_name bash << EOF
export DEBIAN_FRONTEND=noninteractive
echo waiting for network configuration...
sleep 5
apt update && apt upgrade -y
apt install -y bash-completion
# divert binaries that will be replaced
dpkg-divert --divert /usr/bin/Xorg.real --rename /usr/bin/Xorg
dpkg-divert --divert /usr/sbin/spice-vdagentd.real --rename /usr/sbin/spice-vdagentd
dpkg-divert --divert /usr/lib/systemd/systemd-logind.real --rename /usr/lib/systemd/systemd-logind
dpkg-divert --divert /usr/lib/xorg/modules/drivers/spiceqxl_drv.so.real --rename /usr/lib/xorg/modules/drivers/spiceqxl_drv.so
adduser --disabled-password --gecos "$GECOS" $USERNAME
usermod -aG sudo $USERNAME
passwd -de $USERNAME
# create xorg drivers directory
mkdir -pv /usr/lib/xorg/modules/drivers
EOF
lxc file push systemd-logind $instance_name/usr/lib/systemd/systemd-logind
lxc file push spice-vdagentd $instance_name/usr/sbin/spice-vdagentd
lxc file push spiceqxl_drv.so $instance_name/usr/lib/xorg/modules/drivers/spiceqxl_drv.so
# Setup xspice and vdagent on the image
lxc exec $instance_name bash << "EOFF"
cat > /etc/tmpfiles.d/xspice.conf << "EOF"
d /run/xspice/audio 777 root root -
EOF
mkdir -pv /etc/pulse/default.pa.d
cat > /etc/pulse/default.pa.d/99-xspice.pa << "EOF"
load-module module-pipe-sink file=/run/xspice/audio/pulse.output
EOF
cat > /etc/systemd/system/spice-vdagent.path << "EOF"
[Unit]
Description=Start Spice vdagentd
[Path]
PathExists=/run/xspice/uinput
PathExists=/run/xspice/virtio
[Install]
WantedBy=graphical.target
EOF
cat > /etc/systemd/system/spice-vdagent.service << "EOF"
[Unit]
Description=Start Spice vdagentd
[Service]
ExecStart=/usr/sbin/spice-vdagentd -f -x -S /run/xspice/udcs -s /run/xspice/virtio -u /run/xspice/uinput
EOF
mkdir -pv /etc/xdg/autostart
cat > /etc/xdg/autostart/spice-vdagent-lxd.desktop << "EOF"
[Desktop Entry]
Name=Spice vdagent (LXD)
Comment=Agent for Xspice guests
Exec=/usr/bin/spice-vdagent -s /run/xspice/virtio -S /run/xspice/udcs
Terminal=false
Type=Application
X-GNOME-Autostart-Phase=WindowManager
NoDisplay=true
EOF
mkdir -pv /etc/lightdm/lightdm.conf.d
cat > /etc/lightdm/lightdm.conf.d/99-xspice.conf << "EOF"
[Seat:*]
greeter-hide-users=false
EOF
mkdir -pv /etc/X11
cat > /etc/X11/xspice.xorg.conf << "EOF"
Section "Device"
Identifier "XSPICE"
Driver "spiceqxl"
Option "SpiceDisableTicketing" "True"
Option "SpiceAddr" "/run/xspice/spice.unix"
Option "NumHeads" "1"
Option "EnableImageCache" "True"
Option "EnableFallbackCache" "True"
Option "EnableSurfaces" "True"
Option "SurfaceBufferSize" "128"
Option "CommandBufferSize" "128"
Option "FrameBufferSize" "16"
Option "SpiceVdagentEnabled" "True"
Option "SpiceVdagentVirtioPath" "/run/xspice/virtio"
Option "SpiceVdagentUinputPath" "/run/xspice/uinput"
Option "SpicePlaybackFIFODir" "/run/xspice/audio"
EndSection
Section "InputDevice"
Identifier "XSPICE POINTER"
Driver "xspice pointer"
EndSection
Section "InputDevice"
Identifier "XSPICE KEYBOARD"
Driver "xspice keyboard"
EndSection
Section "Monitor"
Identifier "Configured Monitor"
EndSection
Section "Screen"
Identifier "XSPICE Screen"
Monitor "Configured Monitor"
Device "XSPICE"
DefaultDepth 24
EndSection
Section "ServerLayout"
Identifier "XSPICE Example"
Screen "XSPICE Screen"
InputDevice "XSPICE KEYBOARD"
InputDevice "XSPICE POINTER"
EndSection
# Prevent udev from loading vmmouse in a vm and crashing.
Section "ServerFlags"
Option "AutoAddDevices" "False"
EndSection
EOF
cat > /usr/bin/Xorg << "EOF"
#!/bin/sh
filtered_xorg_args="$(echo $* | sed -e 's/vt[0-9]//' -e 's/.novtswitch//' -e 's/.core//')"
exec /usr/lib/xorg/Xorg -config /etc/X11/xspice.xorg.conf -noreset $filtered_xorg_args
EOF
chmod +x /usr/bin/Xorg
export DEBIAN_FRONTEND=noninteractive
apt install -y xserver-xspice spice-vdagent pulseaudio
systemctl enable spice-vdagent.path
if ! grep -q 'default\.pa\.d' < /etc/pulse/default.pa; then
cat >> /etc/pulse/default.pa <<- "EOF"
.nofail
.include /etc/pulse/default.pa.d
EOF
fi
EOFF
# setup KDE, need to hold sddm since it only works if patched
lxc exec $instance_name bash << "EOF"
apt-mark hold sddm
apt install -y kde-full lightdm firefox-esr
EOF
lxc stop $instance_name
lxc publish $instance_name --alias=$new_image_name
help
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment