Monday, June 1

Linux Fu: Raspberry Pi Desktop Headless

It seems to me there are two camps when it comes to the Raspberry Pi. Some people use them as little PCs or even laptops with a keyboard and screen connected. But many of us use them as cheap Linux servers. I’m in the latter camp. I have probably had an HDMI plug in a Pi only two or three times if you don’t count my media streaming boxes. You can even set them up headless as long as you have an Ethernet cable or are willing to edit the SD card before you boot the machine for the first time.

However, with the Raspberry Pi 4, I wanted to get to a desktop without fishing up a spare monitor. I’ll show you two ways to get a full graphical KDE desktop running with nothing more than a network connection.

The same principle applies to most other desktop environments, but I am using KDE and Ubuntu on the Pi, even though something lighter would probably perform better. But before we get there, let’s talk about how X11 has had a big identity crisis over the years.

The Plan

There are many ways to remotely access X programs, many of which are rarely used today. However, for this purpose, we are going to use SSH tunneling along with some special tricks to get the entire desktop running. It is easy to just run a single X program over SSH, and you’ve probably done that often. If so, you can skip to the next section.

If you haven’t done SSH tunneling before, don’t worry; it is easy. When you start ssh to the Pi, just include the -X or -Y option. You can also configure that in the ssh config file (ForwardX11 yes or ForwardX11Trusted yes) so you don’t have to type it in all the time. The SSH programs also have to be configured to allow that, but that’s usually the default behavior.

Consider this command.

ssh -X me@mypi.local konsole &

That would run konsole on your Pi, but the screen appears on your main machine. That’s fine, but it isn’t the entire desktop experience. Plus, some programs really expect support from other services that a desktop environment like KDE starts. So the trick is how to start the desktop?

The Tunneling Desktop

If you want to start a modern version of KDE, you can run startplasma-x11. The obvious thing to do is to try that over an SSH connection with X forwarding. That won’t work, though. Your screen is already managed by something else — maybe even KDE.

The trick is to create a new X server just for the Raspberry Pi. While you could start a new server, it is easier to create a fake server that lives in a window on your main server’s screen. There are two ways to do this: Xnest and Xephyr. Xnest is very old and creates a simple server with very few features. It depends on the host X server for most functions. Xephyr is more modern. It provides lots of modern features no matter what the host server provides. It basically uses the host server as a frame buffer.

Of course, this all assumes you have the KDE desktop installed on the Pi. A simple apt install for kubuntu-desktop will take care of that if you haven’t done it already.

Using XNest

The trick to XNest is that it creates a new server that just happens to draw on the original server — they are nested. There are a lot of options, but usually, it is sufficient to just run the program with a new (unused) display number.

Xnest :11

Notice the first X is uppercase. You might want to set the size:

Xnest --geometry 800x600 :11

You could run this on your local machine or from the Pi. As long as you have X tunneling set on your SSH connection, it won’t matter. But there’s still a problem.

Try running:

DISPLAY=:11 startplasma-x11

Most likely, it will start a few things and will appear to work. But at some point, you’ll get a fatal error and nothing will happen. The problem revolves around trying to render on the remote GPU. This may not be a problem with some lightweight desktops, but KDE stops.

The trick is you need to set one environment variable to tell Qt not to try to do hardware rendering:

QMLSCENE_DEVICE=softwarecontext startplasma-x11

That does the trick and now you can have a full KDE desktop running on the Pi and showing on your main monitor! You aren’t going to want to watch videos on it or play games, but otherwise it is perfectly serviceable.

I wrapped it all up in a script:

#!/bin/bash
Xnest -geometry 3840x2050 :2 &
export QMLSCENE_DEVICE=softwarecontext
DISPLAY=:2 startplasma-x11 &

Or a bit fancier:

#!/bin/bash
X="${1:-1024}"
Y="${2:-768}"
S="${3:2}"
Xnest -geometry ${X}x${Y} :$S &
export QMLSCENE_DEVICE=softwarecontext 
DISPLAY=:$S startplasma-x11 &

Using Xephyr

Xephyr isn’t usually installed and you may have to look for what package it is on your operating system. For Ubuntu, the package is xserver-xephyr. For some reason, running it on the Pi just caused the program to stall and do nothing — at least on my setup. However, in theory, you should be able to use it as a replacement for Xnest.

What I did instead was created the server on my local machine and then asked the Pi to use it. So:

 
Xephyr :1 -screen 1200x720 -resizeable &
DISPLAY=:1 ssh -X ubuntu@192.168.1.39 "QMLSCENE_DEVICE=softwarecontext startplasma-x11" &

This works, but it is very slow. Xephyr does a lot of work on its own, so the Xnest solution is faster.

The X That Was

When X11 started, it had a grand plan. From your login screen you should be able to log into any computer you had access to. Then, you should be able to run programs on your screen from any computer, not just the one you were using as your main computer. This still works, sort of. However, most Linux distributions aren’t really set up to take full advantage of it.

The trick to how things were supposed to be is the DISPLAY variable. That sets where the X clients (programs) connect to an X server (your screen). You can set that to be remote. For example:

DISPLAY=mydesktop.local:0 konsole

In theory, that should have much the same effect, but that assumes your network is open on ports around 9000 and that your Xserver is open or there is a peer authentication scheme set up.

In fact, you can take many greeters (the program that you give your user name and password to) and reconfigure them to listen for network connections and create network connections to other machines, just like the X11 designers intended. But most distributions have that turned off and I’m not even sure if some of the newer greeters offer that option at all.

In modern usage the X11 system has turned into a quasi-display driver for your monitor, and that’s sad. X has so many capabilities that about 90% of the Linux world do not use. (Recalling that 88.35% of all statistics are made up on the spot.)

If you want to try setting it up the old way, have a look at xhost, xauth, and be prepared to change your X server start up to remove the flag that prevents it from listening to TCP sockets. It can be done. Of course, security over the network might not be what you want. Tunneling over SSH solves that in a single line, though.

The Solution

Even after all this work, I’m still just going to log into my Pi from the command line for most jobs. I might include X11 forwarding so I can run the odd program on my desktop. However, for the times you really want to work with the entire desktop, the Xnest solution works well enough. Xephyr was slow. I’m not sure if it would have been faster if it had run on the Pi, but that never worked for me. I suspect it is some interaction with the NVidia display drivers, but I didn’t track it down.

Meanwhile, if you do try this, consider making the window as large as you can and parking it on a virtual desktop. This is a neat solution since you can flip desktops to access the Pi or your regular computer. Add another desktop with VirtualBox running Windows and you have the operating system trifecta. If you use Wayland, this may still work using Xwayland, but I haven’t tested it out.

If you really want to replace your desktop with a Pi, you might want to consider this trial. Or maybe you’d prefer a laptop.

No comments:

Post a Comment