diff --git a/nixos/firewall.nix b/nixos/firewall.nix index aeb679b..1cd237f 100644 --- a/nixos/firewall.nix +++ b/nixos/firewall.nix @@ -20,5 +20,6 @@ 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 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 ''; } diff --git a/nixos/linux.nix b/nixos/linux.nix index 752c904..5117244 100644 --- a/nixos/linux.nix +++ b/nixos/linux.nix @@ -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 = { backend = "podman-socket"; projects.forgejo.settings = import ./arion/arion-compose.nix; diff --git a/nixos/vnc-desktop/Dockerfile b/nixos/vnc-desktop/Dockerfile index 5060336..2686190 100644 --- a/nixos/vnc-desktop/Dockerfile +++ b/nixos/vnc-desktop/Dockerfile @@ -3,25 +3,10 @@ FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install -y \ - tigervnc-standalone-server \ - tigervnc-common \ novnc \ python3-websockify \ - kde-plasma-desktop \ - konsole \ - x11-utils \ - xfonts-base \ - dbus-x11 \ - openssh-client \ - curl \ && 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 RUN chmod +x /start.sh diff --git a/nixos/vnc-desktop/start.sh b/nixos/vnc-desktop/start.sh index 3153ccc..9ec4aaf 100644 --- a/nixos/vnc-desktop/start.sh +++ b/nixos/vnc-desktop/start.sh @@ -1,31 +1,5 @@ #!/bin/bash set -e -mkdir -p /root/.vnc /root/.ssh -chmod 700 /root/.ssh - -# 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 +# Proxy WebSocket (6080) → VNC server running on the host (hetzner-host:5901) +exec websockify --web /usr/share/novnc 6080 hetzner-host:5901