Move KDE desktop to host; container becomes noVNC proxy only

The vnc-desktop container no longer runs a desktop environment. KDE Plasma
and Xvnc now run directly on the host via a vnc-kde systemd service, with
port 5901 firewalled to the podman bridge subnet only. The container is
reduced to a websockify bridge forwarding the noVNC web UI to hetzner-host:5901.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Philip Peterson 2026-06-01 03:13:20 -07:00
parent de07e62e8e
commit 097e3a312f
4 changed files with 58 additions and 43 deletions

View file

@ -20,5 +20,6 @@
networking.firewall.extraCommands = '' networking.firewall.extraCommands = ''
iptables -I nixos-fw -s 10.89.0.0/16 -p udp --dport 53 -j nixos-fw-accept iptables -I nixos-fw -s 10.89.0.0/16 -p udp --dport 53 -j nixos-fw-accept
iptables -I nixos-fw -s 10.89.0.0/16 -p tcp --dport 53 -j nixos-fw-accept iptables -I nixos-fw -s 10.89.0.0/16 -p tcp --dport 53 -j nixos-fw-accept
iptables -I nixos-fw -s 10.89.0.0/16 -p tcp --dport 5901 -j nixos-fw-accept
''; '';
} }

View file

@ -102,6 +102,61 @@ in {
} }
]; ];
# KDE Plasma on the host — the noVNC container (vnc-desktop) is a thin WebSocket
# proxy that connects to the VNC server started here.
services.xserver = {
enable = true;
desktopManager.plasma5.enable = true;
};
# Don't start X via a display manager; the vnc-kde service owns the session.
services.displayManager.sddm.enable = lib.mkForce false;
systemd.services.vnc-kde = {
description = "KDE Plasma desktop accessible over VNC";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" "agenix.service" ];
path = with pkgs; [
tigervnc
dbus
xorg.xauth
plasma5Packages.plasma-workspace
coreutils
gnugrep
];
serviceConfig = {
Type = "simple";
User = "root";
Restart = "on-failure";
RestartSec = "5s";
TasksMax = "infinity";
ExecStart = pkgs.writeShellScript "vnc-kde-start" ''
set -e
rm -f /tmp/.X1-lock /tmp/.X11-unix/X1
mkdir -p /root/.vnc
VNC_PASSWORD=$(grep '^VNC_PASSWORD=' /run/agenix/vnc-password | cut -d= -f2-)
printf '%s' "$VNC_PASSWORD" | vncpasswd -f > /root/.vnc/passwd
chmod 600 /root/.vnc/passwd
Xvnc :1 \
-rfbport 5901 \
-SecurityTypes VncAuth \
-PasswordFile /root/.vnc/passwd \
-geometry 1920x1080 \
-depth 24 \
-AlwaysShared &
export DISPLAY=:1
sleep 2
exec dbus-run-session -- startplasma-x11
'';
};
};
virtualisation.arion = { virtualisation.arion = {
backend = "podman-socket"; backend = "podman-socket";
projects.forgejo.settings = import ./arion/arion-compose.nix; projects.forgejo.settings = import ./arion/arion-compose.nix;

View file

@ -3,25 +3,10 @@ FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
tigervnc-standalone-server \
tigervnc-common \
novnc \ novnc \
python3-websockify \ python3-websockify \
kde-plasma-desktop \
konsole \
x11-utils \
xfonts-base \
dbus-x11 \
openssh-client \
curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Remove Bluetooth stack — obexd gets activated in a tight loop by kded5
# inside the container (no BT hardware), which exhausts the process limit.
RUN apt-get purge -y --auto-remove bluez bluez-obexd 2>/dev/null || true; \
rm -f /usr/share/dbus-1/services/org.bluez.obex.service \
/usr/share/dbus-1/system-services/org.bluez.service
COPY start.sh /start.sh COPY start.sh /start.sh
RUN chmod +x /start.sh RUN chmod +x /start.sh

View file

@ -1,31 +1,5 @@
#!/bin/bash #!/bin/bash
set -e set -e
mkdir -p /root/.vnc /root/.ssh # Proxy WebSocket (6080) → VNC server running on the host (hetzner-host:5901)
chmod 700 /root/.ssh exec websockify --web /usr/share/novnc 6080 hetzner-host:5901
# Clean up stale X lock files from previous container runs
rm -f /tmp/.X1-lock /tmp/.X11-unix/X1
# Set VNC password from environment
echo "${VNC_PASSWORD:?VNC_PASSWORD must be set}" | vncpasswd -f > /root/.vnc/passwd
chmod 600 /root/.vnc/passwd
# Start Xvnc (headless X server + VNC server in one)
Xvnc :1 \
-rfbport 5901 \
-SecurityTypes VncAuth \
-PasswordFile /root/.vnc/passwd \
-geometry 1920x1080 \
-depth 24 \
-AlwaysShared \
&
export DISPLAY=:1
sleep 2
# Start KDE Plasma session
dbus-run-session -- startplasma-x11 &
# Serve noVNC web UI + bridge WebSocket -> VNC
exec websockify --web /usr/share/novnc 6080 localhost:5901