Raspberry Pi (4) Kiosk / Wall Display / Dashboard

This post is about setting up a display with a Raspberry PI or similar computer using Linux, potentially raspbian / n00bs on an sd card and a screen. The Raspberry Pi 4 has some respectable specs is quiet, displays up to 4k and has Wi-Fi which makes it a pretty great dashboard display source.

When you create a dashboard, aim for something that can run as a website and that takes care of refreshing itself, otherwise you can also make whatever browser you choose take care of that.

No matter if you roll it yourself or use one of the numerous services like Google Analytics, Geckoboard, Dasheroo, Kibana or what ever you can come to think of, you’ll probably want a browser to display them.

If you’re still considering to get a Raspberry PI maybe get an on/off switch and a heat sink as well (US referral link), because they get a bit hot (80ยฐ) without cooling.

Configuring the Raspberry Pi for Automatic Login

Since you’re likely to disconnect and remove keyboard and mouse after this setup is done, we should make sure that our Raspberry Pi can login automatically.

Open a terminal and run sudo raspi-config.

raspberry pi autologin config
Select Boot Options
raspberry pi autologin config
Desktop / CLI
raspberry pi autologin config
finally: B4: Desktop Autologin

Automatically Start Dashboard / Kiosk on Startup

When the power goes out or when something seems to have crashed, you’ll most likely want your display to go back to the state it was in before the outage, as soon as the power comes back up. Since the Raspberry Pi does not have a power switch, but just boots when you hook it up to a power source, you’ll need to create a systemd service, which is a simple file that specifies what kind of program you want to run on startup.

Let’s go ahead and create our systemd unit file at the right location:

sudo touch /etc/systemd/system/dashboard.service

and let’s enter the following content, via vim or other text editors:

sudo xdg-open /etc/systemd/system/dashboard.service
Description=Chromium Dashboard



These are the interesting parts:

  • Requires=graphical.target Don’t start before we have GUI support ready
  • Environment=DISPLAY=:0.0 use the specified screen
  • Type=simple to keep track of the script and its spawned pid

To enable the service use:

systemctl enable dashboard.service

Configure Raspberry Pi 4 Display Output

Per default your Raspberry Pi, like a regular computer, will put a screen to sleep if it does not detect mouse or keyboard input for a while. This is absolutely not what we want, so we’ll need to fix that. Also we’re going to use unclutter to hide the mouse cursor from the browser window.

We can do that with the following command:

unclutter -idle 0.5 -root &

You can set the output display by setting the DISPLAY environment variable with either specifying it before running a screen related command

export DISPLAY=:0.0

or by prepending it before running the command or script that will need access to it.

# don't "sleep" this display
DISPLAY=:0.0 xset s noblank

If you’re going to use SSH to set up your pi while it’s connected to only a screen, you’ll most likely need to set the screen ENV variable since your ssh session does not have one assigned by default.

Starting Chromium in Kiosk Mode

Now, I’d love to use Firefox for this, but unfortunately starting the browser in the fullscreen mode is not yet possible. Technically you could use [xdotool][xdotool] to achieve this, but that will introduce some timing and more complexity.

Chromium on the other hand comes with plenty of cool command line options that are very useful to us.

/usr/bin/chromium-browser --no-first-run --noerrdialogs --disable-infobars --kiosk &
  • --no-first-run skips first run checks (like default browser, etc)
  • --noerrdialogs shows no errors (you might want to exclude this while debugging)
  • --disable-infobars no crash warnings or “may we know your location”
  • --kiosk fullscreen mode

To make sure that we don’t have chromium complaining about unclean shutdowns because we typically just tear out the USB-C cable or crash, we’ll need to make it believe that everything went A-OK on the last shutdown when starting it after an incident:

sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' /home/pi/.config/chromium/Default/Preferences
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' /home/pi/.config/chromium/Default/Preferences

The full script can be found below and you should save it at /home/pi/dashbaord.sh

xset s noblank
xset s off
xset -dpms

unclutter -idle 0.5 -root &

sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' /home/pi/.config/chromium/Default/Preferences
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' /home/pi/.config/chromium/Default/Preferences

/usr/bin/chromium-browser --noerrdialogs --disable-infobars --kiosk https://www.raspberrypi.org &

Remember to make the file executable:

chmod +x /home/pi/dashboard.sh

Now you can try it out and run it:

cd /home/pi

Ideally, it should open the raspberry pi website, otherwise, see troubleshooting. If your test worked out, you can hit CTRL+C and start the service with:

systemctl start dashboard.service

Enabling SSH remote access to your Raspberry PI

To remotely update or reboot your little dashboard pi, you can use ssh after enabling the SSH server through raspi-conf. This way you don’t have to walk over to whatever physical location it’s at unless it crashes or overheats.

Even then you can probably just kill the power and wait for it to boot and show your dashboard / website and use SSH again instead of acessing it via its own peripheral hardware.

raspberry pi enable ssh server access
5: Interfacing Options
raspberry pi enable ssh server access
raspberry pi enable ssh server access
Finally: Enable SSH


Now you should have a super cool wall mounted, 55 inch wall display, displaying a website of your choice, that even in case of a power outage will power back up just fine.

If you run into any issues setting this up or operating this, please check the troubleshooting section below and reach out! Your comment or question is going to help others ๐Ÿ™‚

Finally for the full test: Pull the power and put it back in (or sudo reboot)!

Credits to the post of pimylifeup for the chromium / systemd help.


If you change the hostname of your raspberry after starting Chromium for the first time, it will throw an error like

Chromium profile already in use on another computer, do you want to Relaunch and unlock?

The easiest solution to this is to connect a keyboard and hit enter, that should fix it permanently.

Chromium crashes while trying to display a complex website

SSH into your raspberry pi and keep htop open. Keep an eye on the consumed memory and swap space right underneath. One of my PIs continued to crash and I increased the swap space to 2GB and the swap usage stabilised at 250MB, even though there was still empty RAM. Somebody familiar with Linux and memory management can probably tell you why, I can’t.

The most common error message is: Virtual memory exhausted: Cannot allocate memory.

If your Raspberry PI runs out of swap space you can increase it by editing /etc/dphys-swapfile, if you’re on the command line:

sudo nano /etc/dphys-swapfile
# or
sudo vi /etc/dphys-swapfile

and set CONF_SWAPSIZE to something more than 100 (default unit is MB). I set it to 2048 which turned out to be excessive. If you can get away with it, disable swapping, which I don’t think I should on the 1GB RAM PI.

Thank you for reading! If you have any comments, additions or questions, please leave them in the form below! You can also tweet them at me

If you want to read more like this, follow me on feedly or other rss readers

30 thoughts on “Raspberry Pi (4) Kiosk / Wall Display / Dashboard”

  1. Thanks for you great write up.
    I setup the system service which works great, it launch a browser on first screen (HDMI 1). But I also want to launch browser on second screen (HDMI 2), how do I do that?
    Can you give me some hints?

    Thanks a lot

    1. I would love some advice on this also with the idea of two hdmi outputs showing two different websites / dashboards.

        1. Hi,

          How can I set the file system to read only? I used such a system for several month and then the SD card gets some problems.

          Kind regards

          1. Good question, I burned through an SD card as well, I’m assuming it was the constant swapping

          2. The best thing to do is have an extra SD card on hand which is identical to the one in production. You can easily create a new one by taking an image of the one that works and applying that image to the spare. On another system run (assuming the sdcard is /dev/usb and make sure it’s not mounted): `dd if=/dev/usb of=/path/to/storage/image.img bs=2048 conv=noerror,sync`

          3. I determined that an ad card was t the best option as power cycles (frompower outages or just to reser) is damaging g ro sd cards. So went and set up an external HDD via USB- which handles file system recovery much better. A bit slower but solid reliability.

    2. add this to the chromium command: –window-position=1920,0

      so it looks like: /usr/bin/chromium-browser –no-first-run –noerrdialogs –disable-infobars –window-position=1920,0 –kiosk &

      1. I have added the line as you said but I only get the first chromium windows to open. Then when I close it the next window pop’s up, both appear on the correct screen. Do you have any tips?

        1. I think you are missing the first ‘&’ at the end of the command? Missing that would make the environment wait for the first command to end before the script calls the next one.

      2. I have added the line as you said but I only get the first chromium windows to open. How to make the second chromium also open?

  2. I like your post. I think it will be very helpful on my project.
    Couple of comments.
    I think you should move the SSH portion to the beginning where you show running raspi-config. It makes more sense to do them both at the same time.
    I found it a bit confusing as to which commands are to be inside of your dashboard.service file and which are run as CLI commands.
    I also think it would be helpful if you mentioned which OS release you are using here.
    I’m having trouble getting you dashboard.service to run.
    I get two consistent errors:
    Oct 17 09:16:29 raspdak systemd[1]: [/etc/systemd/system/dashboard.service:1] Assignment outside of section. Ignori
    Oct 17 09:16:29 raspdak systemd[1]: [/etc/systemd/system/dashboard.service:20] Missing ‘=’.
    When I check the status it reports the dashboard.service as dead.
    Any thoughts?
    I hope my comments will help with others with your blog.

  3. Hi, thanks for the tutorial!
    Is there a way for the user to go back to the default web page?
    Unfortunately, the web page that I need has a link to a more general one
    and there is no link to go back, so if a user follows that link then needs to reboot in order to go back to the original one… or not? Is there a way to reset/go back?

  4. You have a typo in

    “The full script can be found below and you should save it at /home/pi/dashbaord.sh”

    => should read “dasboard.sh” ๐Ÿ™‚

  5. I have the following error and the chrome is not starting

    I have the files exactly like in your post

    Jan 21 06:38:14 raspberrypi systemd[1]: Started Chromium Dashboard.
    Jan 21 06:38:14 raspberrypi dashbaord.sh[529]: Invalid MIT-MAGIC-COOKIE-1 keyxset: unable to open display “:0.0”
    Jan 21 06:38:14 raspberrypi dashbaord.sh[529]: Invalid MIT-MAGIC-COOKIE-1 keyxset: unable to open display “:0.0”
    Jan 21 06:38:14 raspberrypi dashbaord.sh[529]: Invalid MIT-MAGIC-COOKIE-1 keyxset: unable to open display “:0.0”
    Jan 21 06:38:14 raspberrypi dashbaord.sh[529]: Invalid MIT-MAGIC-COOKIE-1 keyunclutter: could not open display
    Jan 21 06:38:15 raspberrypi systemd[1]: dashboard.service: Succeeded.

  6. I’m not sure how this works, with the browser being started in background. I was in the same boot as Kevin, but removing the & keeps the service running, and eventually the web page displays. To get back to the desktop ssh to the device and stop the service with

    systemctl stop dashboard.service

    Perhaps I’m missing something, but I think script needs to keep running for the duration of the service. For example in the pimylifeup that you reference, there is an infinite while loop that keeps the script going (which is why the & needs to be in that script, otherwise the while loop would never be reached)

    Thanks for the post!

    1. Same here: removed the & at the end of the crowser call: Browser is starting

      With the &, the service seems to be complete instantly and no browser is being displayed:
      pi@HZKAW-PIS01:~ $ sudo systemctl status dashboard.service
      โ— dashboard.service – Chromium Dashboard
      Loaded: loaded (/lib/systemd/system/dashboard.service; enabled; vendor preset: enabled)
      Active: inactive (dead) since Thu 2020-10-22 17:35:51 CEST; 2s ago
      Process: 1019 ExecStart=/bin/bash /home/pi/Scripts/dashboard.sh (code=exited, status=0/SUCCESS)
      Main PID: 1019 (code=exited, status=0/SUCCESS)

      Okt 22 17:35:51 HZKAW-PIS01 systemd[1]: Started Chromium Dashboard.
      Okt 22 17:35:51 HZKAW-PIS01 systemd[1]: dashboard.service: Succeeded.

      Iยดve now readded the &, added the “switch betweet 2 tabs” part described at https://pimylifeup.com/raspberry-pi-kiosk/ and – since there is a “while true; do” loop, I no longer have a “dead” service but an active one:
      pi@HZKAW-PIS01:~ $ sudo systemctl status dashboard.service
      โ— dashboard.service – Chromium Dashboard
      Loaded: loaded (/lib/systemd/system/dashboard.service; enabled; vendor preset: enabled)
      Active: active (running) since Thu 2020-10-22 17:36:09 CEST; 3s ago
      Main PID: 1050 (bash)
      Tasks: 19 (limit: 3862)
      CGroup: /system.slice/dashboard.service
      โ”œโ”€1050 /bin/bash /home/pi/Scripts/dashboard.sh
      โ”œโ”€1057 unclutter -idle 0.5 -root
      โ”œโ”€1060 /usr/lib/chromium-browser/chromium-browser-v7 –disable-quic –enable-tcp-fast-open –ppapi-flash-p
      โ”œโ”€1081 /usr/lib/chromium-browser/chromium-browser-v7 –type=zygote –noerrdialogs –ppapi-flash-path=/usr/
      โ””โ”€1083 /usr/lib/chromium-browser/chromium-browser-v7 –type=zygote –noerrdialogs –ppapi-flash-path=/usr/

      Okt 22 17:36:09 HZKAW-PIS01 systemd[1]: Started Chromium Dashboard.
      Okt 22 17:36:09 HZKAW-PIS01 bash[1050]: –disable-quic –enable-tcp-fast-open –ppapi-flash-path=/usr/lib/chromium-b

  7. I have a number of kiosk installations around since I use Pi’s for all my home automation. I’d got up to 3 different ways of setting them up, none of which work with RaspiOS Buster (latest version) . This method actually works, so right now I’ve got a 3.5″ display on my desk that shows the plant troughs on my balcony and whether they need watering. Next up will be to replace my Domoticz kiosk with this one on a 7″ touch screen.

    I’m not sure about the full-fat version of Buster, but the standard installation (not the lite) needs Unclutter to be installed.

    I’d prefer to use Firefox as well, if only to get away from the ghastly “Update Chrome” messages that I keep getting. I did come across a method of using Firefox as a kiosk but wasn’t able to get it to work in the previous methods I had for kiosks. Perhaps it will work here.

    This is definitely the fastest way I’ve come across to set up a kiosk system on the Pi. Many thanks for sharing it.


  8. Further to my previous comment you can now install firefox-esr on RPi and it will run in kiosk mode. However right now I’ve not been able to make it do that automatically.

  9. Hello JonathanMH and others.

    Did anyone manage to get a separate chromium window on both screens? Any help is welcome.


  10. Anny ideas how to get this work on a rotated screen (portrait) on reboot?

    When i have the screen on normal rotation it works great. Even with xdotool to switch browser tabs. But when i rotate the screen, starting the service file ever thing is great, than i reboot and the service file is giving a error that de display is not found…. stopping the service and starting it seems to work again but on reboot it breaks….

Leave a Reply

Your email address will not be published. Required fields are marked *