A ‘portable’ workstation

03 June 2023
Even though the laptop I bought back in 2013 while living in New Zealand has served me well over the years it was not quite up to the task of being a mobile workstation for professional use. The origial idea considered was buying a new laptop for work purposes but after careful evaluation of what specifications were actually needed, a combination of a portable display and a RaspberryPi turned out to be the best solution because the underlying motive is essentually a thin-client for accessing remote desktops. Setting up the RaspberryPi was a bit of a pain which pushed my tolerance for the platform but it turned out to be a workable solution.

The complete workstation setup

The background

Although somewhat underpowered and noticeably slow it was critically not annoyingly slow for the things I was normally using it for, which in short was web-browsing, email, typing out text, and remote desktop access. In practice the only thing really wrong with this laptop was its 1366x768 display resolution which made it difficult to do things like have a decent-sized Firefox and GVim windows next to each other, which is a real killer as all workstations I have ever used in a professional capacity were either Full-HD (1920x1080) or 2K (2560x1440). In addition my laptop uses a 1.5GHz Intel B800 Celeron and basically anything out there that can be bought new would be more powerful. While easy portability was a requirement the use-case was a system which would be setup on a desk, and then left there for the rest of the day if not the rest of the week.

The remote work-room

When I initially returned to the UK I used an office-room at my parents place for work and long story short that room has an Apple Mac Mini that is used whenever I am over there. However even though MacOS is based on BSD Unix it has some irritations such as broken VPN support, with even the Homebrew build of StrongSwan needing a reboot after one connection. In short it needed to be replaced with something running Linux because I was losing patience having to deal with what to me were quirks and outright deficiencies with MacOS, and since my work no longer specifically needed MacOS there was no longer any need to put up with it. The final nail was ditching MacOS would mean only using a single operating system on all computers used by me — namely Slackware Linux — and going single-system in itself has clear advantages.

Mac Mini workstation

There was plenty of spare computer hardware close at hand including one freshly built rack-mount server ready to go, but I also had other requirements such as the need for a mobile workstation that could also be used elsewhere, and these other requirements would have rendered the not-so-portable rack-based system redundant. With a portable workstation at hand there was no point in keeping a Linux system at this location permanently, and if anything having multiple workstations causes extra problems.

Mobile workstation

In the near-future my expectation is spending significant amounts of time working from locations other than the two office rooms — one in my London flat and the other at my parents' place — and that means having a reasonably portable workstation. When looking at laptop models on Scan made me think what my priorities were in terms of specifications, and ultimately all that really mattered was screen size and resolution. My eventual conclusion was to get a portable display and a small form-factor desktop computer, because pretty much all the laptops out there that did not use Intel HD graphics chips — which I have good reason to avoid — were overpriced for my actual needs. In terms of portability the requirement was just ease of movement in itself rather than the ability to quickly change location of working, so initially a mini-PC such as the ASUS PN52-B-S5055MD seemed a good option.

Remote desktops

It was at least seventeen years ago that I first used remote desktop and in the past I have found them lacking in one way or another, with latency being by far the biggest issue, and it is not helped with the likes of MacOS doing various GUI animations that tend to stress the network video pipe-line. However with my current setup of IceWM within a VNC session and IPSec running on systems I have exclusive use of remote desktops are good enough for work even over a mobile phone wireless hot-spot, so it is possible to go down the thin-client approach where the only programs run locally are graphically-intensive programs like Gimp and programs like KiCAD that need OpenGL. A RaspberryPi seemed the perfect fit for such a role as a thin client and as a bonus it was possible to run it off a USB power pack, allowing the whole workstation without mains power.

RaspberryPi setup

Since I already use Slackware 15.0 on my other systems I originally opted to install Slackware ARM for RaspberryPi instead of using any of the choices offered by the preinstalled NOOBS (New Out Of the Box Software), for which the instructions used to install the RaspberryPi IPSec server still apply. However since the 15.0 installer only comes in 32-bit flavour and some important programs such as Firefox are no longer built for 32-bit targets I ended up once again installing the developmental version. For bonus annoyance at time of writing the SARPi website has broken links so instead the following can be used to grab whatever version is currently available:

lftp -c mirror https://slackware.uk/sarpi/rpi4/current-armv8/img/

The flashing of the MicroSD then uses this updated command — note the filename will likley be a little different but the correct one will have the .img.xz extension.

xz -dc sarpi4_64-installer_slackcurrent_20Apr23_sp1.img.xz | dd of=/dev/sdb bs=65536

After these two things have been done the steps of network connection setup onwards are the same, although due to either the SD Card having poor write performance and/or the server with the installation files being slow the installation took a suspiciously long two hours to complete. The sub-sections below are bare-bones instructions and omit things such as setting up locale that are covered in either the desktop or laptop Slackware 15 installation articles.

Don't reboot at end of installation

This is not new but it is a major gotcha. Once the installer has installed all the packages and done the network setup, drop to a shell rather then reboot because a few extra manual steps need to be done othewise the system will be unbootable. Basically the stock Slackware ARM kernel packages need to be removed and some other RaspberryPi packages installed in their place:

ROOT=/mnt removepkg kernel_armv8 kernel-modules-armv8 mount -t vfat /dev/mmcblk0p1 /mnt/boot rm /mnt/boot/initrd.gz ROOT=/mnt installpkg /rpi-extra/kernel* /rpi-extra/sarpi4_64-*

After the above the system can then be rebooted. As a nice touch one of the packages installed at this stage enables root logins over SSH by default. Automatically going into XDM on system boot rather than needing to run startx can be done by making the following change to /etc/inittab:

# Default runlevel. (Do not set to 0 or 6) id:4:initdefault:

Setting up XDM and IceWM

On RaspberryPi both SDDM and Xfce are broken in ways that make them unusable so instead I opted to use XDM and IceWM, which is probably the right things to do as the latter combination is substantially less resource-intensive. IceWM needs imlib2 which these days has a SlackBuilds script but otherwise is a basic tarball installation, although in my case I also include two customisations: A theming change, and stopping workspace switching from wrapping around. If not interested in these changes then the IceWM SlackBuild script will likley suffice.

cd icewm-2.9.5 patch -p0 < icewm.patch patch -p0 < icewm2.patch ./autogen.sh ./configure --prefix=/usr/local make make install

The hacks I used with Slackware 14.2 to add reboot & shutdown buttons to XDM still work as-is, but otherwise the only thing that needs doing is setting up ~/.xprofile to call icewm-session:

#!/bin/bash exec dbus-launch --exit-with-session /opt/icewm/bin/icewm-session

Not sure when this changed from ~/.xinitrc as I stopped using XDM for desktop installations a while back.

Building Strongswan

The Strongswan Slackbuild has everything that is required but needs one change because the aesni plugin makes use of CPU flags that enable CPU extensions that do not exist on ARM processors resulting in the following error:

Making all in plugins/aesni CC aesni_key.lo gcc: error: unrecognized command-line option '-maes' gcc: error: unrecognized command-line option '-mpclmul' gcc: error: unrecognized command-line option '-mssse3' make[5]: *** [Makefile:616: aesni_key.lo] Error 1 make[4]: *** [Makefile:2273: all-recursive] Error 1 make[3]: *** [Makefile:1353: all] Error 2 make[2]: *** [Makefile:539: all-recursive] Error 1 make[1]: *** [Makefile:604: all-recursive] Error 1 make: *** [Makefile:515: all] Error 2

This plugin can be disabled by changing --enable-aesni around line 71 to --disable-aesni and then running the build script manually. I am not sure if SboPkg provides a way of specifying this parameter.

NetworkManager Strongswan GUI plugin

Rather than using a root shell command-line to start and stop VPN connections it is so muc nicer to grab Strongswan's NetorkManager plugin, which adds Strongswan as a VPN options to the NetworkManager applet. It is another fairly straightforward tarball install and these parameters match what the Strongswan Slackbuild uses:

wget https://download.strongswan.org/NetworkManager/NetworkManager-strongswan-1.6.0.tar.bz2 tar -xzvf NetworkManager-strongswan-1.6.0.tar.bz2 cd NetworkManager-strongswan-1.6.0 ./configure --sysconfdir=/etc --prefix=/usr make -j4 make install

One slight gotcha: Dut to PolKit restrictions under Xfce pops up an authentication dialog asking for the root password but under IceWM just fails almost silently, and the work-around is to nobble the permissions to allow any user to perform them. Under /usr/share/polkit-1/actions/ the file that contains the relevant permissions is org.freedesktop.NetworkManager.policy and in it the relevant sectiom is the following:

<action id="org.freedesktop.NetworkManager.settings.modify.system">

A bit further down after many lines of messages in different languages is the following:

<defaults> <allow_any>auth_admin_keep</allow_any> <allow_inactive>auth_admin_keep<allow_inactive> <allow_active>auth_admin_keep<allow_active> </defaults> </action>

The setting auth_admin_keep means asking the user for the root password if they have not already been asked for it recently. Change them to yes to bypass this and grant the permissions immediately.

A persistent clock

A major headache with RaspberryPi is the lack of any persistent time-keeping so when I was reconfiguring my personal LAN for power-cut resiliency it required some elaborate start-up scripts that allowed for the relative time it took for external internet connectivity tor e-establish itself, so that NTP could be used to set the clock. That was fine for a system that was expected to stay up indefinitely but a pain for one that may well be started and shut down on a daily basis. Fortunately there are many third-party real-time clocks available for the RaspberryPi and here ones based on the Analog Devices DS3231 time-keeping chip was used. While it was not the Chronodot module the setup instructions are good for anything based on the DS3231 and quite a few other chips as well.

Clock module in place

There are two ways to setup the hardware clock but the one summerised here is the one that uses Device Trees. In /boot/config.txt the following lines need to be either uncommected/added and set to the following options:

dtparam=i2c_arm=on dtoverlay=i2c-rtc,ds3231

Once this is done after a reboot hwclock should operate as it does on desktop-based Slackware, where --hctosys reads the time from the hardware clock chip and --systohc writes to it. These are called in the standard startup/shutdown scripts so after initial setup they will not need to be used manually.

Power consumption

With both the portable display and the RaspberryPi powered via USB one consideration is whether they could be powered from portable power supplies, and based on power readings it is something of a close call. The display is multi-voltage and it operated at 12 volts when using the included power adapter but when plugged into my Anker power bank it drew a fairly consistent 1.2 amps at 5 volts, which is pretty high for USB power and exceeds the 500mA limit that is standard for most USB ports. The RaspberryPi itself typically drew 450-550mA but it did peak at around 780mA and a reasonable expectation is for it to draw a full amp if it had USB periperals plugged in as well.

Power meter

While it is possible to supply the whole setup from a USB power bank it has to be one of those more powerful ones that can supply a sustained two amps per port and I am not sure if any of those on the market are really intended for such intense use. Yes it is all well within the notional specifications but given the choice it would be preferable to run it all of mains power.

Software issues

The SARPi project only provides 32-bit packages and installers for the stable versions of Slackware whereas the current (i.e. developmental) release is now exclusively 64-bit, which is presumably due the upstream Slackware ARM project has forked off 64-bit development into what is instead called Slackware AArch64 and it is the latter that the SARPi project tracks, whereas the SARPi 15.0 packages are derived from the stable Slackware ARM 15.0 release which probably never had 64-bit builds and I suspect never will. In practice this means the 15.0 SARPi release is de-facto legacy because a lot of software is only available as 64-bit builds, and there is at time of writing no stable 64-bit SARPi release. This is a major source of potential headaches.

Pre-built AArch64 binaries

I have no idea how official or otherwise it is but there is a repository of pre-built packages built for Slackware AArch64 that is in much the same spirit as AlienBOB, and includes programs such as LibreOffice and Chromium. Firefox and Thunderbord are available but I find these two programs from Mozilla are that bit too resource-hungry for running on a RaspnerryPi. As is typical with the latter, software available via this route are things that are non-trivial to get built and without these pre-built packages I doubt the viability of RaspberryPi for the purpose I got this one for.

SDDM display manager on RaspberryPi

In the past I have normally installed all packages except KDE and Y (games) and then manually installed SDDM but on RaspberryPi SDDM seems to be completely broken even if the entire KDE package is installed. This affected both the 15.0 and developmental builds and while I suspect the problem is the X-server not being properly started there was only so much effort I was willing to expend tracking down the problem. This is a bog-standard install on unexotic hardware so I suspect it may be completely untested, which given that KDE is not exactly light-weight is perhaps not too surprising.

Xfce breakage on RaspberryPi

While Xfce otherwise works fine if it is left for a while it stops responding to keyboard and mouse input — the mouse cursor still moves around and while the display is not itself frozen as the clock still ticks forward, mouse clicks and keyboard button presses have no effect. The only thing the keyboard responds to is switching between virtual desktops and killing the X-Server using Control-Alt-Backspace which in practice is as good as resetting the machine.

Building SlackBuilds

In most cases building using SlackBuild scripts via SboPkg “just works” but in some cases the scripts need to be manually downloaded and slightly modified before being run. The typical problem is scripts not recognising the aarch64 architecture type so it assumes a 32-bit architecture and as a result uses /usr/lib rather than /usr/lib64 which then causes things to fail somewhere down the line, and the offending portion of the script is typically along the lines of the following:

if [ "$ARCH" = "i586" ]; then SLKCFLAGS="-O2 -march=i586 -mtune=i686" LIBDIRSUFFIX="" elif [ "$ARCH" = "x86_64" ]; then SLKCFLAGS="-O2 -fPIC" LIBDIRSUFFIX="64" else SLKCFLAGS="-O2" LIBDIRSUFFIX="" fi

The fix is to change that final LIBDIRSUFFIX="" to LIBDIRSUFFIX="64". Some packages that failed to build were fixed by removing --build directives passed to ./configure and just let the system fall back to the default compiler. A few other tarballs included a horrendously out-of-date config.guess resulting in the following error:

checking whether make sets $(MAKE)... yes checking build system type... ./config.guess: unable to guess system type

Getting around this error necessitates recreating the tarball with an updated version, the example below for gtksourceview giving an overview of the procedure.

wget http://ftp.acc.umu.se/pub/gnome/sources/gtksourceview/2.10/gtksourceview-2.10.5.tar.gz tar -xvf gtksourceview-2.10.5.tar.gz cd gtksourceview-2.10.5 wget "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" -O config.guess cd .. rm gtksourceview-2.10.5.tar.gz tar -czvf gtksourceview-2.10.5.tar.gz gtksourceview-2.10.5

Installing VTE

The SlackBuild script for VTE (Virtual TErminal) uses a very old release of the upstream tarball and since then the latter has switched from autotools to Meson so it need to be manually built. This is a dependency of Gnome Terminator and getting this dependency installed is the only non-trivial part of getting Terminator up and running. At time of writing version 0.72.1 is the latest and since Slackware does not use SystemD the following change will need to be made to meson_options.txt:

option( '_systemd', type: 'boolean', value: false, description: 'Enable systemd support', )

Once this change has been made it is ready to configure and build. The settings below are ones extracted from the SlackBuild script so everything goes into the right place.

meson _build --prefix=/usr --libdir=/usr/lib64 --sysconfdir=/etc --mandir=/usr/man ninja -C _build sudo ninja -C _build install

At this stage check that the Python bindings which utilise Gobject-introspection have been installed, as these are needed to install Terminator.

ls -ltr `cat _build/meson-logs/install-log.txt | grep gir-`

Broken clang

(Added 5 July 2023)
While trying to build potrace (a dependency of Inkscape) the configure script fails while checking clang, outputting the the following message snippet:

checking for clang... clang checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... configure: error: in `/tmp/SBo/potrace-1.16': configure: error: cannot run C compiled programs. If you meant to cross compile, use `--host'. See `config.log' for more details

Digging into /tmp/SBo/potrace-1.16/config.log gives the game away. The configure script is trying to build and run conftest but the resulting binary cannot be run:

configure:3272: checking whether we are cross compiling configure:3280: clang -o conftest -O2 conftest.c >&5 configure:3284: $? = 0 configure:3291: ./conftest ./configure: line 3293: ./conftest: cannot execute: required file not found configure:3295: $? = 127 configure:3302: error: in `/tmp/SBo/potrace-1.16': configure:3304: error: cannot run C compiled programs. If you meant to cross compile, use `--host'.

After writing my own test C program and compiling it with both GCC and Clang it is clear that clang is broken. The workaround is to override the build script to use GCC instead:

CC=gcc ./potrace.SlackBuild

Relocation issues

(Added 5 July 2023)
This is a problem that came up when building Inkscape which makes use of a lot of nested dependencies. When building relocatable code dependent code it links to also needs to be relocatable otherwise errors such as the following get thrown up:

/usr/bin/ld: /usr/lib64/libdouble-conversion.a(string-to-double.cc.o): relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `_ZNSt5ctypeIcE2idE@@GLIBCXX_3.4' which may bind externally can not be used when making a shared object; recompile with -fPIC

The solution is what it says in the error message, namely to use the -fPIC compile option, which can be done using the following build script modification. Once this has been done and the dependency rebuilt & reinstalled the down-stream build script should work. Most SlackBuilds I built without this flag but after seeing this error I suspect it should be added for at least all libraries as a matter of routine.

else SLKCFLAGS="-O2 -fPIC" LIBDIRSUFFIX="64" fi

Remarks

Particularly with the problems SDDM/Xfce had the setting up seriously tested my tolerance for dissatisfaction and I had doubts over whether the RaspberryPi was really any more powerful than my laptop, but in the end everything I needed worked as desired. There was the mobility and relatively low cost but without an unreasonable sacrifice in performance and functionality. A major plus was getting Chromium to actually sync with my Google account, although I have no idea whether this is something Google are now turning a blind eye to or whether the API keys are ones that should not be shared but their use is managing to stay below the radar.