-
-
Notifications
You must be signed in to change notification settings - Fork 0
Remote Desktop
syn-remote puts this desktop on a VNC viewer somewhere else — including when
nobody is sitting at it — or streams it to Moonlight, which is video rather than
rectangles of pixels.
syn-remote on # start it now, and at every login
syn-remote address # how to connect to it
syn-remote password # the password a viewer is asked for
syn-remote status # what it is doing
syn-remote off # stop it, and stop it starting at loginSettings ▸ Remote Desktop is the same thing in a window.
wayvnc is the wlroots-native VNC server. It captures the screen through
zwlr_screencopy_manager_v1 and drives the seat through
zwp_virtual_pointer_manager_v1 and zwp_virtual_keyboard_manager_v1. synui
implements all three and hands them to any native client, so nothing here goes
through a desktop portal and nothing prompts.
"Wayland can't do remote desktop" does not apply here. All three reasons that is said are about other stacks:
- GNOME and KDE gate capture behind a portal that asks a human, per session. That is a policy, and it makes unattended access impossible by design.
xdg-desktop-portal-wlrimplements ScreenCast but not RemoteDesktop, so there is no input injection through the portal. That is why portal-based tools can watch a wlroots desktop and cannot touch it — going native sidesteps it.- Nothing exists to connect to before somebody logs in. That one is true here, on any Wayland system, and
syn-remote statussays so rather than failing with an error that reads like a bug.
A blanked output cannot be captured at all. Once synui's idle blank stage
has fired, screencopy answers failed to copy output — a viewer gets nothing,
and there is no frame to click on to get out of it. power_blank_timeout
defaults to 600 seconds, so an unattended machine would go dark to a viewer ten
minutes after the last keypress and stay dark.
That is what the wrapper is for. When somebody connects it turns the outputs back on and holds a real idle inhibitor; when the last viewer leaves it releases it, so the machine goes back to sleeping normally. Two viewers is one screen: the wake happens once, and the release waits for the last one.
| This machine only (default) | Bound to 127.0.0.1. Reach it from elsewhere over an SSH tunnel. |
| The network |
syn-remote listen lan — every device on the LAN can reach it. |
⛔ The firewall does not stand behind this. synnet's base policy is default-drop on input and accepts everything from
10/8,172.16/12and192.168/16. A port bound to0.0.0.0is therefore not "open but firewalled" — it is reachable by every device on the network, and there is no second door to unlock afterwards. The certificate and the password are what stand in the way.
From another machine, with the default loopback binding:
ssh -N -L 5900:localhost:5900 you@your-machinethen point a VNC viewer at localhost:5900. syn-remote address prints that
line with the right names in it.
Two separate things stand in the way, and both have to be dealt with. Neither
of them is syn-remote listen lan, which only decides what the server binds to.
1. The firewall drops it. synnet's input chain accepts loopback,
established/related, ICMP, and sources in 10/8, 172.16/12, 192.168/16
(plus IPv6 ULA and link-local). Everything else hits the drop policy, so an
unsolicited connection from a public address never arrives however the server
is bound.
Warning
synnet --allow <ip> will not open it. Despite the name it only removes
an address from the block set — it undoes a previous --block and opens
nothing. --trust-if is DHCP and DNS on a gateway bridge, also not this.
The verb that opens a port is --open:
sudo synnet --open tcp/5900 100.64.0.0/10 # e.g. a Tailscale mesh
synnet --status # shows what is openWith no CIDR the source is any, which means the internet if this machine is
reachable from it — so it says so when you do that.
2. The certificate does not carry the address you would dial. It is built
from the addresses this machine holds, so a public IP in front of a port
forward — or the dynamic-DNS name that resolves to it — is not in it and cannot
be. A viewer validates against what it dialled, so it fails with IP address mismatch or Hostname mismatch. Name it:
syn-remote names add myhouse.duckdns.org
syn-remote names # what it vouches forThat re-issues the certificate, so every client that already trusted this
machine has to syn-remote trust <name> --renew.
WireGuard on a private range (10.x, 192.168.x) |
Works as shipped. Inbound packets carry a private source, so synnet already accepts them, and the tunnel address is picked up by the certificate — run syn-remote trust <name> --renew on the client once the interface exists. |
| Tailscale | Needs one rule. Its 100.64.0.0/10 is not a private range, so the tunnel establishes outbound and then every packet inside it is dropped, with nothing in any log mentioning the firewall. sudo synnet --open tcp/5900 100.64.0.0/10. |
| An SSH tunnel from outside | Same problem one layer down — inbound SSH from a public address is dropped too. It only helps from on-LAN, or over a VPN that already works. |
The connection always carries TLS: wayvnc's enable_auth requires a
certificate, a key and a password together, so there is no
password-without-encryption — which is the right way round, given VNC's own
authentication is DES with an eight-character key. The certificate is
self-signed, made once, and lives in ~/.config/syn-remote/.
| A generated password (default) | Twenty characters from /dev/urandom. syn-remote password prints it, syn-remote password new rolls it. |
| Your account password |
syn-remote auth pam — the same three-try lockout as any other login on the machine. |
VNC sends rectangles of pixels; a stream sends an encoded video frame. The GPU does the encoding, so a desktop at 1440p120 is smooth where VNC is a slideshow — which is what makes games, video and anything that moves worth doing this way. The server is sunshine; the client is Moonlight, on a PC, a phone, a tablet or a TV box.
syn-remote stream on # start it now, and at every login
syn-remote stream status # what it is serving, and to how many
syn-remote stream off # stop it, and stop it starting at login
Settings ▸ Remote Desktop has the same switch.
Moonlight shows a four-digit PIN and waits. Accept it on the machine being streamed:
syn-remote stream pair 1234
Each client pairs once. syn-remote stream web prints the address of
sunshine's own settings page, with the user name and password to open it.
Important
A streaming host is on the network. sunshine binds every interface and announces itself over mDNS. There is no loopback-only mode, so unlike the VNC server above, switching this on makes the machine reachable by anything on the network that speaks Moonlight. Pairing is what stands in the way.
By default the stream does not show a monitor. synctl virtual add grows a
headless output on the running compositor — a real screen in every way
except the cable: it takes a desktop, it holds windows, the bar and the dock
come up on it — and the stream serves that.
syn-remote stream display virtual # a display of its own (the default)
syn-remote stream display auto # the screen that is on this desk
syn-remote stream display DP-3 # …or one by name
syn-remote stream mode 2560x1440@120 # what the virtual display starts at
When a client connects, that display is resized to exactly what the client asked for — resolution and frame rate — and put back when streaming stops. So a phone gets a phone-shaped desktop and a 4K TV gets a 4K one, without touching the screens in the room.
syn-remote stream solo on |
the screens in this room go dark while somebody is streaming, and come back when they leave |
syn-remote stream tune encoder nvenc |
pick the encoder by hand instead of letting sunshine choose |
syn-remote stream tune latency off |
give the encoder back its quality presets |
The idle blank stage never turns a virtual display off. A blanked output cannot be captured at all, and there is nobody in front of this one to wake it.
sunshine's Wayland grabber binds zwlr_export_dmabuf_manager_v1 and
xdg_output, both of which synui exports — so there is no portal here either.
The generated config pins capture = wlr.
Note
With capture left to autodetection, sunshine prefers X11 when DISPLAY is
set. synui runs XWayland, so it is always set, and the result is a stream of
XWayland windows and nothing else — sunshine's own log says
"screencasting will only work on XWayland applications".
Input arrives through /dev/uinput, which logind grants to the user of the
active seat. Nothing else is needed and nothing has to be run as root.
The other half of the package: syn-remote-gui, or the same thing from a
terminal. A connection is saved once and opened by name.
syn-remote add desktop 192.168.1.50:5900 <user>
syn-remote trust desktop # check the certificate — once, before the first connection
syn-remote saved desktop set # remember the password (optional)
syn-remote connect desktop
Important
The certificate has to be checked before the first connection, and nothing else will tell you so. wayvnc offers exactly one security type this viewer speaks — VeNCrypt X509Plain — so the server's certificate is the first thing in the exchange. Until it has been trusted, the TLS session comes up and is dropped, and there is no error on the machine you are sitting at. The only trace is on the server:
ERROR: ../neatvnc/src/server.c: 2374: Client handshake timed out
which reads like a firewall and is not one. syn-remote trust <name> shows
the fingerprint and waits for a yes; compare it against syn-remote fingerprint on the machine you are dialling before answering.
The window's Check the certificate button does the same thing in a terminal, because the fingerprint is a question for a person. A connection that has not been checked says so in the list rather than failing quietly.
A re-issued certificate — which happens by itself when the server's address
moves — is correctly refused by everything that trusted the old one. Accept the
new one with syn-remote trust <name> --renew.
syn-remote add tv 192.168.1.60 --stream
syn-remote trust tv # Moonlight shows a PIN; the other machine accepts it
syn-remote connect tv
--stream saves it on sunshine's port instead of VNC's, and connect opens it
with Moonlight rather than the VNC viewer. There is no certificate to pin and no
password to remember: a streaming host is paired with, once, and the other
machine is where that is accepted — syn-remote stream pair <PIN> over there,
or its settings page.
The window and the TUI show which kind each saved connection is, and the buttons change with it: Pair with it instead of Check the certificate.
Three different problems wear the same word:
- The screen is asleep. Handled above — the wrapper wakes it when somebody connects.
- The machine is suspended. It has no server, no port and nothing listening, so nothing can be woken by connecting to it. That needs a magic packet, and both ends are below.
- Nobody has logged in. There is no compositor, so there is nothing to capture. A machine meant to be reached this way wants autologin.
syn-remote wakeable # what it is now
syn-remote wakeable on # arm the wired card for a magic packet
wakeable reports the interface, its hardware address, whether the card can be
woken at all, whether it is armed right now, and whether it will still be
armed after the next reboot. Those last two are separate questions on purpose:
arming the card and remembering to arm it again are two different things, and a
machine that is armed today and forgotten at the next boot reads as working
right up until the reboot nobody connects to it after.
So wakeable on writes both. NetworkManager remembers the setting and
re-applies it every time the connection is activated — a reboot, a replugged
cable, a driver that clears the flag on link-down. A small helper applies it
immediately, without activating anything, because activating the connection you
are reaching the machine over drops the link underneath you.
Note
Reading the flag needs privilege, not just writing it: the same kernel call can return a card's SecureOn password, so it is guarded like a write. At the machine's own keyboard this is granted without a password; over SSH it is not, which is deliberate — reaching in from the network to change whether a machine can be woken from the network asks for an administrator.
syn-remote wake desktop # send the packet and wait for it
syn-remote connect desktop # does that by itself if it is not answering
The hardware address is read off the network when the connection is saved, so
syn-remote add while the other machine is still awake needs nothing else.
--mac gives it explicitly for a machine that was already asleep when it was
saved. Two places on that machine print the address to use: syn-remote wakeable, and Settings ▸ Network, which lists a hardware address for every
interface beside the addresses it holds — see The Network
pane.
Nothing acknowledges a magic packet — there is no reply, and no error — so
wake watches the port instead and reports what actually happened. connect
does the same before it opens anything, rather than handing a viewer a machine
that is not there.
Important
A magic packet is a broadcast, and a broadcast does not cross a router. The machine sending it has to be on the same network as the machine being woken. Reaching a sleeping machine from outside needs something on that network to send the packet — the VPN endpoint above, or a router that can be asked to send one. And a machine that was shut down rather than suspended needs Wake-on-LAN enabled in its own firmware setup as well; the operating system is not running to arm anything.
syn-remote on starts the server at every login, and it waits for the desktop
rather than racing it — the unit is started before the compositor exists, so
its first seconds are spent waiting for a session that is still coming up.
syn-remote status says Server stopped while it waits, and the journal says
what it is waiting for.
syn-remote owns no part of the VNC protocol, the encryption or the
credentials — wayvnc does all of it, and sunshine does the same for the stream.
What the wrapper adds is the screen wake, the idle inhibitor, the loopback
default, the generated certificate and password, the virtual display a stream is
served on, and one place to read the state from.
See also: The-Desktop, Settings, Commands.
Using it
- Installation
- Welcome Guide
- Updating
- Software
- Files
- Settings
- Calendar
- Editor
- Studio
- Terminal
- Keybindings
- Speech and dictation
- Remote Desktop
- Malware Scanning
- Commands
- Configuration
- Nix
- Gaming
- Big Screen
- DaVinci Resolve
- Secure Boot
- Troubleshooting
Customising it
Components
Apps
Hacking on it