diff --git a/nixos/arion-vnc/arion-compose.nix b/nixos/arion-vnc/arion-compose.nix new file mode 100644 index 0000000..35ba1bf --- /dev/null +++ b/nixos/arion-vnc/arion-compose.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: +{ + project.name = "vnc-desktop"; + + services.vnc = { + service = { + image = "forge.quinefoundation.com/ironmagma/vnc-desktop:latest"; + container_name = "vnc-desktop"; + restart = "unless-stopped"; + env_file = [ "/run/agenix/vnc-password" ]; + volumes = [ + "/root/.ssh:/root/host-ssh:ro" + ]; + extra_hosts = [ "hetzner-host:host-gateway" ]; + ports = [ "127.0.0.1:6080:6080" ]; + }; + }; +} diff --git a/nixos/arion-vnc/arion-pkgs.nix b/nixos/arion-vnc/arion-pkgs.nix new file mode 100644 index 0000000..1d16305 --- /dev/null +++ b/nixos/arion-vnc/arion-pkgs.nix @@ -0,0 +1,3 @@ +import { + system = "x86_64-linux"; +} diff --git a/nixos/linux.nix b/nixos/linux.nix index fd156ba..f356fc4 100644 --- a/nixos/linux.nix +++ b/nixos/linux.nix @@ -66,6 +66,16 @@ in { file = ./secrets/forgejo-runner-token.age; owner = "root"; }; + + vnc-password = { + file = ./secrets/vnc-password.age; + owner = "root"; + }; + + vnc-htpasswd = { + file = ./secrets/vnc-htpasswd.age; + owner = "nginx"; + }; }; environment.systemPackages = [ @@ -93,9 +103,10 @@ in { ]; virtualisation.arion = { - backend = "docker"; + backend = "podman"; projects.forgejo.settings = import ./arion/arion-compose.nix; projects.riverside.settings = import ./arion-riverside/arion-compose.nix; + projects.vnc-desktop.settings = import ./arion-vnc/arion-compose.nix; }; services.gitea-actions-runner.instances."ubuntu" = { diff --git a/nixos/nginx.nix b/nixos/nginx.nix index 687ddd9..dbd072e 100644 --- a/nixos/nginx.nix +++ b/nixos/nginx.nix @@ -200,6 +200,23 @@ }; }; + "vnc.quinefoundation.com" = { + enableACME = true; + forceSSL = true; + basicAuthFile = config.age.secrets.vnc-htpasswd.path; + + locations."/" = { + proxyPass = "http://127.0.0.1:6080/"; + 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; + ''; + }; + }; + "forge.quinefoundation.com-https" = { serverName = "forge.quinefoundation.com"; enableACME = true; diff --git a/nixos/secrets/default.nix b/nixos/secrets/default.nix index 974a585..907d6fa 100644 --- a/nixos/secrets/default.nix +++ b/nixos/secrets/default.nix @@ -17,4 +17,11 @@ in { # TOKEN= "./forgejo-runner-token.age".publicKeys = [mainframePublicKey]; + + # VNC_PASSWORD= + "./vnc-password.age".publicKeys = [mainframePublicKey]; + + # htpasswd-format credentials for nginx basic auth on vnc.quinefoundation.com + # Generate with: htpasswd -n + "./vnc-htpasswd.age".publicKeys = [mainframePublicKey]; } diff --git a/nixos/vnc-desktop/Dockerfile b/nixos/vnc-desktop/Dockerfile new file mode 100644 index 0000000..9103611 --- /dev/null +++ b/nixos/vnc-desktop/Dockerfile @@ -0,0 +1,23 @@ +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y \ + tigervnc-standalone-server \ + tigervnc-common \ + novnc \ + python3-websockify \ + openbox \ + xterm \ + x11-utils \ + xfonts-base \ + dbus-x11 \ + openssh-client \ + && rm -rf /var/lib/apt/lists/* + +COPY start.sh /start.sh +RUN chmod +x /start.sh + +EXPOSE 6080 + +CMD ["/start.sh"] diff --git a/nixos/vnc-desktop/start.sh b/nixos/vnc-desktop/start.sh new file mode 100644 index 0000000..b8be64c --- /dev/null +++ b/nixos/vnc-desktop/start.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +mkdir -p /root/.vnc /root/.ssh +chmod 700 /root/.ssh + +# 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 1280x800 \ + -depth 24 \ + -AlwaysShared \ + & + +export DISPLAY=:1 +sleep 2 + +# Start window manager and initial terminal +openbox-session & +xterm & + +# Serve noVNC web UI + bridge WebSocket -> VNC +exec websockify --web /usr/share/novnc 6080 localhost:5901