SSH X11 forwarding lets you run graphical applications on a remote server and have their windows appear on your local desktop.

Let’s see it in action.

Imagine you have a powerful Linux server remote-server where you’ve installed xeyes. You want to run xeyes on remote-server but see its window on your local machine, local-machine.

First, on your local-machine, make sure you have an X server running. On most Linux desktops, this is already the case. On macOS, you’d typically use XQuartz. On Windows, you might use VcXsrv or MobaXterm.

Then, connect to your remote-server using SSH with the -X or -Y flag:

ssh -X user@remote-server

The -X flag enables trusted X11 forwarding, while -Y enables untrusted forwarding. For most use cases, -X is sufficient and slightly more secure. If you encounter issues with applications not displaying correctly or having permission errors, try -Y.

Once logged in, you can simply type the name of the graphical application you want to run:

user@remote-server:~$ xeyes

A small window with two eyes that follow your mouse cursor should appear on your local-machine’s desktop, even though the xeyes process is running entirely on remote-server.

This works because when you enable X11 forwarding, your SSH client on local-machine sets up a special listening port (usually localhost:6000 or localhost:6001). It also sets the DISPLAY environment variable on the remote-server to point to this local port. When the graphical application on remote-server tries to open a window, it attempts to connect to the X server specified by the DISPLAY variable. SSH intercepts this connection, forwards the X11 protocol commands over the encrypted SSH tunnel to your local-machine, where your local X server receives them and draws the window.

The primary problem X11 forwarding solves is the inability to easily run GUI applications on remote machines without installing them locally or using more complex remote desktop solutions. It’s particularly useful for developers who need to test GUI applications they’re building on a specific server environment, or for system administrators who need to manage graphical tools on servers that don’t have a direct graphical interface.

The key configuration for X11 forwarding happens on the SSH server (sshd_config). Ensure these lines are present and uncommented:

X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes

X11Forwarding yes is the master switch. X11DisplayOffset 10 tells sshd to start looking for display numbers from :10.0. So, the first forwarded connection will use localhost:6010, the second localhost:6011, and so on. X11UseLocalhost yes restricts the X server to only accept connections from the loopback interface, which is more secure. If you set this to no, the X server would be accessible from anywhere on the network, which is generally not recommended.

The security implications of X11 forwarding are important. While the SSH connection itself is encrypted, the X11 protocol is not. This means that if you use untrusted forwarding (-Y), a malicious application running on the server could potentially snoop on your X11 input (like keystrokes) or even inject events into your local X server. Trusted forwarding (-X) attempts to mitigate this by restricting the capabilities of the forwarded X11 client, but it’s not foolproof. Always be cautious about which applications you run with X11 forwarding enabled on untrusted servers.

When an X11 application is launched, the DISPLAY variable is crucial. On the server, it will look something like localhost:10.0 or remote-server:10.0 if X11UseLocalhost is no. The :10.0 part indicates the display number (10, in this case, due to the X11DisplayOffset) and screen number (0). The SSH client on your local machine is responsible for listening on localhost:6010 and relaying the X protocol traffic.

One subtle point is that X11 forwarding is generally quite slow, especially over high-latency networks. This is because X11 is a chatty protocol, with many small messages exchanged between the client and server for each graphical operation. For applications that require rapid screen updates or complex graphics, it can become unusable. Furthermore, X11 security extensions can sometimes interfere with forwarding, leading to applications failing to launch or display correctly.

If you find that -X gives you permission errors or the application doesn’t appear, but -Y works, it’s often because the application is trying to do something that the more restrictive -X security model disallows, but is permitted by the less restrictive -Y model.

The next hurdle you’ll likely encounter is dealing with applications that have complex dependencies or require specific configurations that aren’t present on the server, or wrestling with performance issues on slow networks.

Want structured learning?

Take the full Ssh course →