I would like to share my experience of setting up the Raspberry Pi 3B + as a kiosk with a GUI based on the Kivy library for Python 3. Why Kivy? It's just that we already have a product developed in Python, we would like to add a graphical interface to it. It's worth noting that before Kivy, we tried several options, including wxWidgets and even a Chromium browser with a web app. All these alternatives proved to be powerless against Kivy, light and fast. A very good overview of this library is already on Habré .
Environment
We will be using Raspbian Lite with Python 3.7 and the Supervisor process and service management system. By the way, the Raspberry Pi Imager utility is very convenient , with which you can prepare an SD card. After the first download of our baby RPi, we log in using the standard pi login and raspberry password . Then we execute:
$ sudo raspi-config
We select the fifth item Interfacing Options , in the menu that appears we are interested in the second item SSH , with which we will enable remote access for convenience.
So, leaning back comfortably in your favorite chair, we will continue configuring RPi through any convenient ssh client.
User
Let's create a user with a convenient name for us, allow him to use sudo and reboot:
$ sudo useradd -m kivygui -s /bin/bash
$ sudo passwd kivygui
$ sudo usermod -a -G sudo kivygui
$ sudo reboot
After rebooting, log in via ssh with the new data for kivygui and remove the standard pi account :
$ sudo userdel pi
$ sudo rm -r /home/pi/
It will not be superfluous to point out that we are using the American keyboard layout:
$ sudo sed -i 's/XKBLAYOUT="gb"/XKBLAYOUT="us"/' /etc/default/keyboard
Test application
Our test application will be in a separate folder, let's create it:
$ mkdir /home/kivygui/helloworld
Now, in the nano text editor, let's create a script to run the Python application /home/kivygui/helloworld/run.sh with the following content:
export DISPLAY=:0.0
xset s off -dpms
exec matchbox-window-manager &
while true; do
exec python3 start.py
done
Let's make in nano and an example of a simple interface in the file /home/kivygui/helloworld/start.py:
import kivy
kivy.require('1.11.0')
from kivy.app import App
from kivy.uix.label import Label
class MyApp(App):
def build(self):
return Label(text='Hello, world!')
if __name__ == '__main__':
MyApp().run()
Graphical user interface
We need pip3 :
$ sudo apt-get update -y
$ sudo apt-get install -y python3-pip
I also came across the fact that when installing nodm, all the necessary packages were not always downloaded, so just in case, we will install them in advance:
$ sudo apt-get install -y desktop-base gtk2-engines-pixbuf libxklavier16 xserver-xorg xserver-xorg-input-all xserver-xorg-input-libinput xserver-xorg-input-wacom xserver-xorg-legacy xserver-xorg-video-all xserver-xorg-video-amdgpu xserver-xorg-video-ati xserver-xorg-video-fbdev xserver-xorg-video-nouveau xserver-xorg-video-radeon xserver-xorg-video-vesa
Now let's set nodm and window manager matchbox :
$ sudo DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true apt-get install -y x11-xserver-utils nodm matchbox-window-manager
$ echo "/usr/sbin/nodm" | sudo tee /etc/X11/default-display-manager
$ sudo sed -i -e "s/NODM_ENABLED=false/NODM_ENABLED=true/" -e "s/NODM_USER=root/NODM_USER=kivygui/" -e "s/NODM_X_OPTIONS='-nolisten tcp'/NODM_X_OPTIONS='-nolisten tcp -nocursor'/" /etc/default/nodm
Now it's Kivy's turn :
$ sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev pkg-config libgl1-mesa-dev libgles2-mesa-dev python-setuptools libgstreamer1.0-dev git-core gstreamer1.0-plugins-{bad,base,good,ugly} gstreamer1.0-{omx,alsa} python-dev libmtdev-dev xclip xsel libjpeg-dev
$ sudo python3 -m pip install --user kivy
Now we will teach our system to show us a graphical interface instead of a console prompt, hide all diagnostic messages and show a graphical system boot screen:
$ sudo rm /etc/systemd/system/default.target
$ sudo rm /etc/systemd/system/getty@tty1.service.d/autologin.conf
$ sudo ln -s /lib/systemd/system/graphical.target /etc/systemd/system/default.target
$ sudo sed -i '$ s/$/ quiet splash consoleblank=0 loglevel=0 logo.nologo plymouth.ignore-serial-consoles/' /boot/cmdline.txt
$ sudo sed -i 's/console=tty1/console=tty3/' /boot/cmdline.txt
If desired, the tty1 console can be disabled altogether:
$ sudo systemctl disable getty@tty1
Supervisord
Now let's install Supervisor :
$ sudo apt-get install -y supervisor
Let's create a folder for logs:
$ mkdir /home/kivygui/logs
Now, let's stop the Supervisor service for a while to reconfigure:
$ sudo systemctl stop supervisor
Add the following to the configuration file /etc/supervisor/supervisord.conf using the nano editor :
[program:rungui]
command=sh run.sh
directory=/home/kivygui/helloworld
user=root
autostart=true
autorestart=true
startsecs = 5
startretries=3
stderr_logfile=/home/kivygui/logs/rungui.err.log
stdout_logfile=/home/kivygui/logs/rungui.out.log
stderr_logfile_maxbytes=5MB
stdout_logfile_maxbytes=5MB
stopsignal=INT
stopwaitsecs=5
Also, let's give kivygui and root users some extra options. To do this, use the command:
$ sudo visudo
Let's bring the file to the following form:
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
kivygui ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
kivygui ALL = NOPASSWD: /usr/bin/supervisorctl
kivygui ALL = NOPASSWD: /usr/bin/python3.7
kivygui ALL=(ALL) NOPASSWD: /bin/systemctl daemon-reload
kivygui ALL=(ALL) NOPASSWD: /usr/bin/supervisord
root ALL=(ALL) NOPASSWD: /bin/systemctl daemon-reload
root ALL = NOPASSWD: /usr/bin/supervisorctl
root ALL = NOPASSWD: /usr/bin/python3.7
root ALL=(ALL) NOPASSWD: /usr/bin/supervisord
Now we can start the service:
$ sudo systemctl start supervisor
On the monitor connected to the RPi, we will see the cherished greeting. All that remains is to reboot to test the graphical boot screen.
PS
In fact, nodm can be replaced with lightdm with autologin . It will be absolutely similar to nodm solution. Moreover, the nodm developer himself recommends this approach.