Raspberry Pi Kiosk HOW-TO


Tested with Raspberry Pi 3 and 4, but should work on some older models too.

For Ethernet connected kiosk machines.

Download and install Raspberry Pi OS

Download img file and image to micro SD card.

  • Raspberry Pi OS (32-bit) with desktop, Image with desktop based on Debian Buster. Warning: This is not the distribution with "recommended software".

All the following, unless otherwise indicated should run in a root shell. Use sudo -i after initial login as user pi.

The default user:pass for Raspbian is pi:raspberry

Initial update and clean up

apt -y update
apt -y dist-upgrade
apt -y install unclutter vim ntpdate at-spi2-core libnotify-bin \
    mate-notification-daemon mate-notification-daemon-common
apt -y remove vlc geany thonny qpdfview xarchiver gpicview galculator mousepad
apt -y autoremove

raspi-config and general config

Things to do:

  • 1. Change User Password
  • 3-B1-B4. Desktop autologin as pi
  • 4-I2 Localisation, change timezone
  • 4-I3 Localisation, change keyboard layout to us
  • 4-I4 Localisation, change wi-fi country to Australia
  • 5-P2 Interfacing Options, enable SSH server

Configure default editor to vim

sudo update-alternatives --config editor

By default, the user pi is part of the sudoers group and requires no password. We want to change this to prompt a user for a password when performing sudo operations for the first time in a session.

Edit /etc/sudoers.d/010_pi-nopasswd and change:




Optional: Enable root account

Set password for root user as well, this will enable the root user.

sudo passwd root

Disable wireless and Bluetooth

Disable bluetooth and wireless via GUI in the system tray. The systme should persist this change after reboots. This can also be done via the command line using rfkill.

Enable GPIO shutdown

Allow shutdown via GPIO. Add to /boot/config.txt, at the of the [all] section.


This will give a physical shutdown button on pin GPIO 26. Shorting GPIO 26 to GND will invoke a shutdown.

   3V3  (1) (2)  5V
 GPIO2  (3) (4)  5V
 GPIO3  (5) (6)  GND
 GPIO4  (7) (8)  GPIO14
   GND  (9) (10) GPIO15
GPIO17 (11) (12) GPIO18
GPIO27 (13) (14) GND
GPIO22 (15) (16) GPIO23
   3V3 (17) (18) GPIO24
GPIO10 (19) (20) GND
 GPIO9 (21) (22) GPIO25
GPIO11 (23) (24) GPIO8
   GND (25) (26) GPIO7
 GPIO0 (27) (28) GPIO1
 GPIO5 (29) (30) GND
 GPIO6 (31) (32) GPIO12
GPIO13 (33) (34) GND
GPIO19 (35) (36) GPIO16
GPIO26 (37) (38) GPIO20
   GND (39) (40) GPIO21

Fix mouse lag

Add to end of kernel command line file /boot/cmdline.txt to fix laggy mouse behaviour.


Optional: Configure SSH

Prepare authorized_keys file in ~/.ssh/authorized_keys for both users root and pi. Use your own favourite technique for doing this.

Set permissions for the file

sudo chmod 0600 /home/pi/.ssh/authorized_keys
sudo chmod 0600 /root/.ssh/authorized_keys

Allow only public key authentication, edit /etc/sshd/sshd_config

PermitRootLogin prohibit-password
PasswordAuthentication no

Restart sshd

service sshd restart

Check and confirm you can remotely SSH to the device as both root and pi.

Configure ntpdate

Automatic time sync should already be enabled, however sometimes it is not and I'm not sure why. Enable it with

timedatectl set-ntp True

Disable screensaver and blanking

Disable console screen blanking. This doesn't affect a GUI based kiosk machine but we'll do it anyway for completeness.

Add to /boot/cmdline.txt


Disable UI screen blanking by creating ~/.config/lxsession/LXDE-pi/autostart. Note the first 3 lines is from the global /etc/xdg/lxsession/LXDE-pi/autostart. If a local file in ~/.config is found, the global file is ignored. This is why we need to copy the lines from the global file to the local user file.

Run all this as user pi. Create ~/.config/lxsession/LXDE-pi/autostart

mkdir -p ~/.config/lxsession/LXDE-pi && touch ~/.config/lxsession/LXDE-pi/autostart

Make a symbolic link so it's easier to find and edit later on.

ln -s .config/lxsession/LXDE-pi/autostart ~/autostart

Edit autostart and add:

@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@xset s off
@xset dpms 0 0 0

Configure autostart script

Create a file ~/autostart.sh and make it executable

chmod +x ~/autostart.sh

# URL to open automatically

while ! ip route | grep -q -e "eth0" -e "wlan0"; do
    notify-send -t 900 "Waiting for network connection..." &> /dev/null
    sleep 1

notify-send -t 500 "Connected." &> /dev/null
notify-send -t 3000 "Starting browser..." &> /dev/null
chromium-browser --incognito --app=$URL \
    --start-fullscreen \
    --check-for-update-interval=31536000 \
    --overscroll-history-navigation=0 \

Some command line switches customises the Chromium instance:

  • --overscroll-history-navigation=0 disables behaviour where left and right swiping would trigger the browser's history back and forward behavivour.
  • --disable-pinch disables pinch to zoom.
  • --check-for-update-interval=31536000 disables automatic checks for updates, otherwise would cause "could not be updated" error.

Restarting the unit with sudo reboot and Chromium should automatically start once the network connection is up.

Note this does not automatically refresh the web page at regular intervals, the target web site itself should perform the refreshing.

Overlay FS

It's recommended to use the Overlay FS. After the set up is completed and tested to be working correctly, in raspi-config, enable the Overlay FS with a writable /boot directory.

You will want to clear ~/.config/chromium prior to enabling the overlay. Or alternatively, you can add rm -rf /home/pi/.config/chromium to /boot/start.sh after enabling the Overlay FS.

Prior to enabling OverlayFS

pkill chromium-browser; rm -rf /home/pi/.config/chromium

Using a Overlay FS means it is more resilient to power outages by making the root file system read only. Changes to the filesystem are written to a in memory tmpfs filesystem.

raspi-config implements the scripts based on this article by Mattias Wikstrom.

Update workflow with OverlayFS

To update packages and other files on the flash card (except /boot), you'll need to disable OverlayFS.

  • Disable overlay with raspi-config and reboot
  • Make the changes
  • Clear chromium profile with pkill chromium-browse; rm -rf /home/pi/.config/chromium
  • Enable overlay with raspi-config and reboot