Setting up a Chromium kiosk on a Raspberry Pi
Setting up a proper kiosk mode with Chromium on a Pi can prove quite tricky. Here's how you do it!
In my home and at work there are a few different displays which we use for different things: displaying a dashboard with metrics, showing a Home Assistant dashboard with buttons, etc. Some fairly different use cases, but all of them have one thing in common: it’s a Raspberry Pi with a display, sometimes with touch.
I went through various iterations of setting this up, with LXDE autostart scripts, systemd services, but I also ran into issues with a lot of these approaches. My last setups have been more successful though, and have - so far - been working perfectly. The secret: a systemd user service, and a simple script.
In this post I am going to walk through how to set this all up, so hopefully other people can also reap the fruits of my troubles.
Getting Started
Before we get started, I am going to assume you have a working Raspberry Pi with an attached display. You will also need to be able to access it (obviously), either via SSH or with an attached keyboard and mouse.
Before we create any files, you are going to need a couple of tools:
chromium-browser
(or any other browser of your choice)unclutter
xscreensaver
(optional)
All of these can be installed using apt
.
Step 1: The Kiosk Script
I generally like to create a kiosk.sh
script in the home directory.
That way it’s easy to find and edit, should you ever need to change it.
The full script looks something like this:
#!/usr/bin/env bash
# Disable xset blanking, let xscreensaver handle that.
xset s noblank
xset s off
# Start xscreensaver.
xscreensaver &
# Hide the mouse cursor.
unclutter -idle 1 -root &
# Let Chromium think it always exited cleanly.
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' '~/.config/chromium/Default/Preferences'
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' '~/.config/chromium/Default/Preferences'
# Start Chromium.
chromium-browser --kiosk --noerrdialogs --disable-infobars 'http://192.168.0.11:8123' &
~/kiosk.sh
Let’s go through it bit by bit, to explain what it all does.
Preventing or Adjusting Screen Blanking
Depending on your installation, the X server will blank the screen after a set amount of time.
To prevent that, we can run these two xset
commands:
xset s noblank
xset s off
If you completely want to prevent the screen from going blank, that’s all you need here.
However, depending on your use case, you might actually want the screen to go blank after some time.
For that, it is preferable to use xscreensaver
.
The main advantage of this over the default X screen blanking is that it will ignore the first tap on a touchscreen after blanking,
whereas X by default will actually register that tap, causing you to tap on an unknown area of the screen.
To run it, you simply call:
xscreensaver &
Note the ampersand (&
) at the end, which forks the process and continues the script.
Depending on your preferences, you will need to configure xscreensaver
.
This is done via the ~/.xscreensaver
file.
When setting this up, you can run xscreensaver-demo
to generate this file with a bunch of defaults, after which you can easily edit it.
More information on this configuration file can be found on: https://www.jwz.org/xscreensaver/man1.html (ctrl+f is your friend here).
Uncluttering the Display
Next we want to hide the mouse cursor.
This can be done with unclutter
:
unclutter -idle 1 -root &
The -idle 1
flag tells it to hide the mouse cursor after 1 second of inactivity.
The -root
flag tells it to also hide the cursor if it is on the root background (i.e. the desktop).
Again, note the ampersand at the end, because we need to run this as a forked process and continue with the script.
Tricking Chromium
If you use Chromium (or a similar browser), you are probably familiar with this popup:
This popup also displays in kiosk mode, and will inevitably ruin your kiosk setup if you don’t prevent it. Luckily, with just two simple commands you can trick Chromium into thinking it always shut down correctly:
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' '~/.config/chromium/Default/Preferences'
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' '~/.config/chromium/Default/Preferences'
This replaces values like "exited_cleanly":false
and "exit_type":"Crashed"
in your Chromium preferences,
which is where it stores information about the last time(s) you exited the browser.
If it finds evidence of a crash (or unclean exit) in that file, it will show you the “restore pages” popup.
Note that the path '~/.config/chromium/Default/Preferences'
will be different if you use another browser.
Opening the Browser
Finally, it is time to actually start Chromium:
chromium-browser --kiosk --noerrdialogs --disable-infobars 'https://example.com' &
Don’t forget to replace 'https://example.com'
with the actual page you want to open.
The most important flag here is --kiosk
, which will start the browser in kiosk mode (i.e. fullscreen with no way of exiting it).
Alternatively, if you do want to be able to exit fullscreen mode, you can use --start-fullscreen
.
The --noerrdialogs
and --disable-infobars
flags are there to prevent any unwanted info bars, error dialogs, etc.
For a large (although likely not quite complete) list of possible flags, see: https://peter.sh/experiments/chromium-command-line-switches.
Step 2: The Kiosk Service
Next we can create our service file.
This should be located in ~/.config/systemd/user
.
The filename can be whatever you want, but should end with .service
.
[Unit]
Description=Chromium kiosk
PartOf=graphical-session.target
[Service]
ExecStart=/home/pi/kiosk.sh
Restart=on-abort
Type=forking
[Install]
WantedBy=xsession.target
~/.config/systemd/user/kiosk.service
The most important thing here is the ExecStart
value, which should point to the script we created in step 1.
We want this service to run as soon as we have a graphical session,
however (for reasons I don’t fully understand) we can’t make it WantedBy=graphical-session.target
.
Instead, we make it WantedBy=xsession.target
and create our own xsession.target
, which will run as soon as the X session starts.
Step 3: Hooking Into the X Session
Like mentioned above, we need a way to hook into the X session startup, which is done using these two files:
[Unit]
Description=Xsession running
BindsTo=graphical-session.target
~/.config/systemd/user/xsession.target
systemctl --user import-environment PATH DBUS_SESSION_BUS_ADDRESS
systemctl --no-block --user start xsession.target
~/.xsessionrc
I won’t go into too much detail here, but simply creating these exact files should be all you need! If you want a bit more info, you can check the StackExchange posts linked in the sources below.
Step 4: Enabling Everything!
Now it’s time to start the service, and see if it all works!
You do this using systemctl
with the --user
flag (and without superuser permissions or sudo
).
systemctl --user enable kiosk
systemctl --user start kiosk
Here you need to replace kiosk
with whatever you called your .service
file in step 2.
Note that you can omit the extension from the name.
You should see Chromium starting, and displaying your page! That’s all you need to do, so now whenever you boot up your Raspberry Pi, the Chromium kiosk should start with it.
Sources
This post would not have been possible (or a lot more work) without these two posts on StackExchange:
Massive thanks to those lovely people :)