a3nm's blog

Trying out Wayland

I had been meaning for a long time to try out Wayland, which is designed as a modern replacement for the Linux graphical stack, the X Window System. The main selling point of Wayland for me is that it is better designed in terms of security: processes don't have access to each other's events, unlike X where any process can listen to all events that happen on the server. The lack of security in the design of X is a real problem: no matter which other kind of sandboxing you put in place (e.g., separate users, containers, etc.), you can't prevent a rogue process (e.g., malicious JavaScript using a browser security vulnerability) to access all events and, e.g., log all keystrokes that happen elsewhere in the session.

It is possible to sandbox processes in X by running an X server within the X server, e.g., Xnest, or more commonly Xpra. The way this works is that Xpra acts both as a client for the running X server, and as an X server in which you can run the process that you wish to sandbox: Xpra does not give the running process access to all events of the X server, but only gives it the events that it needs. This is what is done by Subuser, and it is what I did in my old setup to sandbox Skype. However, this is a rather ugly hack, and my experience the performance of the applications running inside Xpra has always been quite bad -- usable for Skype, but not really usable for something like a web browser. (I had tested this long ago by compiling the latest version of Xpra, and I just tested it again with the version packaged by Debian: video playback in a Web browser is not smooth.)

Another solution is what is done by QubesOS, which I haven't tested yet, but seems difficult to separate from the rest of their system (which looks interesting, but I'm not ready to migrate there yet). They are also thinking about using Wayland.

Anyway, Wayland looked like a reasonable solution to the problem, especially as the window manager that I use, i3, has been faithfully adapted to Wayland: sway. So I tried it out, and after some hours it seems to be fairly usable (using the Wayland packaged by Debian testing). This blogpost documents what I did.

Installing sway and its dependencies

Use apt-get to install all requisite dependencies for sway, and its dependency wlroots. The list of the packages that I installed for this is here. We will also need a recent version of libjson-c, because the one packaged by Debian is too old.

Essentially it should be something like:

mkdir ~/apps
cd apps

git clone 'https://github.com/json-c/json-c'
cd json-c
sh autogen.sh
./configure
make
sudo make install
cd ..

git clone 'https://github.com/swaywm/wlroots'
cd wlroots
meson build
ninja -C build
sudo ninja -C build install
cd ..

git clone 'https://github.com/swaywm/sway'
cd sway
meson build
ninja -C build
sudo ninja -C build install

You can then copy your i3 config to sway:

mkdir -p ~/.config/sway
cp ~/.config/{i3,sway}/config

And then you can try running sway in a TTY and see what happens. For me, everything almost worked out of the box: I document here what needs to be adapted. You can also have a look at my sway configuration, with only minimal changes relative to my i3 configuration,

For some reason the font in window titles and in the sway bar was wrong, but this was simply fixed by changing the font names in the config file to "Terminus". I think this is essentially the only change I had to make. When using sway there are some very small differences with i3 (e.g., the formatting of window title bars, or the precise behavior), but honestly the difference is hardly noticeable and I'm rather impressed at how close the adaptation is.

Fixing the keyboard layout

I have my custom keyboard which adapts the US Dvorak layout with some key combinations to write French accented characters. I used to load it with xkbcomp, but this no longer works with Wayland.

What works instead is to write a keyboard description like this and put it in ~/.xkb/symbols. Note that this includes some external files, some of which are in in the systemwide /usr/share/X11/xkb/symbols folder, and others are applying my customizations (see, e.g., this) and they should also go in ~/.xkb/symbols. For some reason, trying to load this keyboard description by running setxkbmap a3nm will not work. However, it works to load the keyboard description in sway, by running XKB_DEFAULT_LAYOUT=a3nm sway or editing the sway configuration file to add an input * block containing the xkb_layout a3nm directive, i.e.:

input * {
  repeat_delay 250
  repeat_rate 50
  xkb_layout a3nm
}

Note that this is also where I configure the keyboard repeat delay and rate.

Many thanks to ManDay for helping me figure this out on the #sway IRC channel.

Switching to apps with native support for Wayland

Most applications do not yet support Wayland, but there is a compatibility layer to run them on Wayland, called XWayland. The way this works is that, when you run an application with no Wayland support (or where Wayland support is not enabled), it will instead be run in an X server that will display in Wayland. For me this worked fine, with no noticeable lags or performance loss. However, all X applications run in XWayland share the same instance (for now), so in terms of security these applications are not better isolated from one another than with X.

So what matters is that applications manipulating sensitive information (e.g., for me, terminal emulators) should not be run in XWayland. This means switching to a Wayland-compatible terminal emulator. My current terminal emulator, rxvt-unicode, is not. For now I just went back to gnome-terminal, which works. Suggestions of terminals to try out (which I haven't tested yet) include:

  • Alacritty
  • Germinal
  • Kitty, which is packaged for Debian but the packaged version doesn't use Wayland (and I didn't find a way to convince it to do otherwise)
  • Termite

Again, thanks for ManDay for suggestions here.

As for other applications I don't care much except for the Web browser. Experimental support for Wayland just landed in Firefox Nightly, you can download it here, uncompress it, and then run it with GDK_BACKEND=wayland ./firefox. This is promising, however from my tests it's still not very stable: opening a second window often made it hang or at least fail to redraw the window that was being manipulated. I hope that this will improve and eventually be available in the normal Firefox releases.

Tearing

Not a point to fix, but just a remark: one of the things that interested me in testing Wayland was that it is supposed to help reduce screen tearing. That said, it seems I'm no longer able to reproduce tearing on X either... Testing on some videos I didn't manage to see any noticeable difference between X and Wayland, so I can't really claim this as a benefit.

In terms of video playback: Debian's mpv in testing is able to use Wayland natively by running mpv --gpu-context=wayland. For me it worked fine but I couldn't see any difference with running it in XWayland. VLC, however, does not use Wayland (I couldn't figure out if there was a Wayland backend). In terms of performance (measured by CPU usage on the same file) for mpv and VLC:

  • VLC on Wayland (in XWayland) or in X, and mpv with hardware acceleration (--hwdec=auto) and with the native Wayland backend or in X, are the most efficient (around 8% CPU)
  • Running mpv with hardware acceleration and in XWayland is a bit worse (15% CPU)
  • Without hardware acceleration, mpv is much less efficient at around 45% CPU, both in X and in Wayland (both for XWayland and for the native backend).

Disclaimer: enabling hardware acceleration for mpv is discouraged.

Taking screenshots

I used to take screenshots with scrot, but it is an X utility, so it will fail silently. Instead, you can use grim, as suggested in the sway wiki.

cd ~/apps

git clone 'https://github.com/emersion/grim'
cd grim
meson build
ninja -C build

You cannot invoke grim without specifying an output file. I preferred scrot's way of automatically generating a filename based on date and time, so you just have to write a wrapper script, e.g., this.

Changing the screen locker

It seems that my previous screen locker (xtrlock) worked with Wayland, but I thought it safer to switch to the one supplied with sway, i.e., swaylock. I customized it to the way I like, e.g., I like to have the possibility of locking my session without hiding what's on the screen (e.g., to monitor stuff). The result is here.

Sandboxing a process

With sway in place, sandboxing a process is rather easy. Let's say that the process to sandbox uses X (not Wayland natively), and that it is running as user sandbox. In Wayland, you just need to issue xhost +si:localuser:sandbox (which will set the access controls for the XWayland server), and then run the process with sudo -u sandbox process as usual: the process will display while running in XWayland, and will be indistinguishable from other performances, in particular I didn't notice any performance problems. (For instance, playing a video on Youtube in Firefox is hungry in terms of CPU, using around 120-150%, but that's the same figure as running Firefox under X.) The sandboxed process will have access to all events in other X applications that use XWayland, but it is not able to access the events of native Wayland applications, and these applications cannot access the events of one another.

You can use xinput test (running in XWayland) to see the events that are communicated to the XWayland X server. In fact, this is the easiest way I found to test if a window was running natively in Wayland or in XWayland.

Remaining issues

To me the main issues that remain with the setup are:

  • General perceived sluggishness. It's hard to explain why but I get the impression that some things are less smooth in Wayland, in particular moving windows around (while in tiling mode), but even displaying text in a terminal emulator just feels a tiny bit slower. I'm not sure if I'm just imagining this, or I'll stop noticing this after a while, or if there's a way to improve performance, or if it will improve over time as the code of sway, wlroots, etc., improves. For now it's just a rather mild annoyance. We'll see whether I stick with Wayland nevertheless or if I get fed up with it and give up.
  • Having to install programs (sway and dependencies) that are not packaged for Debian yet. That said, there has been some interest in packaging sway for Debian, and hopefully it will happen once sway reaches version 1.0, which doesn't seem so far away.
  • Lack of native apps for Wayland, in particular having to go back to gnome-terminal or to try more experimental terminals.
  • The realization that X applications are not isolated from one another as they are all running with the same XWayland server.
  • I did not try using a projector yet. With X you use xrandr (see my guide here), but this doesn't work on Wayland. It looks like you should configure it instead with sway by specifying the coordinates of the various outputs. However, I don't know whether projectors would work fine, given that the list of modes that they support is often pretty erratic, whereas with my laptop's screen, for instance, sway only shows one available mode. Also, there is no support yet for showing the same content on two monitors, e.g., on the screen and on the projector.
  • There is no support for the nm-applet icon to configure NetworkManager, see this issue.

A more subtle point is that there is no discernible benefit to the user in running Wayland: at best it works just like X. For me the main benefit is security, but this is a pretty hard benefit to notice...

Thanks to linkmauve for proofreading and suggestions.

comments welcome at a3nm<REMOVETHIS>@a3nm.net