Files
komorebi/nix/linux/dev/krdp.nix
T
LGUG2Z f01853ceca refactor(repo): move the KDE and macOS nix files under nix/ (pure move)
komorebi-for-kde/nix/ -> nix/linux/
komorebi-for-mac/nix/ -> nix/macos/

The nix expressions of the platforms (modules, option files, VM test suites, kwin effects,
the darwin module) sit next to the existing nix/workspace-src.nix. Renames only (252
files); the flakes that import them are replaced by one root flake later in this stack, so
nix does not evaluate at this revision.
2026-11-05 15:03:27 -08:00

108 lines
4.3 KiB
Nix

# KRDP, Plasma's RDP server, in the Plasma session of every user who logs in. The session guest
# of plasma-vm.nix enables it, and so does the VM suite `rdp`, which checks that a client can log
# in and get a picture of the desktop (docs/dev/PLATFORM.md says what it does not check).
#
# The password is not in the repository: the unit starts once the user has written one to
# ~/.config/komorebi-vm/rdp-password, and a client logs in with the user's name and that password.
# A guest whose password comes from outside, as the demo guest's does (run-kde.nix), names a file
# of the guest in `passwordFile`, which the unit reads in place of that one when it is there.
{
config,
lib,
pkgs,
...
}:
let
cfg = config.komorebi.krdp;
# KRDP asks for the H.264 Constrained Baseline profile and nothing else. A guest whose VA-API
# drives the host's encoder (virgl, with the QEMU of run-kde.nix) lists Main and High and no
# Constrained Baseline, so ffmpeg's h264_vaapi finds no profile it can use and KRDP encodes on
# the CPUs. Main is in RDP's H.264 mode as well, and the software encoder takes it too.
krdp = pkgs.kdePackages.krdp.overrideAttrs (old: {
postPatch = (old.postPatch or "") + ''
substituteInPlace src/VideoStreamSurface.cpp --replace-fail H264Baseline H264Main
'';
});
startKrdp = pkgs.writeShellScript "krdp-start" ''
set -eu
dir=$HOME/.config/komorebi-vm
password_file=$dir/rdp-password
${lib.optionalString (cfg.passwordFile != null) ''
if [ -r ${lib.escapeShellArg cfg.passwordFile} ]; then
password_file=${lib.escapeShellArg cfg.passwordFile}
fi
''}
mkdir -p "$dir"
# krdpserver refuses to run without a TLS certificate and key (its --help promises a temporary
# one, but it only checks that the files exist), so make a throwaway self-signed pair
if [ ! -f "$dir/rdp.crt" ] || [ ! -f "$dir/rdp.key" ]; then
${pkgs.openssl}/bin/openssl req -x509 -newkey rsa:2048 -nodes -days 3650 -subj /CN=komorebi-vm \
-addext subjectAltName=DNS:localhost,IP:127.0.0.1 -keyout "$dir/rdp.key" -out "$dir/rdp.crt"
chmod 600 "$dir/rdp.key"
fi
# --plasma asks KWin for the screen and for input directly, with no portal prompt to click
exec ${krdp}/bin/krdpserver --plasma --address 0.0.0.0 --port 3389 \
--certificate "$dir/rdp.crt" --certificate-key "$dir/rdp.key" \
--username "$USER" --password "$(cat "$password_file")"
'';
in
{
options.komorebi.krdp = {
enable = lib.mkEnableOption "KRDP, an RDP server, in every Plasma session";
passwordFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/run/run-kde-guest/rdp-password";
description = ''
The path, in the guest, of a file with the password a client logs in with. It is a path in
the running guest and not a file of the Nix store, so that no password is part of the
system. The unit reads it in place of `~/.config/komorebi-vm/rdp-password` when it exists,
and starts when either exists.
'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
krdp
# A client, to try the server from inside the guest. FreeRDP decodes H.264 with OpenH264
# when it is built with it, and OpenH264 shows nothing of the video KRDP sends; without it,
# FreeRDP decodes with FFmpeg (the VM suite `rdp`, docs/dev/PLATFORM.md).
(pkgs.freerdp.override { openh264 = null; })
];
# krdp streams the screen through pipewire
services.pipewire = {
enable = true;
wireplumber.enable = true;
};
security.rtkit.enable = true;
networking.firewall.allowedTCPPorts = [ 3389 ];
systemd.user.services.krdp = {
description = "RDP into this Plasma session";
wantedBy = [ "plasma-workspace.target" ];
after = [ "plasma-core.target" ];
# with no password the unit is skipped, not failed: `systemctl --user start krdp` once the
# file is there
unitConfig.ConditionPathExists =
if cfg.passwordFile == null then
"%h/.config/komorebi-vm/rdp-password"
else
[
"|%h/.config/komorebi-vm/rdp-password"
"|${cfg.passwordFile}"
];
serviceConfig = {
ExecStart = startKrdp;
Restart = "on-failure";
RestartSec = 3;
};
};
};
}