1. Introduction

We’re used to working with a Graphical User Interface (GUI) and starting applications with its elements. Sometimes, however, we have to use a command from a terminal and may experience messages like No X11 DISPLAY variable was set or Error: Can’t open display. In this tutorial, we’ll look at how to solve such issues.

2. Definitions

X11 or X Window is a graphical system for most flavors of UNIX. It started its life in 1984 at the Massachusetts Institute of Technology (MIT) with Project Athena. At MIT, several hundred heterogeneous workstations were scattered on the campus. The idea was to provide a window system to write applications to run on any station. It should be possible to access applications on any workstations through the network and see graphical output locally.

2.1. Client-Server Model and Core X Protocol

For device-independent applications, the details of device access are hidden in the X Server. It provides all basic windowing mechanisms by handling connections from X applications, demultiplexing graphics requests, and multiplexing input from a keyboard, mouse, etc., back to the application. An application connects to the X Server through interprocess communication (IPC) path, either over shared memory or a network protocol like TCP.

Such an IPC path is called the X Client. Since most applications open only a single connection, we often call the application itself the X Client. The communication protocol between an X Client and an X Server is called the X Protocol. It is the fundamental layer on which other tools are built.

2.2. What Does DISPLAY Mean?

To create windows on the screen and to receive events, we should establish a connection to display. In terms of X, the display consists of one or more screens, a single keyboard, an (optional) pointing device, and the X Server. By default, an application uses the display name stored in the shell environment variable DISPLAY; this is a string in the following format:

Host_Name:[:]Display_Number.Screen_Number

  • Host_Name is the name of the host on which the display is physically attached.
  • :[:] We use double colon only in the case of networking with DECnet.
  • Display_Number is the zero-based number of the display server on that host machine. A computer can have more than one running server.
  • Screen_Number (also starts at 0) specifies the screen to be used on that server. A single X server can control many screens.

3. Knowing and Setting DISPLAY

The simplest way of knowing our current DISPLAY is by using echo this variable or grep it from the list of all shell variables that the set command gives:

$~ echo $DISPLAY 
:0
$~ set | grep DISPLAY
:0

In our example, Host_Name and Screen_Number are missing, which is typical. It means X clients will use the local X server and IPC transport for communications. The obtained value is equivalent to unix:0.0 or :0.0, and unix here means X clients use IPC. If there is a Host_Name before the colon, X server and X client communicate via TCP transport.

Usually, the DISPLAY is already set for us by the system. In some cases, however, we should do it manually. Determining it by hand is the same as for any other shell variables. Here is an example of setting it up directly:

$~ export DISPLAY=unix:0.0

To test our DISPLAY setting, we usually try to run a simple program like xeyes or xclock.

4. DISPLAY is not set and Similar Problems

If we start, for example, xeyes from a local console and it runs without any murmur, the DISPLAY is set correctly. If we remove the DISPLAY with a command unset and re-run xeyes, it will complain:

$~ unset DISPLAY
$~ xeyes 
Error: Can't open display: 

Applications using java will also complain:

$~ java -jar Paint.jar 
Exception in thread "AWT-EventQueue-0" java.awt.HeadlessException: 
No X11 DISPLAY variable was set, but this program performed an operation which requires it.

Popular browser chromium will lament with a huge output message that starts similar to this one:

$~chromium
[6864:6864:1126/221702.545428:FATAL:ozone_platform_x11.cc(232)] Check failed: x11::Connection::Get()->Ready(). Missing X server or $DISPLAY

In all these cases, we meet the keywords X server, DISPLAY, that are incorrect or missing.

The output of Qt programs, however, is more complicated. It does not have these keywords because Qt is a framework for multiplatform applications and has lots of dependencies:

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.

So, the error message depends on the software. Solving this problem, in turn, depends on where we want to run an X client, on a remote machine, or a local one.

5. Starting a Remote X Client

The best way to start a remote X client is to use ssh with the so-called X Forwarding to direct the X protocol packets over the same connection we use for the commands. So, we’ll ssh -X our_remote_host and, after logging in, we start X11 applications. That’s all, of course, if the ssh daemon sshd runs on the remote end and its configuration file, sshd_config, includes the line X11Forwarding yes. The typical DISPLAY value is localhost:10.0:

tiger@home:~> ssh -X [email protected]
Last login: Wed Dec  1 14:32:07 EET 2021 from home on pts/4
Have a lot of fun...
tiger@gatti:~> set | grep DISPLAY
DISPLAY=localhost:10.0

Instead of -X, we may use the -Y key, but it makes sense only if this sshd is suitably configured. These two keys are for untrusted and trusted connections correspondingly. Trusted ones have full access to the entire DISPLAY. They can do keylogging, screenshots, and input into other programs’ windows; it can use all X server extensions like accelerated graphics. Trusted connections may be suitable for running applications smoothly but undoubtedly nasty for security.

If X server accepts TCP connections, we can use the xhost method. We’ll show it with an example.

Supposing, we’re sitting near the host jaguar and want to connect and run X client on the remote host tiger, but output its result locally, on jaguar.

Before establishing a connection to the remote host tiger, we need to add it to the list of allowed ones with the xhost command, xhost +our_remote_host:

$~ xhost +tiger
tiger being added to access control list

The xhost+ will also work. Its use, however, is dangerous because clients can connect to your DISPLAY from any host, making a security hole.
Having logged to tiger, we set up DISPLAY to output on our local machine, jaguar in our case:

$~ export DISPLAY=jaguar:0.0

After finishing and logging off, we remove the host from the list:

$~ xhost -tiger
localhost being removed from access control list

However, this method won’t work out of the box on modern distributions because TCP connections to the X server are forbidden by default.

6. Starting on a Local Machine

Usually, we start applications from GUI directly, but in some situations, we do it from a konsole or terminal like xterm, gnome-terminal or yakuake. If a local application complains about DISPLAY, we can try to use another type of terminal.

We may face errors with the DISPLAY if trying to run an application after the sudo command. Of course, to solve the problem, we can ssh -X user@localhost, but if this is not possible due to sshd configuration restrictions, we can also use either the xhost or xauth method.

6.1. Using xhost Method

We’ll use an example to illustrate the method. We logged as a user panter. Assume, panter needs to execute a command as another user, lion. To preserve the DISPLAY value, we’ll add an option -E (or –preserve-value), but this is not enough:

panter~> sudo -Eu lion xeyes 
[sudo] password for lion: 
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Error: Can't open display: :0

Printed information about authorization is our key to resolving this issue. It hints that we need to add the lion to the list of allowed users. So,  before sudo, we’ll do it:

panter~> xhost +si:localuser:lion
localuser:lion being added to access control list

In this command, the key si means X server will perform this connection.

This time we can run our X application. When it finishes, we remove user lion from the list:

panter~> xhost -si:localuser:lion
localuser:lion being removed from access control list

6.2. Using xauth Method

We can use the method with xauth. It allows access to anyone who knows the secret key. This key is called a magic cookie or authorization record, and the authorization scheme is named MIT-MAGIC-COOKIE-1. We’ll also show how to use it with the same example.

We start by getting our DISPLAY and the secret key with the xauth command:

panter~> set | grep DISPLAY
DISPLAY=:0
panter~> xauth list $DISPLAY
panter.cats.edu/unix:0  MIT-MAGIC-COOKIE-1  abf87ea2c8a4ed7f41ce8e7b99047870
#ffff##:0  MIT-MAGIC-COOKIE-1  abf87ea2c8a4ed7f41ce8e7b99047870

Then, we switch to the lion and set up DISPLAY (or use the -E key in sudo, as in the example above):

lion:~> export DISPLAY=:0

In addition, we note xauth output; xclock can’t run.

lion~> xauth list $DISPLAY
xauth:  file /home/lion/.Xauthority does not exist
lion~> xclock
Authorization required, but no authorization protocol specified
Authorization required, but no authorization protocol specified
Error: Can't open display: :0

Furthermore, we export the secret key; xclock can run:

lion~> xauth add $DISPLAY . abf87ea2c8a4ed7f41ce8e7b99047870
xauth:  file /home/lion/.Xauthority does not exist

After finishing, we remove the key:

lion~> xauth rem $DISPLAY

Missing the $HOME/.Xauthority file is not an error. If it is missing, the file will be created automatically.

The xauth method we can also use for running X clients on a remote host. This method is much more secure than the xhost one.

7. Notes About Wayland

A new communication protocol between a display server and its clients, Wayland, getting more popular.

Using it may also cause some complaining about DISPLAY. The best way to avoid such problems is using the ssh method. Note, however, that not all X11 applications will run under Wayland.

There is a feature: a Wayland ssh client may require a nested X server like Xephyr, and a Wayland ssh host may need the preset string before an application command, GDK_BACKEND=x11. Xephyr becomes our X11 display on a client, and we point Wayland host to use an X11 to run the application on the Xephyr window.

8. Conclusion

In this article, we observed X Window System principles and learned the meaning of the DISPLAY shell variable and its role in the X Window System. We solved the problems like Error: Can’t open display. To run a GUI on a remote machine and get its output locally, we used ssh with the -X or -Y key. If both X server and X client run on the same machine, we may need to set the shell variable DISPLAY and permit the server to use it locally.