GNOME (Wayland) RDP
GNOME's own remote-desktop stack (GNOME Remote Desktop) is GNOME-only. lamco-rdp-server speaks standard RDP on GNOME/Mutter through the freedesktop RemoteDesktop portal and Mutter's Direct API, and the same server also runs on KDE, sway, Hyprland, and COSMIC. This guide is the concrete GNOME setup: install, grant permission once, connect, and fix the GNOME-specific things that trip people up.
Install
Community Edition (any distro): Lamco's own self-hosted Flatpak repository (recommended, auto-updates), the Flatpak bundle attached to the GitHub release, or the Snap Store.
flatpak install --from https://flatpak.lamco.ai/io.lamco.rdp-server.flatpakref
# equivalent, in two steps
flatpak remote-add --user --if-not-exists lamco https://flatpak.lamco.ai/lamco.flatpakrepo
flatpak install --user lamco io.lamco.rdp-server
# or: install the downloaded bundle once, no auto-updates
flatpak install <downloaded>.flatpak
flatpak run io.lamco.rdp-server # launches the GUI
# or: snap install lamco-rdp-server
Native (Ubuntu 24.04 / Fedora / Arch): use the distribution package (see the Installation page). GNOME/Mutter needs PipeWire and xdg-desktop-portal-gnome, which ship by default on a GNOME desktop.
Verify the environment before connecting:
Look for Portal (RemoteDesktop + ScreenCast) available and an Encoding backend.
Grant permission once (unattended access)
GNOME shows a portal permission dialog the first time a remote session starts. For unattended or headless use, grant it once and store a restore token:
This triggers the portal dialog, obtains a restore token, and stores it so future connections start without a prompt. Re-run it if you revoke access or change users.
Minimal config
~/.config/lamco-rdp-server/config.toml:
# Dual-stack by default: "[::]:3389" listens on IPv6 and, on a standard Linux
# host, also accepts IPv4 clients. Use "0.0.0.0:3389" only to force IPv4-only.
listen_addr = "[::]:3389"
[security]
tls = true # self-signed by default; see Security for your own cert
[video]
codec = "auto" # AVC444/AVC420 via EGFX where the client supports it
Start it:
# or: flatpak run io.lamco.rdp-server
Connect
The server listens dual-stack by default, so IPv4 and IPv6 clients both work. Use the host's name (it resolves to whichever family the client prefers) or an explicit address; IPv6 literals go in brackets.
- Windows: built-in Remote Desktop Connection (
mstsc.exe) →host:3389, or an IPv6 literal in brackets:[2001:db8::10]:3389. - Linux: Remmina, or FreeRDP:
xfreerdp /v:host:3389 /u:USER(IPv6 literal:xfreerdp /v:[2001:db8::10]:3389 /u:USER). - macOS: Microsoft Remote Desktop.
Input uses libei by default on GNOME, which is the supported modern path.
GNOME-specific behavior (current in 1.4.5)
- Area capture, so a fullscreen video no longer freezes the session. Mutter
stops recording a monitor stream while a surface is handed to direct scanout (mutter#3903), which
froze the remote picture for the length of any video. The server now resolves the monitor's
rectangle through
org.gnome.Mutter.DisplayConfigand records that area instead. Selected bycapture.gnome_record_mode:auto(the default, area on a single monitor),area, ormonitor. An area stands in for exactly one monitor, so multi-monitor layouts fall back to the monitor stream. The cost is that an area stream always re-composites where a monitor stream blits, and Mutter's area source runs at a fixed 60 fps. - DMA-BUF capture is attempted, with shared memory as fallback. The GNOME profile no longer forces shared memory. Virtual GPUs are checked for the Venus capset rather than refused by driver name, so a Venus-capable virtio-gpu can take the DMA-BUF path.
- Headless servers can present the virtual monitor as a real display with
capture.gnome_virtual_is_platform = true(GNOME 46 or newer, off by default). The compositor's logical scale is now read from the stream asorg.gnome.scaleon virtual-monitor sessions. - Multitouch over MS-RDPEI, enabled with
input.enable_touch. - Many sequential sessions, no restart. On GNOME/Mutter the server now uses a per-connection session: it creates a fresh RemoteDesktop/ScreenCast session on each connect and releases it on disconnect. You can connect, disconnect, and reconnect all day. (Earlier versions kept one long-lived session that Mutter's idle timeout reaped a few seconds after a client left, which looked like "it only works once.")
- GNOME 49 input works via a lazy Mutter EIS lifecycle with a kept-alive connection.
- PAM authentication works under the hardened system service (the unit joins the
shadowgroup and keeps full seccomp hardening).
Verified in the 1.4.5 campaign on GNOME 48 (Debian 13), GNOME 49 and 50 (Fedora, Arch), and Ubuntu 26.04.
Troubleshooting
| Symptom | Cause | Fix |
| Connects, then black screen (mouse/audio work) | No working H.264 encoder, or portal capture not started | Run --show-capabilities; ensure an Encoding backend is present. On CPU-only systems install Cisco's OpenH264 (see Video Encoding); prefer a GPU for hardware VA-API |
| Works once, then every reconnect fails until restart | Old persistent-session model reaped by Mutter idle timeout | Update to 1.4.4 (per-connection lifecycle) |
| Input does nothing on GNOME 49 | EIS lifecycle regression | Fixed in 1.4.4 |
| Screen freezes during fullscreen video | Mutter stops recording a monitor stream during direct scanout (mutter#3903) | Fixed in 1.4.5 by area capture; keep capture.gnome_record_mode = "auto" |
| Video is blurry or laggy | Mutter over-reports damage | Fixed in 1.4.5; the server distrusts the hints and uses its own pixel diff for the connection |
| Portal dialog on every connect | No stored restore token | Run lamco-rdp-server --grant-permission once |
| PAM login always fails on the packaged system service | Hardened unit blocked the PAM helper | Fixed in 1.4.4 (unit joins shadow); or use the recommended auth method the server reports at startup |
See also: Installation, Configuration, Security, Video Encoding, the Platform Compatibility matrix, and the sibling guides for KDE/KWin, sway/wlroots, Hyprland, and COSMIC.