Build a Raspberry Pi Kiosk
Boot a Raspberry Pi straight into full-screen Chromium with no desktop, no cursor, and no screen blanking using labwc, systemd autologin, and Wayland.
Before you start
- ▸Raspberry Pi 4 or 5 with a microSD card (16 GB minimum) and HDMI display
- ▸Raspberry Pi OS Lite (64-bit, Bookworm) flashed and booted with SSH enabled
- ▸Admin user account with sudo access on the Pi
- ▸Network connectivity on the Pi for package installation
A Raspberry Pi kiosk turns a $35 board into a locked-down display that boots straight into a full-screen browser — no taskbar, no cursor, no escape. This guide covers the complete stack: a lightweight Wayland compositor, autologin via systemd, Chromium in kiosk mode, and disabling screen blanking so the display never goes dark. Steps are written for Raspberry Pi OS (Bookworm, 64-bit), which is Debian-based, but the same logic applies to Ubuntu Server for Pi with minor package name changes.
1. Start With a Lean Base
Flash Raspberry Pi OS Lite (64-bit) using Raspberry Pi Imager. Lite has no desktop environment installed, which gives you a clean slate. Enable SSH and set your hostname in the imager before writing the card.
After first boot, update the system:
sudo apt update && sudo apt full-upgrade -y
Install the packages you need. labwc is a lightweight, wlroots-based Wayland compositor well-suited for kiosk use. cage is an even simpler single-app Wayland compositor — either works, but labwc gives you more flexibility if you ever want a second app.
sudo apt install --no-install-recommends \
labwc \
chromium-browser \
xwayland \
fonts-liberation \
unclutter-xfixes
If you prefer the absolute minimum, replace labwc with cage and skip the labwc config below — cage takes a single command as its argument and runs nothing else.
2. Create a Dedicated Kiosk User
Running the kiosk as a restricted user reduces the blast radius if the browser is exploited.
sudo useradd -m -G video,input,render kiosk
sudo passwd -l kiosk
passwd -l locks password login. The account can still be used by systemd for autologin. Add it to the seat group if seatd is managing device access:
sudo usermod -aG seat kiosk
3. Configure labwc for Kiosk Mode
Create the labwc config directory for the kiosk user and write a minimal config that hides all decorations and disables the compositor's built-in screen-saver.
sudo -u kiosk mkdir -p /home/kiosk/.config/labwc
sudo -u kiosk tee /home/kiosk/.config/labwc/rc.xml <<'EOF'
<?xml version="1.0"?>
<labwc_config>
<core>
<decoration>server</decoration>
</core>
<screen>
<screensaver enabled="false" />
</screen>
</labwc_config>
EOF
Write the autostart file that labwc executes on startup. This launches Chromium and hides the cursor with unclutter:
sudo -u kiosk tee /home/kiosk/.config/labwc/autostart <<'EOF'
chromium-browser \
--kiosk \
--noerrdialogs \
--disable-infobars \
--no-first-run \
--disable-translate \
--disable-features=TranslateUI \
--disable-session-crashed-bubble \
--check-for-update-interval=31536000 \
--app=https://your-kiosk-url.example.com &
unclutter --hide-on-touch --start-hidden &
EOF
Replace https://your-kiosk-url.example.com with your actual URL. The --app flag strips the browser chrome (address bar, tab strip) automatically — use it instead of passing the URL as a bare argument.
4. Autologin and Autostart via systemd
Override the getty service for TTY1 to autologin as the kiosk user:
sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/autologin.conf <<'EOF'
[Service]
ExecStart=
ExecStart=-/sbin/agetty --autologin kiosk --noclear %I $TERM
EOF
Now configure the kiosk user's shell profile to launch labwc automatically on TTY1. We do this in .bash_profile so it only fires on a real login shell, not on every bash invocation:
sudo -u kiosk tee /home/kiosk/.bash_profile <<'EOF'
# Only start compositor on TTY1
if [ "$(tty)" = "/dev/tty1" ]; then
exec labwc
fi
EOF
If you chose cage instead of labwc, replace exec labwc with:
exec cage -- chromium-browser --kiosk --noerrdialogs --app=https://your-kiosk-url.example.com
Reload systemd and enable the override:
sudo systemctl daemon-reload
sudo systemctl enable getty@tty1
5. Disable Screen Blanking and DPMS
Three separate layers can blank your display: the kernel console, the Wayland compositor, and the monitor's DPMS. Silence all three.
Kernel Console Blanking
Edit /boot/firmware/cmdline.txt (Raspberry Pi OS Bookworm path — older releases use /boot/cmdline.txt). Add the following to the end of the existing single line:
sudo sed -i 's/$/ consoleblank=0 logo.nologo=1/' /boot/firmware/cmdline.txt
DPMS via wlr-randr or Chromium Flag
labwc respects the WAYLAND_DISPLAY variable. You can disable DPMS by adding a wlr-randr call to the autostart file, or by passing Chromium's flag. Install the tool first:
sudo apt install wlr-randr
Then append to the labwc autostart file:
sudo -u kiosk tee -a /home/kiosk/.config/labwc/autostart <<'EOF'
wlr-randr --output HDMI-A-1 --on &
xset -dpms s off s noblank && xset s 0 0 &
EOF
The xset call handles any XWayland-inherited DPMS settings. If your HDMI output name differs, check it later with wlr-randr (no arguments) once the compositor is running.
Raspberry Pi-Specific Blanking (vc4 driver)
Add these lines to /boot/firmware/config.txt under the [all] section:
sudo tee -a /boot/firmware/config.txt <<'EOF'
# Kiosk: prevent blanking
[all]
hdmi_blanking=1
EOF
hdmi_blanking=1 allows software to control HDMI power (the default, 0, can override and blank regardless).
6. Harden and Lock Down the Kiosk
Prevent users from reaching a shell or changing configuration:
- Set
kiosk's shell to/usr/sbin/nologinas an extra measure:sudo chsh -s /usr/sbin/nologin kiosk— but note this conflicts with.bash_profileif you use agetty. Keep bash as the shell; the lock is the locked password. - Disable SSH password auth in
/etc/ssh/sshd_config(PasswordAuthentication no) and manage the Pi over key-based SSH from your workstation. - Mount
/home/kioskread-only with a tmpfs overlay if you want to prevent any local writes — though Chromium needs a writable cache, so point--user-data-dirat a tmpfs instead: add--user-data-dir=/tmp/chromium-kioskto the Chromium flags.
7. Verify
Reboot and confirm the kiosk comes up cleanly:
sudo reboot
After the Pi restarts, the display should show your URL in full-screen Chromium with no cursor within about 15–20 seconds. SSH in from another machine and check:
# Confirm labwc is running as kiosk
ps aux | grep labwc
# Confirm Chromium is running
ps aux | grep chromium
Output will vary but you should see both processes owned by the kiosk user.
Troubleshooting
Blank screen after boot
SSH in and check the kiosk user's journal: sudo journalctl --user -b -u labwc. Usually the cause is a missing group (video, render, or seat) or a typo in the autostart path.
Chromium shows "crashed" dialog on next boot
Add --disable-session-crashed-bubble and --restore-last-session flags, or point --user-data-dir at /tmp so the profile resets on every boot.
Screen still blanks after 10 minutes
Run wlr-randr with no arguments inside a compositor session to confirm your output name, then add an explicit DPMS-off call. Also double-check cmdline.txt has consoleblank=0 on one unbroken line — a stray newline breaks the kernel parameter parsing.
Wrong resolution
Set hdmi_group and hdmi_mode in config.txt, or use wlr-randr --output HDMI-A-1 --mode 1920x1080@60 in the autostart file.
Frequently asked questions
- Can I use X11 instead of Wayland on Raspberry Pi OS Bookworm?
- Yes — install openbox and xorg, use lightdm for autologin, and set DISPLAY in your autostart. However, Bookworm defaults to Wayland and the Chromium package is optimised for it; stick with Wayland unless you have a specific reason not to.
- How do I update the kiosk URL without rebuilding the SD card?
- SSH into the Pi as your admin user, edit /home/kiosk/.config/labwc/autostart with the new URL, then run sudo systemctl restart getty@tty1 to restart the session.
- Will the kiosk recover automatically after a network outage?
- Chromium will show its offline page. Add a simple watchdog script using a systemd timer that checks connectivity and reloads Chromium if needed, or set --app to a local HTML fallback page that auto-refreshes when the network returns.
- How do I prevent Chromium from showing update or permission prompts?
- Use --no-first-run, --disable-infobars, and --check-for-update-interval=31536000 (one year). Also point --user-data-dir at /tmp/chromium-kiosk so the profile is wiped on each reboot, eliminating accumulated prompts.
- Does this work on a Pi Zero 2 W or only Pi 4/5?
- labwc and Chromium run on Pi Zero 2 W (which is 64-bit capable) but expect slower startup — around 45–60 seconds to first paint. Pi 4 or 5 with 2 GB+ RAM is strongly recommended for smooth kiosk operation.
Related guides
Linux Clipboards Explained (+ Clipboard Managers)
Learn the difference between Linux's PRIMARY and CLIPBOARD selections, use xclip, xsel, and wl-clipboard from the terminal, and manage history with GPaste or Klipper.
Configure LibreOffice for Daily Use
Configure LibreOffice for daily use: set default save formats for MS Office interop, tune autosave, install fonts, and add productivity extensions.
Configure the Touchpad and Multitouch Gestures
Configure Linux touchpad behavior and multitouch gestures using libinput, libinput-gestures, and native GNOME and KDE Plasma settings on both Wayland and X11.
Wayland vs X11: How to Choose and Configure Each
Know when to run Wayland or X11, how to check your current session, switch at login with GDM/SDDM/LightDM, and handle NVIDIA and XWayland edge cases.