Remote GUI over SSH¶
What it is¶
With the SSH service a remote session
cannot open a window on the host's screen, so by default the GUI launchers
(jb ide, jb chrome, jb firefox, jb browser, jb apps run) are
host-only. With remote.ssh.gui on, they instead draw on a shared RDP
display: a small jailbee-display container running the weston compositor
(RDP backend, software rendering). You tunnel its port over the existing SSH
connection and view it in any RDP client.
There is one screen for every container. Apps from different containers appear side by side on it.
Turn it on¶
- Set
remote.ssh.gui: trueinglobal.yaml(seeremote.ssh). jb display up. The first run pulls an image and installs weston, which takes a few minutes; later runs are instant.
The flag is re-read for every new session and every forward request, so no
jb remote ssh restart is needed to turn it on or off. Containers mount the
display directory at their next start (or on the first GUI launch) only while
it is on; jb display up warns if it is still off.
jb display up prints the connection recipe; jb display status prints it
again.
Connect¶
On your own computer, in two steps:
ssh -N -L 3389:127.0.0.1:13389 -p <ssh port> jailbee@<host>
then point an RDP client at localhost:3389. Any client works: mstsc on
Windows, Windows App (formerly Microsoft Remote Desktop) on macOS, xfreerdp or
Remmina on Linux.
If the client asks for a login, any user name and password will do: the
display speaks TLS without Network Level Authentication and checks no
credentials (see Security). Accept the self-signed
certificate the client warns about.
Already in an SSH session? Add the forward to it with ~C, then
-L 3389:127.0.0.1:13389. To have every session carry it, put
LocalForward 3389 127.0.0.1:13389 in the host's entry in ~/.ssh/config.
The server accepts the forward from any authorized key while remote.ssh.gui
is on, and only to 127.0.0.1:13389. You can connect before or after
launching anything.
Launch¶
Run jb chrome, jb ide or jb apps run from an SSH session, or choose a
launch in the remote dashboard. To launch an arbitrary command, use
jb exec <name> -d --gui -- <cmd>; a plain jb exec -d never touches the
shared display, so detached builds and servers are unaffected. If no RDP client is connected yet, the command
prints the recipe and waits up to 120 seconds for one. Once a client appears it
waits a few seconds more for the client's input seat to settle, then launches.
If nobody connects in time it fails with an error telling you to connect first;
run it again after connecting.
Autostart apps started from a GUI-enabled SSH session also go to the shared
display, so they can wait for the RDP client in the same way. If the display
cannot be prepared, the first failure is reported and the remaining autostart
apps are skipped, so jb new waits at most once.
What it does not do¶
- No RDP authentication. Any login is accepted; access is limited by network reachability and the SSH tunnel (see Security).
- Window titles do not name the container; two Chrome windows from two containers look alike.
- No GPU. Rendering is in software.
- One screen for all containers, and one shared clipboard.
jb gui(the Qt dashboard) stays a host command.- When SSH repository exclusions are active (
remote.ssh.excluded_reposis non-empty), the GUI launchers (ide, the browsers,apps run) are refused over SSH even withguion, because the scoped command allow-list does not include them.jb exec -d --guiis in that list and still works.
Security¶
See Remote GUI in the security model.
Troubleshooting¶
jb display statusshows whether the container and its service are running.jb display up --recreaterebuilds the display container from scratch.jb display downstops it; the tunnel still opens, but the RDP client then finds nothing listening.- A refused forward (
administratively prohibitedinssh -v) meansremote.ssh.guiwas off when it was requested, or the forward named a destination other than127.0.0.1:13389(localhostdoes not count). - "No seats available" from an app means no RDP client was connected when it started. Connect a client, then launch again.
- A container that was already running when the feature was enabled gets the display directory mounted at its next start, or on the first GUI launch.