From 19b9844881c034e19e11ada720ecc0b63275f042 Mon Sep 17 00:00:00 2001 From: Philip Peterson <1326208+philip-peterson@users.noreply.github.com> Date: Wed, 10 Jun 2026 13:58:17 -0700 Subject: [PATCH] Replace vnc-desktop container with native novnc service, add claw.quineglobal.com Co-Authored-By: Claude Sonnet 4.6 --- nixos/firewall.nix | 1 - nixos/linux.nix | 52 ++++++++++------------------------------------ nixos/nginx.nix | 16 ++++++++++++++ 3 files changed, 27 insertions(+), 42 deletions(-) diff --git a/nixos/firewall.nix b/nixos/firewall.nix index 1cd237f..aeb679b 100644 --- a/nixos/firewall.nix +++ b/nixos/firewall.nix @@ -20,6 +20,5 @@ 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 0c50b22..32c1865 100644 --- a/nixos/linux.nix +++ b/nixos/linux.nix @@ -18,8 +18,6 @@ nixPkgs = specialArgs.nixPkgs; ourRustVersion = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.complete); - vncContext = builtins.path { path = ./vnc-desktop; name = "vnc-desktop-context"; }; - ourRustPlatform = nixPkgs.makeRustPlatform { rustc = ourRustVersion; cargo = ourRustVersion; @@ -114,8 +112,8 @@ in { } ]; - # KDE Plasma on the host — the noVNC container (vnc-desktop) is a thin WebSocket - # proxy that connects to the VNC server started here. + # KDE Plasma on the host — the novnc systemd service (websockify) proxies + # WebSocket traffic from nginx to the VNC server started here. services.xserver = { enable = true; desktopManager.plasma5.enable = true; @@ -187,35 +185,18 @@ in { systemd.services.arion-paperless.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; systemd.services.arion-openclaw.environment.DOCKER_HOST = "unix:///run/podman/podman.sock"; - # Build the VNC desktop image locally from the Dockerfile — no registry push/pull needed. - # vncContext is a Nix store path that changes whenever any file under vnc-desktop/ changes, - # which causes build-vnc-image to re-run and podman-vnc-desktop to restart on nixos-rebuild. - systemd.services.build-vnc-image = { - description = "Build VNC desktop container image from Dockerfile"; - wantedBy = [ "podman-vnc-desktop.service" ]; - before = [ "podman-vnc-desktop.service" ]; + systemd.services.novnc = { + description = "noVNC WebSocket proxy for VNC desktop"; + wantedBy = [ "multi-user.target" ]; + after = [ "vnc-kde.service" "network.target" ]; serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = pkgs.writeShellScript "build-vnc-image" '' - STAMP=/var/lib/build-vnc-image/context-hash - EXPECTED="${vncContext}" - if [ -f "$STAMP" ] && [ "$(cat "$STAMP")" = "$EXPECTED" ]; then - echo "VNC image is up to date, skipping build" - exit 0 - fi - echo "Building VNC desktop image..." - ${pkgs.podman}/bin/podman build \ - -t forge.quinefoundation.com/ironmagma/vnc-desktop:latest \ - ${vncContext} - mkdir -p "$(dirname "$STAMP")" - echo "$EXPECTED" > "$STAMP" - ''; + Type = "simple"; + Restart = "on-failure"; + RestartSec = "3s"; + ExecStart = "${pkgs.python3Packages.websockify}/bin/websockify --web ${pkgs.novnc}/share/webapps/novnc 127.0.0.1:6080 localhost:5901"; }; }; - systemd.services.podman-vnc-desktop.restartTriggers = [ "${vncContext}" ]; - services.gitea-actions-runner.instances."ubuntu" = { enable = true; name = "ubuntu"; @@ -310,18 +291,6 @@ in { # ports = ["8081:80"]; # }; - "vnc-desktop" = { - autoStart = true; - image = "forge.quinefoundation.com/ironmagma/vnc-desktop:latest"; - environmentFiles = [ config.age.secrets.vnc-password.path ]; - volumes = [ "/root/.ssh:/root/host-ssh:ro" ]; - ports = [ "127.0.0.1:6080:6080" ]; - extraOptions = [ - "--add-host=hetzner-host:host-gateway" - "--pids-limit=-1" - ]; - }; - "navidrome" = { autoStart = true; environment = { @@ -482,6 +451,7 @@ in { "acme-selfsigned-www.philippeterson.com.service" "acme-selfsigned-riverside.coldairnetworks.com.service" "acme-selfsigned-vnc.quinefoundation.com.service" + "acme-selfsigned-claw.quineglobal.com.service" "acme-selfsigned-webdav.philippeterson.com.service" "acme-selfsigned-pluto.philippeterson.com.service" "acme-selfsigned-paperless.philippeterson.com.service" diff --git a/nixos/nginx.nix b/nixos/nginx.nix index a570b1f..bfa058f 100644 --- a/nixos/nginx.nix +++ b/nixos/nginx.nix @@ -52,6 +52,22 @@ }; }; + "claw.quineglobal.com" = { + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyPass = "http://127.0.0.1:4310/"; + extraConfig = '' + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_read_timeout 86400; + ''; + }; + }; + "hyper.quineglobal.com" = { enableACME = true; forceSSL = false;