Hello, I am writing this because this topic was at first a question I had and I couldn’t find an answer to it, information about it online is scarce and outdated so here I am to share what I have figured out; so
Let’s establish things
- Remote Machine = The device processing the program/audio and holding the files, streaming them over to the Local Machine
- Local Machine = The device which initiates the connection to the Remote Machine, hears the audio, interacts with the programs and receives the files requested
What we’ll be using (L/R means Local or Remote respectively)
- SSH (openSSH) L&R
- waypipe L&R
- Any wlroots based Compositor L optionally R as well
- xwayland-satellite R
- pipewire, pipewire-pulse and wireplumber L
- sshfs L
- Any Terminal Emulator L
- FUSE L
In my case my compositor of choice will be Labwc, keep in mind all of the components used have a lot of options and you could benefit from checking out whats hot in each of them, I will only cover settings up to things WORKING
First things first install the packages and on the Local Machine make sure you have your sound system running for your User, if you hear audio already you should be okay otherwise review your specific distribution documentation on how to start the services
For example on Arch: systemctl start pipewire pipewire-pulse wireplumber --user
Next is to start your Compositor of choice and open up a terminal emulator, you should first make a connection from the Local Machine to the Remote Machine with SSH and your credentials so
For example: ssh -p 7777 -l user 192.168.100.2
Managed to connect to your Remote Machine? Great now we’ll need to do the set-up, we’re going to need to make start xwayland-satellite and set environment variables automatically on each SSH login
There might be many ways to do this, In my case I will use ~/.bash_profile;
For Example:
if ! [ "x${SSH_TTY}" = "x" ]; then
if (find $XDG_RUNTIME_DIR/pulse-server-*) >/dev/null 2>&1; then
export PULSE_SERVER=unix:$(find $XDG_RUNTIME_DIR/pulse-server-* | tail -n 1)
fi
if ! [ "x${WAYLAND_DISPLAY}" = "x" ]; then
export DISPLAY=:$(shuf -i 300-3000 -n 1)
xwayland-satellite $DISPLAY >> /dev/null 2>&1 &
fi
fi
This will first evaluate if we are on an SSH Session, to keep any of our process from affecting local Machine usage, then if it’s true it will try to locate the Pulse Audio server socket we will forward through SSH (encrypting it) and set the PULSE_SERVER variable it needs to function, following that the second process will check if we have a WAYLAND_DISPLAY (automatically set by Waypipe) and start xwayland-satellite on a random above 30 DISPLAY=: value to avoid conflicts with local/multi-session usage and fork it into the background so we can actually use the Console ourselves
Next we need to automatically clean everything up when we’re done and closing our session, for this purpose I will use ~/.bash_logout
For example:
if ! [ "x${SSH_TTY}" = "x" ]; then
if ! [ "x${PULSE_SERVER}" = "x" ]; then
rm ${PULSE_SERVER#*:}
fi
if ! [ "x${DISPLAY}" = "x" ]; then
kill -SIGTERM $(pgrep -f "xwayland-satellite $DISPLAY")
fi
fi
This will first again evaluate if we are on an SSH session, and if true proceed to delete the Pulse Audio server socket we forwarded (necessary to avoid errors in future connections) and terminate xwayland-satellite (necessary because the session would otherwise get stuck and never end because we are still forwarding that application)
When this is all set-up, we can exit the Remote Machine’s shell and everything is basically ready on the Remote Machine
Now on our Local Machine we have to modify our SSH command to forward the Pulse Audio socket we have mentioned prior
For example: ssh -p 7777 -l user -R $XDG_RUNTIME_DIR/pulse-server-"$RANDOM":$XDG_RUNTIME_DIR/pulse/native 192.168.100.2
The important part is -R $XDG_RUNTIME_DIR/pulse-server-"$RANDOM":$XDG_RUNTIME_DIR/pulse/native which is creating the UNIX Stream socket on the remote machine and giving it the name “pulse-server” + a random number to prevent multi-session conflicts and linking it to your Local Machine’s audio socket
This makes applications on the Remote machine talk directly to your Local Machine’s audio server and playing audio in it, everything basically functions as if it were running Locally, due to this the audio stream is uncompressed, you might want to add -c to the SSH command for all the data to be streamed with compression if you have limited data plans
Next up we should set-up waypipe, this application allows forwarding both Wayland native applications AND wayland compositors themselves, alongside with xwayland-satellite that allows forwarding X11 applications running on the Remote Machine, you can forward any application running Remotely to your Local Machine, even wlroots-based Compositors themselves if you want a full Remote Desktop that encapsulates everything you run instead
For example: waypipe --video h264 ssh -p 7777 -l user -R $XDG_RUNTIME_DIR/pulse-server-"$RANDOM":$XDG_RUNTIME_DIR/pulse/native 192.168.100.2
In my example command, I use hardware accelerated video encoding which greatly increases performance, you may just want to use waypipe alone however which uses default settings, I highly recommend reading waypipe documentation for achieving the best performance for your setup and test it with your application of choice
For example: WLR_RENDERER=gles2 Labwc (executed on the Remote Machine Shell, will open it on your Local Machine’s Compositor)
Finally, for setting up Remote File Access we use sshfs prior to connecting to the Remote Machine, this utility mounts a Remote Filesystem on a local directory through SSH and FUSE using the sftp protocol which is all encrypted
For example: sshfs -p 7777 user@192.168.100.2:/home/user/RemoteDirectory/ /home/user/LocalDirectory/
Nice, now we have it all set up and ready to work, we can finally make it convenient to use, in my case I prefer to run all of this as a script easily accessible on my terminal as a single command that executes the script located on my scripting environment, and we add another command that just unloads the Remote Filesystem mount when we’re done
For an example script:
sshfs -p 7777 user@192.168.100.2:/home/user/RemoteDirectory/ /home/user/LocalDirectory/
waypipe --video h264 ssh -p 7777 -l user -R $XDG_RUNTIME_DIR/pulse-server-"$RANDOM":$XDG_RUNTIME_DIR/pulse/native 192.168.100.2
umount /home/user/LocalDirectory/
Let’s say we create this script and it’s saved in our home folder, we just have to make it executable (chmod +x scriptdir) and run it from our Terminal Emulator
For example: ./Remote\ Machine1.sh
And it will automatically set up everything for us and ask for our Credentials, we have a perfect workspace that imitates that of a remote desktop experience, on Wayland (may not be exclusive to this but that’s what I’m doing here)
Did I miss anything? Have suggestions? Let me know what can be done better and I’ll update this post, thanks for reading and have a good one


Tested, triaged it and re-wrote the guide to add it in there, please take a look and tell me what you think, missed me convenience options or something? I’d love to know, thanks for your contribution!
Sorry if it seems like I do, but I in fact do not have a brain.
I just found this tool gets the job done, and that’s it.
I typically just use it in a pretty stupid manual way.
Even the xfce4-panel discovery was an accident.
I was using waypipe before knowing about xwayland-satellite. I wanted to run an X program, so in the same shell I typed
vncserverto, well, launch a VNC server. That invoked xfce4-session, BUT since the WAYLAND_DISPLAY was set, XFCE DE attached to waypipe rather than XTigerVNC, launching a full remote desktop over my local one.And out of that, xfce4-panel proves pretty useful. I can easily launch other programs using GUI, and also see widgets on that panel.
Here’s what I mean, if that sounds confusing:

Plasma panel (bottom) is local, XFCE panel (top and middle bottom) are remote.
Right, and you’re probably wondering why that app launcher at the top looks shattered. Well, both can’t be opened at once. If the application launcher goes out of focus, it closes.
But also, I use the shatter effect in KDE Plasma, so it doesn’t go away immediately. This is just as close as I could get with screenshot timing.
That’s cool, if it works and looks like magic, You’re a Wizard too, don’t question it! Just contributing what you found to work makes things better for us all