Introduction
Previously, I wrote about how to connect to Hyprland via Windows’ built-in RDP client.
https://www.munenick.me/blog/hyprland-rdp
In that article, I introduced how to connect to Hyprland from the standard Windows RDP client by combining xrdp and WayVNC.
However, Hyprland does not have a mechanism to operate as an RDP server by itself. As a result, the configuration was complicated: xrdp acted as the RDP entry point and internally bridged to WayVNC.
Even though I only wanted to connect via RDP, I had to think about RDP, VNC, Wayland, and Hyprland headless outputs. There were also compatibility issues between xrdp and WayVNC, along with dynamic resolution changes.
In that case, I thought it would be a good idea to create an RDP server exclusively for Hyprland.
So I created hypr-rdp.
https://github.com/MuNeNiCK/hypr-rdp
What is hypr-rdp?
hypr-rdp is a native RDP server for Hyprland.
It is built to connect to Hyprland from a normal RDP client, such as the standard Windows Remote Desktop client.
hypr-rdp itself acts as an RDP server, handling Hyprland’s screen capture, input, audio, clipboard, etc.
The main features are as follows.
| Feature | Details |
|---|---|
| Screen streaming | H.264 / EGFX |
| Codec | AVC420, experimental AVC444 |
| Encoding | Fallback to software encoding when VA-API is unavailable |
| Screen capture | wlr-screencopy-v1, ext-image-copy-capture-v1 |
| Audio | Transfer to the RDP client via PipeWire |
| Clipboard | Two-way synchronization of text and images |
| Input | Keyboard/mouse input |
| TLS | Automatic generation of self-signed certificate, optional certificate specification |
| Configuration file | ~/.config/hypr-rdp/config.toml |
How to use
Requirements
hypr-rdp requires Hyprland 0.54 or later.
The main runtime dependencies are listed below. The package manager will resolve them during installation.
- ffmpeg / libavcodec
- libva
- PipeWire
- libxkbcommon
If you use hardware encoding with VA-API, you will also need a VA-API driver that is compatible with your GPU.
Install intel-media-driver for Intel GPUs, libva-mesa-driver for AMD GPUs, and so on.
Install
On Arch Linux, it can be installed from AUR.
yay -S hypr-rdp
If you use Nix, you can install it with the following.
nix run github:MuNeNICK/hypr-rdp#hypr-rdp -- --help
You can also use prebuilt binaries obtained from GitHub Releases.
tar xzf hypr-rdp-v*.tar.gz
sudo install -Dm755 hypr-rdp /usr/local/bin/hypr-rdp
Start
If you want to connect from another machine, specify the bind address and start it.
hypr-rdp -u user -p pass --bind 0.0.0.0:3389
Specify resolution and frame rate
To specify resolution and frame rate, use --resolution and --fps.
hypr-rdp -u user -p pass --resolution 2560x1440 --fps 60
Use this if you want a fixed-size output for RDP.
Use a specific output
If you want to capture a specific output, specify --output.
hypr-rdp -u user -p pass --output DP-1
Use this when you want to use an existing physical output or a specific Hyprland output instead of the headless output for RDP.
Specify capture method
The screen capture method can be specified with --capture-mode.
When using wlr-screencopy-v1, do the following:
hypr-rdp -u user -p pass --capture-mode wlr
When using ext-image-copy-capture-v1, do the following:
hypr-rdp -u user -p pass --capture-mode ext
Encoding settings
hypr-rdp uses RDP EGFX for screen streaming.
By default, AVC420 is used.
hypr-rdp -u user -p pass --egfx-codec avc420
AVC444 can also be specified experimentally.
hypr-rdp -u user -p pass --egfx-codec avc444
Use --bitrate to specify the H.264 bit rate.
hypr-rdp -u user -p pass --bitrate 20000000
Use --quality to specify the quality.
hypr-rdp -u user -p pass --quality 23
In environments where VA-API is available, hardware encoding is used.
If it is unavailable, hypr-rdp falls back to software encoding.
Configuration file
If you don’t want to specify CLI arguments every time, you can use a configuration file.
The configuration file is below.
~/.config/hypr-rdp/config.toml
This is an example.
bind = "0.0.0.0:3389"
username = "user"
password = "pass"
# resolution = "1920x1080"
capture_mode = "wlr"
bitrate = 10000000
quality = 23
fps = 30
egfx_codec = "avc420"
# output = "DP-1"
Values specified in CLI arguments take precedence over configuration files.
You can write the settings you usually use in config.toml and override them with CLI arguments only when necessary.
TLS and authentication
RDP uses TLS.
hypr-rdp automatically generates a self-signed certificate if you do not specify one.
If you want to specify your own certificates, use --cert and --key.
hypr-rdp \
-u user \
-p pass \
--cert /path/to/cert.pem \
--key /path/to/key.pem
Username and password can be specified in -u / -p.
hypr-rdp -u user -p pass
It can also be written in the configuration file.
username = "user"
password = "pass"
When listening at 0.0.0.0:3389, be sure to set authentication information.
Inner workings
Overall configuration
hypr-rdp uses IronRDP for the RDP server layer.
It combines IronRDP with Hyprland-specific processing.
The rough structure is as follows.
RDP Client
↓
IronRDP
↓
hypr-rdp
├─ Hyprland IPC
├─ Wayland capture
├─ H.264 / EGFX
├─ PipeWire audio
├─ Clipboard
└─ Input
It accepts RDP connections, captures the Hyprland screen, encodes it in H.264, and sends it to the RDP client.
At the same time, keyboard and mouse input from the RDP client is passed to Hyprland, while audio and clipboard data are handled as RDP channels.
Prepare output for the session
To connect with RDP, you need a screen to send to the client.
If you want to use an existing output, you can specify it with --output.
If it is not specified, hypr-rdp prepares a headless output for RDP sessions.
Internally, it connects directly to the Hyprland IPC.
Hyprland’s IPC socket constructs a path from HYPRLAND_INSTANCE_SIGNATURE and XDG_RUNTIME_DIR.
$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket.sock
Use socket2 for events.
$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock
When creating output, send Hyprland IPC commands like the following:
output create headless hypr-rdp
When an output is added on the Hyprland side, a monitoradded event is emitted on socket2.
hypr-rdp waits for this event and gets the output name of the created hypr-rdp-* output.
Once you have obtained the output name, set the resolution and placement using keyword monitor.
hypr-rdp-1,1920x1080@60,-9999x0,1
The headless output is resized if the RDP client requests an initial size or if DisplayControl requests a resize.
The created headless output is deleted when the session ends.
output remove hypr-rdp-1
Additionally, if a hypr-rdp-* headless output remains from a previous session, it can be reused.
Capture screen and send to RDP
Once the output is ready, capture it with Wayland’s protocol.
The supported capture methods are as follows.
- wlr-screencopy-v1
- ext-image-copy-capture-v1
The captured frames are encoded in H.264 and sent to the client as RDP EGFX.
If VA-API is available, use hardware encoding.
If it cannot be used, hypr-rdp falls back to software encoding.
When encoding with software, the maximum length is 3840 on the long side and 2160 on the short side, considering the ease of handling H.264. If a larger size is requested, it will be reduced to fit within the upper limit while rounding to an even size.
Send audio
PipeWire is used for audio transfer.
hypr-rdp captures audio from PipeWire and sends it to the client through RDP’s RDPSND channel.
This allows the RDP client to listen to the sounds played in the Hyprland environment.
Sync the clipboard
Clipboard supports two-way synchronization.
It can handle not only text but also image clipboards.
By connecting the clipboard on the Wayland side with the CLIPRDR channel on the RDP side, the clipboard is synchronized between the client and Hyprland.
Clipboard synchronization is very important when using it as a remote desktop.
It affects not only how you can see the screen, but also whether you can use it in your daily work.
Pass input
For input, the keyboard and mouse events received from the RDP client are passed to Hyprland.
On the Wayland side, we use a virtual keyboard or virtual pointer system.
Screen streaming alone is relatively simple, but input processing is required to use it as a remote desktop.
hypr-rdp receives keyboard, pointer, click, scroll, and other input events from the RDP side and passes them to Hyprland.
Why use Hyprland IPC instead of xdg-desktop-portal?
When handling screen sharing and remote desktop in a Wayland environment, it is natural to handle it via xdg-desktop-portal.
xdg-desktop-portal is the standard entry point for handling sessions such as screen sharing and remote desktop between applications and compositors.
In Wayland, the idea is that an application should not automatically capture the screen or inject input. Instead, user permission and compositor control should pass through the portal.
Therefore, the ideal mechanism for remote desktop and screen sharing would be to complete everything through xdg-desktop-portal.
However, at present, Hyprland does not yet have the necessary APIs for RDP server use.
There are also related issues and PRs.
| Type | Number | Content | Status |
|---|---|---|---|
| Issue | #252 | org.freedesktop.portal.RemoteDesktop support request |
Open |
| PR | #308 | RemoteDesktop portal implementation | Draft |
| PR | #402 | RemoteDesktop portal + ConnectToEIS compatible | Open |
| PR | #268 | Input Capture Desktop Portal implementation | Open |
In particular, #402 implements org.freedesktop.impl.portal.RemoteDesktop for Hyprland and adds remote input injection using ConnectToEIS, wlr-virtual-pointer, and virtual-keyboard.
In other words, although RemoteDesktop support via xdg-desktop-portal is progressing, it is not yet officially available.
Therefore, hypr-rdp uses Hyprland IPC directly as the currently practical method.
Specifically, the process is as follows.
Connect to Hyprland IPC
↓
output create headless
↓
wait for monitoradded on socket2
↓
Set resolution and placement with keyword monitor
↓
Screen capture with wlr-screencopy-v1/ext-image-copy-capture-v1
↓
Transfer to client with RDP EGFX
In the future, if xdg-desktop-portal becomes officially compatible with RemoteDesktop and can be used stably with Hyprland, I would like to support that as well.
Conclusion
hypr-rdp is an RDP server dedicated to Hyprland.
It is built to connect to Hyprland from the standard Windows RDP client.
It supports screen streaming with H.264/EGFX, audio transfer with PipeWire, bidirectional clipboard synchronization, keyboard/mouse input, TLS, configuration files, and more.
Currently, it uses Hyprland IPC directly to create and manage headless output.
Ideally, it would be possible to handle it via xdg-desktop-portal, but support for RemoteDesktop is still in progress on the Hyprland side. Therefore, I am currently implementing it using Hyprland IPC.
In the future, if xdg-desktop-portal becomes officially compatible with RemoteDesktop and can be used stably with Hyprland, I would like to support that as well.
If you want to connect to Hyprland from Windows’ built-in RDP client, try it.