Published
July 26, 2024

Kiosk mode for edge computing with Kairos and Kubernetes

Dimitris Karakasilis
Dimitris Karakasilis
Open Source Principal Software Engineer

There’s a whole world of edge kiosks out there

When we think about edge computing use cases, we often think of unattended or headless boxes that real people — real users — don't interact with directly or knowingly. Think IoT devices, industrial equipment, network base stations, smart building controllers, and so on.

But there's a whole other class of edge computing devices that are deployed at scale, distributed across locations, but that users interact with directly through a graphical user interface.

We can call this class of devices edge computing ‘kiosks’, but it encompasses everything from ticket machines, vending machines and parking meters to ATMs, point of sale (POS), and interactive digital signage.

graphical user interface

Managing kiosks is just as challenging as other edge devices

Traditionally single-app kiosks — such as the ATM above — have evolved from a PC operating model. We’re sure you’ve been in a museum and found that the information screen is just a full-screen browser on a Windows machine.

But kiosks present many of the same challenges and requirements around manageability, security and reliability as any other edge computing host. They:

  • Are at risk of tampering, so we need an ability to secure and verify the boot and make the software stack immutable
  • Are deployed out in the field for years, needing new feature upgrades and patches, without risk of bricking the device and requiring a field engineering visit, so we need A/B upgrades.
  • May be deployed in large distributed fleets in locations lacking technical staff, whether it's a museum or a parking garage, therefore we need automated installation and remote/centralized operations
  • May run software with different lifecycles than the OS itself and are in need of the flexibility to update parts of the system outside the main OS lifecycle

What are your options?

Aside from good ol’ Windows XP or OS/2 Warp, there are a number of different software options out there that you can use to build locked-down kiosks for untrusted users. 

For example, Windows has a kiosk mode, and so does Android. Kiosks can also be created with Ubuntu or specialized software like OpenKiosk. PC-like devices can potentially be managed with mobile device management (MDM) solutions.

And although some of these solutions do better than others at solving the security and operational challenges of running kiosks, we’ve seen a lot of interest from users in using the CNCF Sandbox Kairos project for their kiosk use cases.

At first glance, this may seem odd: our Kairos team did not set out to target kiosk use cases, and we have never pitched it that way when having conversations at conferences. To us, Kairos is a Linux meta-distribution designed to simplify the creation and management of edge Kubernetes clusters, for traditional edge computing use cases.

But the Kairos project is actually a great fit because it was built for managing edge nodes with tamper-resistent security, resilience and automation — all things that kiosks require, just like other edge devices. So let’s take this opportunity to bring some cloud native innovation to a whole new industry!

What does Kairos offer?

Let’s not get hung up on the term ‘Kubernetes’. Kairos uses Kubernetes to perform management tasks, such as node upgrades, at scale. Kubernetes is not the final deliverable, it’s merely a technical detail, enabling some of Kairos’s features.

For example, Kairos supports:

It’s also lightweight, meaning it can run on limited edge hardware, and supports a wide range of hardware and customizable OS components.

Kairos in action: deploying a GUI application to a kiosk

For the purpose of this post, we will use the example of a single-app kiosk. We will show how Kairos can be used to run a single GUI application in “kiosk mode” (using cage), meaning that the users aren’t able to run anything else on the machine. 

Our example application will be just a browser serving the “kairos.io” website. Replacing that with the application of your choice should be trivial.

Here is the software stack of this example:

software stack kairos

1. Create a custom Kairos image

The standard Kairos images don’t include the necessary packages, like the Chromium browser, to run GUI applications. 

We’ll create a derivative image adding those packages by creating a Dockerfile that starts from a released image. Check our docs here to learn more. 

 
 FROM busybox AS downloader
‍
RUN wget https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/1319705/chrome-linux.zip
RUN unzip chrome-linux.zip
RUN mv chrome-linux /
‍
FROM quay.io/kairos/ubuntu:24.04-standard-amd64-generic-v3.1.0-rc1-k3sv1.29.4-k3s1
‍
RUN apt update && apt install -y cage libnss3 libasound2t64
‍
COPY --from=downloader /chrome-linux /etc/chrome-linux
RUN ln -s /etc/chrome-linux/chrome /usr/bin/chrome

This dockerfile uses an Ubuntu “standard” Kairos image (with K3s), installs a couple of additional packages for `cage` to work, and installs a build of the Chromium browser. Chromium will be used as the kiosk application, serving a single web page.

2. Create a Kairos config

The following Kairos config file will make sure Kairos installs automatically and start a systemd service to load the kiosk application automatically upon boot. 

Most of the config is implementing the `cage` docs.

Sidenote: Although we mentioned trusted boot earlier in this document, for sake of brevity, here we’ll describe the simpler installation of Kairos without trusted boot. If you are planning to implement this in production, make sure you go through the trusted boot docs!

 Save the following file as `config.yaml`:

 
 ```yaml
#cloud-config
‍
users:
  - name: kairos
passwd: kairos
‍
debug: true
‍
install:
  auto: true
  device: "auto"
  reboot: true
  grub_options:
extra_cmdline: "rd.immucore.debug rd.debug"
‍
k3s:
  enabled: true
‍
stages:
  boot:
- name: "Default systemd config"
  if: '[ -e "/sbin/systemctl" ] || [ -e "/usr/bin/systemctl" ] || [ -e "/usr/sbin/systemctl" ] || [ -e "/usr/bin/systemctl" ]'
  commands:
    - systemctl start cage@tty1.service
‍
# Mostly a copy of:
# https://github.com/cage-kiosk/cage/wiki/Starting-Cage-on-boot-with-systemd
write_files:
- path: /etc/pam.d/cage
  content: |
auth   required  pam_unix.so nullok
account  required  pam_unix.so
session  required  pam_unix.so
session  required  pam_systemd.so
‍
- path: /etc/systemd/system/cage@.service
  permissions: "0644"
  owner: "root"
  content: |
# This is a system unit for launching Cage with auto-login as the
# user configured here. For this to work, wlroots must be built
# with systemd logind support.
‍
[Unit]
Description=Cage Wayland compositor on %I
# Make sure we are started after logins are permitted. If Plymouth is
# used, we want to start when it is on its way out.
After=systemd-user-sessions.service plymouth-quit-wait.service
# Since we are part of the graphical session, make sure we are started
# before it is complete.
Before=graphical.target
# On systems without virtual consoles, do not start.
ConditionPathExists=/dev/tty0
# D-Bus is necessary for contacting logind, which is required.
Wants=dbus.socket systemd-logind.service
After=dbus.socket systemd-logind.service
# Replace any (a)getty that may have spawned, since we log in
# automatically.
Conflicts=getty@%i.service
After=getty@%i.service
‍
[Service]
Type=simple
ExecStart=/usr/bin/cage chrome https://kairos.io -- --kiosk --enable-features=UseOzonePlatform --ozone-platform=wayland
Restart=always
User=kairos
# Log this user with utmp, letting it show up with commands 'w' and
# 'who'. This is needed since we replace (a)getty.
UtmpIdentifier=%I
UtmpMode=user
# A virtual terminal is needed.
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
# Fail to start if not controlling the virtual terminal.
StandardInput=tty-fail
‍
StandardOutput=file:/home/kairos/cage.log
StandardError=file:/home/kairos/cage.err.log
‍
# Set up a full (custom) user session for the user, required by Cage.
PAMName=kairos
‍
[Install]
WantedBy=graphical.target
#Alias=display-manager.service
DefaultInstance=tty7

If for some reason the kiosk application does not start, check the two output files for errors:

 
StandardOutput=file:/home/kairos/cage.log
StandardError=file:/home/kairos/cage.err.log

3. Build the container image:

Now that we have a dockerfile, it’s time to build the container image with it:

 
 docker build -t kairos-kiosk -f ./Dockerfile .

4. Build an ISO

We will use Auroraboot to convert the image we built in the step above into a bootable ISO.

 
 docker run -v “$PWD/config.yaml”:/config.yaml \
         -v "$PWD/build”:/tmp/auroraboot \
         -v /var/run/docker.sock:/var/run/docker.sock \
         --rm -ti quay.io/kairos/auroraboot \
         --set container_image="docker://kairos-kiosk" \
         --set "disable_http_server=true" \
         --set "disable_netboot=true" \
         --cloud-config /config.yaml \
         --set "state_dir=/tmp/auroraboot"
# Fixing the build dir permissions
docker run -v "$PWD/build”:/tmp/build kairos-kiosk chown -R 1000:1001 /tmp/build

5. Boot the ISO

The generated ISO has the Kairos config embedded in it, which means we simply have to boot the ISO and let it complete the installation. 

Use the hypervisor of your choice or boot a real device with the ISO and wait until the installation completes, rebooting automatically into the installed system.

If you are on Linux with qemu installed, here are some commands that should work for you:


qemu-img create -f qcow2 "$PWD/disk.img" 60g
export CDROM="${1:-build/build/kairos.iso}"
qemu-system-x86_64 \
-enable-kvm \
-cpu "${CPU:=host}" \
-serial mon:stdio \
-m ${MEMORY:=10096} \
-smp ${CORES:=5} \
-rtc base=utc,clock=rt \
-chardev socket,path=qga.sock,server=on,wait=off,id=qga0 \
-device virtio-serial \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 \
-drive id=disk1,if=none,media=disk,file="$PWD/disk.img" \
-device virtio-blk-pci,drive=disk1,bootindex=0 \
-netdev user,id=net0,hostfwd=tcp::2224-:22 \
-device e1000,netdev=net0 \
-drive id=cdrom1,if=none,media=cdrom,file="${CDROM}" \
-device ide-cd,drive=cdrom1,bootindex=1 \
-boot menu=on

You should eventually see qemu running chromium in kiosk mode, serving the kairos.io web page:

You’ll notice that there is no way for the user to open any other application. Even if the application crashes or exits, it will be restarted.

Note: In a production deployment, the Kairos config would need to change in order to:

  • Not have a default user (or any login capabilities at all)
  • Become a multi node cluster (e.g. as per the docs)

…and others. Please refer to the Kairos documentation for recommendations and available configuration options.

Ideas and final thoughts

In the example above, we just served a publicly available web page. But Kubernetes is also running in the background. Although it can be used to upgrade Kairos, Kubernetes can also be used to host the actual kiosk application. 

Such an application would even be able to access specialized hardware attached to the Kairos node. 

For example, consider an application that allows a doctor to analyze a patient’s CT scan using AI. Capturing the CT scan might require the node to communicate with the CT scanner and AI processing might require access to the GPU. All these can be packaged nicely and run on the node’s Kubernetes.

The example above simply demonstrates that running GUI applications with Kairos is possible and easy. Starting a full desktop environment is also possible. We actually started playing with the idea by running XFCE: it’s just a matter of installing the needed packages and enabling the relevant systemd services. This scenario might be suitable for school laboratories and cases when more than one application should be offered to the user.

If you liked this use of Kairos or if you have ideas on how this could be extended further, we’d love to hear from you! Head to the Kairos site and start building your own kiosk solution. Or, if you’d rather get enterprise level support and guidance, check out Spectro Cloud’s Palette Edge, which builds on top of Kairos.

Tags:
Edge Computing
How to
Security
Subscribe to our newsletter
By signing up, you agree with our Terms of Service and our Privacy Policy