A Minimalistic 64 bit Web Kiosk for RPi 3

Update: don’t miss the NodeJS configuration as follow up

Update 2: BENJA is back, as DIY project

For those who don’t know me, I’ve created a while ago a project called B.E.N.J.A. which is unfortunately slowly dying due lack of time, lack of contributions, and lack of money (TL;DR it’s not sustainable).

That project idea is that you flush an SD card, you develop on your laptop, and when you put it in one of those supported SBCs, it starts Electron in Kiosk mode with node running and, where possible, hardware acceleration.

While its cool to run Electron, it’s also not always necessary and few developers were more than happy to use Qt5 Web Engine based alternatives, more suitable as example for video playback performance, or basic WebKitGtk, GJS driven, alternative, since it runs everywhere, even on Pi 0.

There are numerous applications for Web based Kiosk SBCs and not necessarily related to the Internet of Things + you just need a modern browser to have fun developing snappy interfaces, and WebKitGTK is one of the most advanced out there, with native support for Custom Elements, ESM Modules, all the modern JS syntax you want, and through GJS you can interface yourself directly with the Operating System or the GLib namespace, something most of the time is just about enough to complete a few tasks.

ArchLinux to the rescue!

There’s nothing more convenient than ArchLinux ARM to create these kind of systems for these simple reasons:

  • every used library or software is the most recent one. No need to wait 6 months before you get next version of Node or GJS, as example
  • it’s super lightweight. It works on a 4GB SD card leaving room for a lot of extra software
  • it’s super fast on boot time thanks to its minimalistic software selection
  • it works on ARMv5, ARMv6, ARMv7, and ARMv8 … that covers pretty much every board out there and, in the case of the Raspberry Pi 3, you can finally use all its native 64-bit powers right away 🎉

Excited to get started?

Step #0: requirements

In order to succeed with this installation you need:

  • a Raspberry Pi version 3, the 64 bit one
  • a network cable, or WiFi router, connected to the internet

Step #1: create the bootable SD card

If you follow these instructions there’s not much that could go wrong except you need to download the ArchLinuxARM-rpi-3-latest.tar.gz and not the version for the rpi-2.

That being said, pretty much everything I’ve done for the RPi-3 should work on both RPi-0, RPi-1, and RPi-2 as well.

Step #2: setup a different password

As soon as you boot your Raspberry Pi 3 and login as root with the password root, you should change password for both root and alarm user.

So, to be clear, login typing root, then typing root again. Now:

# change root password
passwd
# change alarm user password
passwd alarm

This is very important because otherwise anyone can access via ssh your device if discovered through the same network. There have been already various IoT security related scandals, I don’t want to contribute more 😉

Step #3: connect to the internet

If you are using a network cable there’s most likely nothing to do.

Just type ping 8.8.8.8 and you should see information flowing.

Stop it there via ctrl+c command.

If you want to use the Wi-Fi instead, type wifi-menu, find your one and point at it via arrows, press enter to setup the password.

If you want to use that automatically, you need to type the following after:

netctl enable wlan0-YourWiFi-NAME

Feel free to double check via ping 8.8.8.8 that you reach the internet.

Step #4: install bare minimum system for a Kiosk

I want to be honest with you: the ideal Kiosk for these little boards would be a lightweight and fully Hardware Accelerated Weston compositor to run Gtk+.

Unfortunately I could not find a way to have a Kiosk mode in Weston 3, so I’ve ditched it in favor of the good old Xorg, which is easier to configure for Kiosk.

Once you login as root, you could simply follow these instructions, hopefully learning and/or understanding what are you doing, or you could be very lazy and write this instead:

bash <(curl -s https://archibold.io/kiosk/pi3)

which will basically execute right away everything explained in here.

Bash in a nutshell

If you are choosing to type instructions manually, here a list of essential hints you need to keep in mind with shell or bash:

  • single and double quotes are very different. I’ve used single quotes here per each command, just stick with those.
  • if you start a string via single/double quote, you can just press return to reach the new line. You’ll need to close such quote eventually to execute or show anything on console. Just follow my code here.
  • if for some reason you need to edit or double check a file, you can either use vi or the more beginner friendly nano software ( nano file.txt )
  • everything is case sensitive and every char matter in my scripts but you can omit writing comments, which are those lines starting with #

That’s it. If you pay attention to every char I’ve written, you should do fine.

Update the system and its pre-installed software

ArchLinux has a packages manager called pacman. There are many things it can do but today we’ll see just a few.

# update the system and the mirrors list
pacman -Sy --needed pacman-mirrorlist
# update the rest of the software
pacman -Su

The -S option is to install software. Followed by ay, it also updates modules info, while followed by an u it updates all packages already installed.

The --needed command ensure you’re not re-installing stuff already there.

Give GPU more memory and enable HW Acceleration

By default, the Raspberry Pi uses a very little amount of RAM for its GPU, and it doesn’t Hardware Accelerate it. To give it something like 256 MB of memory, you need to configure it at boot time.

# enable GPU memory and vc4
echo '
gpu_mem=256
dispmanx_offline=1
dtoverlay=vc4-fkms-v3d
dtparam=audio=on
'>>/boot/config.txt

But this is not enough. There should be enough memory allocation and the way to set it up is via cma but to change this setting we need some tool.

# modify boot.scr to reserve cma memory and make the boot silent
pacman -S --needed uboot-tools
sed -i 's/rootwait/rootwait cma=256MB/' /boot/boot.txt
mkimage -T script -C none -n "RPi3 VC4" -d /boot/boot.txt /boot/boot.scr

If you’d like to have a less loud boot, you can put quiet loglevel=0 splash instructions between rootwait and cma=256MB.

I’m not even sure you actually need 256MB for the cma, but it works so …

Automatic login

Once the Pi 3 is switched on, nobody wants to put credentials on a terminal to launch the kiosk mode, right?

# automatic login
mkdir -p /etc/systemd/system/getty@tty1.service.d
echo '[Service]
ExecStart=
ExecStart=-/usr/sbin/agetty -nia alarm %I
'>/etc/systemd/system/getty@tty1.service.d/override.conf

This is the easiest way to login the alarm user without asking a password.

Video driver

Despite the late 90’s look of their website, the Mesa 3D Project brings graphics and Hardware Acceleration to most mainstream graphic cards and systems.

pacman -S --needed mesa libva-vdpau-driver libva-mesa-driver

On regular Intel/AMD hardware, you might want to use mesa-vdpau too.

X11 / Xorg

To have a graphic environment, instead of a basic terminal, you can install the following packages:

pacman -S --needed xorg-server xorg-xinit xorg-xset xf86-video-fbdev

The server takes care of the rendering, while xinit allow to start a session via startx command and an .xinitrc file in the user folder.

The xset gives us the ability to configure the behavior, as example disabling sleep for the screen, it’s a Kiosk!

Audio utilities

I’m not sure audio works as expected, but whenever I’ll figure it out it’s good to have common audio utilities already available.

# install alsa utils
pacman -S --needed --noconfirm alsa-utils

Basic Graphical UI

With GJS and a standard theme for cursors, icons, and/or colors, we can already create a Kiosk mode without needing any browser: it’s Gtk+ !

# install Gtk via GJS bindings + standard themes
pacman -S --needed gjs gnome-themes-standard

WebKit after all

Since we’re after a Web based Kiosk, let’s bring this lovely engine in!

# and also latest WebKit (it's really good!)
pacman -S --needed webkit2gtk gst-plugins-base gst-plugins-good

The plugins are related to extra libraries useful to show videos, render images, or play audio. There is a third option that brings in bad plugins too, which are those with non free licenses and/or unknown binary blobs.

If that’s your cup of tea:

pacman -S --needed gst-libav

How to launch WebKit2GTK

To start with, it’s time to move into the user folder.

cd /home/alarm

Now, all you need is to learn a bit of GJS, or simply use a basic script I’ve written long time ago.

# download a minimalistic full screen browser
curl -L archibold.io/test/gjs/browser -o .browse
chmod a+x .browse
chown alarm:alarm .browse

The chmod a+x operation ensure the file is executable, while the chown one ensure the alarm user can access and use it, or even change it, as it needs.

Which site to visit ?

We could decide to use a remote URL for our Kiosk, why not, or we can simply use a file with some useful information.

# create www/index.html
mkdir -p www
echo '<!doctype html><h1>RPi3 Web Kiosk</h1><pre>'>www/index.html
ip addr>>www/index.html
echo '</pre>'>>www/index.html
chown -R alarm:alarm www

The ip addr command, something you can try even now right away, shows some network information so let’s put those into an index.html page.

Launch the browser

We delegate this task to the .xinitrc file, which is automatically executed as soon as startx command is run.

# setup the xinitrc
echo '# avoid sleep
xset s off -dpms
# browse a generic page
./.browse --fullscreen file:///home/alarm/www/index.html'>.xinitrc
chown alarm:alarm .xinitrc

Remember, you could use any other fully qualified URL to start.

Launch the Kiosk

That’s it, once we login automatically, we want our system to run startx:

# bootstrap xorg from .bashrc
echo '
# startx on login
[[ -z $DISPLAY && $XDG_VTNR -eq 1 ]] && exec startx > /dev/null 2>&1'>>.bashrc
chown alarm:alarm .bashrc

… but silence please …

# avoid initial message
touch .hushlogin
chown alarm:alarm .hushlogin

You can reboot now writing: reboot 🎉

If everything went OK you’ll see the index page with your network info.

Step #5: OK, I see the page, what’s next ?!

It depends what you need but in general this is what you could do.

Connect to the RPi via ssh

That ip addr was not suggested by accident, if you read a number such 192.168.1.5 or similar IPv4 you can connect through that address to your Pi:

ssh alarm@192.168.1.5

It will ask the first time if you are OK with connecting to that host, and the password to enter will be the same you have chosen for the alarm user.

Perform operations as root

Once you are connected via SSH you can type su, write down the password you previously set for the root user, and that’s it. You can now install, mess up, destroy your own system as you please. Type exit to get out.

… but what about sudo ?

You can install sudo manually, or you can let my scripts do that for you.

As alarm user, once logged in, type the following:

bash <(curl -s https://archibold.io/install/sudo)

That’s it, you can try sudo ls after it’s installed and the very first time only you’ll have to understand sudo powers and agree on using it.

Install NodeJS and npm

These two packages are separately available via pacman and regular repositories, but you could also let my script better configure npm for you, without ever needing sudo powers to install stuff globally, as example.

bash <(curl -s https://archibold.io/install/npm)

NodeJS will be installed too, which is why you have to wait a little bit.

Can I avoid port 8080 or similar?

You can forward there everything that passes through port 80, if you like.

# configure 8080 to 80 redirect
echo '[Unit]
Description=port 80 to 8080 service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
ExecStart=/usr/bin/iptables -t nat -I OUTPUT -p tcp -o lo --dport 80 -j REDIRECT --to-port 8080
[Install]
WantedBy=multi-user.target
'>port80to8080.service
sudo mv port80to8080.service /etc/systemd/system/
sudo systemctl enable port80to8080.service

OK but how do I start NodeJS ?

You can go in the ~/www folder, a shortcut for /home/alarm/www, and put a package.json file with a start script. Your node script will need to use child_process or something else to launch the /home/alarm/.browse script and then you can edit .xinitrc removing or commenting via # the line that launches the browser and put cd www && npm start there instead.

All good, but fonts are horrible!

You can install numerous fonts in ArchLinux and these are just few suggestions:

  • ttf-dejavu and ttf-symbola to cover most common fonts and emoji cases, in blak and white though
  • ttf-liberation and ttf-freefont to have more free choices
  • ttf-droid if you like it, or the most recent noto-fonts, together with the noto-fonts-emoji to have an even better emoji support.

Step #6: Enjoy 🍻

If you have questions, suggestions, or you actually know how to start Weston as full screen Kiosk GJS app, please don’t hesitate to write me here or in twitter where my DMs are open.

I hope you’ll create something amazing with Web technologies and JS!

Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.