feat: add vnc-server
This commit is contained in:
parent
947cbe3ac5
commit
7bbda6140f
3 changed files with 264 additions and 0 deletions
10
Modules/System/Service/default.nix
Normal file
10
Modules/System/Service/default.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
./vnc-server.nix
|
||||
];
|
||||
}
|
||||
253
Modules/System/Service/vnc-server.nix
Normal file
253
Modules/System/Service/vnc-server.nix
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
# nyx-module/system/service/vnc.nix
|
||||
#
|
||||
# Provides:
|
||||
# - TigerVNC multi-session server as a systemd service
|
||||
# - Desktop session (.desktop file) for the chosen environment
|
||||
# - Automatic password hashing at build time (via `vncpasswd -f`)
|
||||
# - Optional firewall rule opening for chosen display port
|
||||
#
|
||||
# Options:
|
||||
# enable → Enable the VNC server service
|
||||
# user → System user that owns and runs the VNC server
|
||||
# password → Plaintext password (hashed during build)
|
||||
# displayNumber → X display number (e.g. :1 => TCP 5901)
|
||||
# openFirewall → Open firewall for the corresponding TCP port
|
||||
# session → Name of the desktop session (xfce, plasma, etc.)
|
||||
# geometry → Screen resolution (e.g. 1920x1080)
|
||||
# sessionCommand→ Command to start the X session
|
||||
#
|
||||
# Example:
|
||||
# nyx-module.system.service.vnc = {
|
||||
# enable = true;
|
||||
# user = "myuser";
|
||||
# password = "secret12";
|
||||
# session = "xfce";
|
||||
# geometry = "1280x800";
|
||||
# };
|
||||
#
|
||||
# After enabling, run:
|
||||
# sudo nixos-rebuild switch
|
||||
# sudo systemctl enable --now vncserver
|
||||
#
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib; let
|
||||
cfg = config.nyx-module.system.service.vnc;
|
||||
|
||||
# Resolve the user home safely even if the user isn't declared yet.
|
||||
userHome = lib.attrByPath ["users" "users" cfg.user "home"] "/home/${cfg.user}" config;
|
||||
|
||||
# Only generate passwd file if enabled, otherwise null
|
||||
generatedPasswdFile =
|
||||
if cfg.enable then
|
||||
pkgs.runCommand "tigervnc-passwd" {
|
||||
buildInputs = [ pkgs.tigervnc ];
|
||||
} ''
|
||||
mkdir -p $out
|
||||
echo -n "${cfg.password}" | vncpasswd -f > $out/passwd
|
||||
''
|
||||
else
|
||||
null;
|
||||
in {
|
||||
options.nyx-module.system.service.vnc = {
|
||||
enable = mkEnableOption "Enable a TigerVNC multi-session server.";
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
example = "myuser";
|
||||
description = "System user that owns and runs the VNC server.";
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = types.str;
|
||||
example = "secret12";
|
||||
description = ''
|
||||
Plaintext VNC password. Will be hashed at build time using
|
||||
`vncpasswd -f`. **Warning:** Stored in the Nix store, only
|
||||
the first 8 characters are significant.
|
||||
'';
|
||||
};
|
||||
|
||||
displayNumber = mkOption {
|
||||
type = types.int;
|
||||
default = 1;
|
||||
description = "X display number (:1 => TCP 5901).";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Open the firewall for the selected display port.";
|
||||
};
|
||||
|
||||
session = mkOption {
|
||||
type = types.str;
|
||||
default = "xfce";
|
||||
example = "plasma";
|
||||
description = "Name of the desktop session (matches .desktop file).";
|
||||
};
|
||||
|
||||
geometry = mkOption {
|
||||
type = types.str;
|
||||
default = "1920x1080";
|
||||
description = "Default VNC display resolution.";
|
||||
};
|
||||
|
||||
sessionCommand = mkOption {
|
||||
type = types.str;
|
||||
default = "${pkgs.xterm}/bin/xterm";
|
||||
example = "${pkgs.xfce4-session}/bin/startxfce4";
|
||||
description = "Command to start the X session.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Install required packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
tigervnc
|
||||
xorg.xauth
|
||||
xorg.xinit
|
||||
];
|
||||
|
||||
# Enable X server and desktop environment
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
desktopManager.xfce.enable = true;
|
||||
xkb.layout = "de";
|
||||
displayManager.defaultSession = cfg.session; # fixed option path
|
||||
};
|
||||
|
||||
# Configure session
|
||||
services.xserver.displayManager.session = [
|
||||
{
|
||||
manage = "desktop";
|
||||
name = cfg.session;
|
||||
start = ''
|
||||
${cfg.sessionCommand} &
|
||||
waitPID=$!
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# Install a custom .desktop file for session
|
||||
environment.etc."xdg/xsessions/${cfg.session}.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Name=${cfg.session}
|
||||
Comment=Custom ${cfg.session} session for VNC
|
||||
Exec=${cfg.sessionCommand}
|
||||
Type=Application
|
||||
'';
|
||||
|
||||
system.activationScripts.linkCustomSession = ''
|
||||
mkdir -p /usr/share/xsessions
|
||||
ln -sf /etc/xdg/xsessions/${cfg.session}.desktop \
|
||||
/usr/share/xsessions/${cfg.session}.desktop
|
||||
'';
|
||||
|
||||
# Systemd service for VNC server
|
||||
systemd.services.vncserver = {
|
||||
description = "TigerVNC server on :${toString cfg.displayNumber}";
|
||||
after = ["network.target" "syslog.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = cfg.user;
|
||||
TimeoutStartSec = "60s";
|
||||
WorkingDirectory = userHome;
|
||||
PIDFile = "${userHome}/.vnc/%H:${toString cfg.displayNumber}.pid";
|
||||
|
||||
Environment = "PATH=${pkgs.xorg.xinit}/bin:${pkgs.tigervnc}/bin:${pkgs.xorg.xauth}/bin:/run/current-system/sw/bin";
|
||||
|
||||
ExecStartPre = pkgs.writeShellScript "prepare-vnc" ''
|
||||
mkdir -p ${userHome}/.vnc
|
||||
cp ${generatedPasswdFile}/passwd ${userHome}/.vnc/passwd
|
||||
chmod 600 ${userHome}/.vnc/passwd
|
||||
chown ${cfg.user}:users ${userHome}/.vnc/passwd
|
||||
|
||||
mkdir -p ${userHome}/.config/tigervnc
|
||||
cat > ${userHome}/.config/tigervnc/config <<EOF
|
||||
session=${cfg.session}
|
||||
geometry=${cfg.geometry}
|
||||
alwaysshared
|
||||
rfbauth=${userHome}/.vnc/passwd
|
||||
EOF
|
||||
|
||||
# Minimal xstartup with logging
|
||||
cat > ${userHome}/.vnc/xstartup <<'EOF'
|
||||
#!/bin/sh
|
||||
|
||||
export DISPLAY=:${toString cfg.displayNumber}
|
||||
export XAUTHORITY="$HOME/.Xauthority"
|
||||
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
|
||||
export XKL_XMODMAP_DISABLE=1
|
||||
export GTK_USE_PORTAL=0
|
||||
export PULSE_SERVER=unix:/run/user/$(id -u)/pulse/native
|
||||
export PULSE_SERVER=tcp:localhost:4714
|
||||
# Log:
|
||||
echo "=== Starting VNC session on $(date) ===" >> "$HOME/.vnc/xstartup.log" 2>&1
|
||||
|
||||
# Load user profile to get PATH, XDG vars, etc.
|
||||
if [ -f /etc/profile ]; then
|
||||
. /etc/profile
|
||||
fi
|
||||
|
||||
# Source NixOS user environment
|
||||
if [ -f "$HOME/.nix-profile/etc/profile.d/nix.sh" ]; then
|
||||
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
|
||||
fi
|
||||
|
||||
export XDG_SESSION_TYPE=x11
|
||||
export XDG_CURRENT_DESKTOP=XFCE
|
||||
export XDG_CONFIG_HOME="$HOME/.config"
|
||||
|
||||
${cfg.sessionCommand} >> "$HOME/.vnc/xstartup.log" 2>&1 &
|
||||
|
||||
wait $!
|
||||
EOF
|
||||
|
||||
chmod +x ${userHome}/.vnc/xstartup
|
||||
chown ${cfg.user}:users ${userHome}/.vnc/xstartup
|
||||
touch ${userHome}/.vnc/xstartup.log
|
||||
chown ${cfg.user}:users ${userHome}/.vnc/xstartup.log
|
||||
chmod 600 ${userHome}/.vnc/xstartup.log
|
||||
'';
|
||||
|
||||
ExecStart = "${pkgs.tigervnc}/bin/vncserver :${toString cfg.displayNumber}";
|
||||
ExecStop = "${pkgs.procps}/bin/pkill -f 'Xvnc :${toString cfg.displayNumber}' || true";
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."X11/Xsession" = {
|
||||
text = ''
|
||||
#!/bin/sh
|
||||
LOGFILE="$HOME/.vnc/xsession.log"
|
||||
mkdir -p "$HOME/.vnc"
|
||||
touch "$LOGFILE"
|
||||
chmod 600 "$LOGFILE"
|
||||
|
||||
echo "=== Xsession started on $(date) ===" >> "$LOGFILE" 2>&1
|
||||
|
||||
if [ -x "$HOME/.vnc/xstartup" ]; then
|
||||
echo "Found xstartup, executing..." >> "$LOGFILE" 2>&1
|
||||
exec "$HOME/.vnc/xstartup" >> "$LOGFILE" 2>&1
|
||||
else
|
||||
echo "No ~/.vnc/xstartup found, cannot start session." >> "$LOGFILE" 2>&1
|
||||
echo "No ~/.vnc/xstartup found, cannot start session." >&2
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
mode = "0755";
|
||||
};
|
||||
|
||||
# Optionally open firewall
|
||||
networking.firewall.allowedTCPPorts = mkIf cfg.openFirewall [
|
||||
(5900 + cfg.displayNumber)
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
imports = [
|
||||
./Application
|
||||
./Programming-Tools
|
||||
./Service
|
||||
];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue