How the service works¶
PaperPi runs as a systemd service: systemd is the part of Linux that starts and watches programs like this one (a "service"). It starts PaperPi at every start of the Pi and starts it again after a crash. This page is about how that is put together. To install PaperPi: Install; to update or remove it: Update and Uninstall.
What the install script does¶
install/paperpi-install prints each step before it does it:
- Unless a config is already in
/etc/paperpi, it asks which screen is connected (or takes--display,--model,--vcom).0, or--yeswithout--display, means the virtual screen, which only saves pictures in/var/lib/paperpi/screen/. - It installs what is missing from Debian, after asking:
git,python3-venv, andgccandpython3-dev(they buildspidev, the SPI library). - For a real screen, it turns on SPI with
raspi-config nonint do_spi 0(the same as raspi-config's menu Interface Options, SPI). When SPI only works after a restart, it asks before restarting the Pi. - It makes the
paperpiuser, copies the newest release into/opt/paperpi/code(or the branch, tag or commit of--ref:curl ... | sudo bash -s -- --ref main), installs the Python packages ofuv.lock, writes the first config (paperpi example-config --setup: a clock and the set-up screen), and starts the service.
update does steps 2 and 4 again, without the questions and with the config as it is. PaperPi itself is always installed again, also when its version number hasn't changed between commits. How releases are made: Making a release.
Use¶
| To | Run |
|---|---|
| see whether it runs | systemctl status paperpi |
| follow the log | journalctl -u paperpi -f |
| apply a change to the config file made by hand | sudo paperpi reload (prints what changed, or the mistake that stops it; --check only checks) |
| restart / stop / start | sudo systemctl restart paperpi (or stop, start) |
| forget the web password | sudo paperpi reset-password, then sudo paperpi reload |
| web interface unreachable after a new port or address | sudo paperpi web-defaults, then sudo systemctl restart paperpi |
| check the health report | paperpi health |
When PaperPi crashes 5 times within 10 minutes, systemd stops trying (systemctl status paperpi says so). Fix the cause (see the log), then sudo systemctl reset-failed paperpi and sudo systemctl start paperpi.
Where the files are¶
| Path | What | Owner |
|---|---|---|
/opt/paperpi/code |
PaperPi's code, a copy of the GitHub repository | root |
/opt/paperpi/venv |
Python and its packages for PaperPi (the system's Python 3.13, the package versions of uv.lock) |
root |
/opt/paperpi/tools |
uv, which installs the packages |
root |
/etc/paperpi/paperpi.toml |
the config file; the web interface changes it | paperpi |
/var/lib/paperpi |
plugin files, the last good config, the log, screen-stuck |
paperpi |
/run/paperpi/health |
the health report, in memory | paperpi |
/etc/systemd/system/paperpi.service |
the service file (from install/paperpi.service) |
root |
/usr/local/bin/paperpi |
the paperpi command |
root |
/usr/local/sbin/paperpi-install |
the install script (install/paperpi-install), for update and uninstall |
root |
The code belongs to root, so PaperPi itself (and a plugin) can't change it. PaperPi runs as the user paperpi, which can't log in, has no password and is only in the spi and gpio groups. A plugin that goes wrong can't read your own files or use sudo.
The service file¶
install/paperpi.service:
Type=notify,WatchdogSec=120: systemd counts PaperPi as started only after it saysREADY=1, and restarts it when no "still running" message (WATCHDOG=1) arrives for 2 minutes. Only the main process may send them (NotifyAccess=main, the default), so a plugin process can't hide a stuck loop.TimeoutStopSec=45: longer than the screen clear at exit (30 s) and its check (2 s).KillModestays at its default,control-group: stopping the service ends every PaperPi process (plugin processes, the process that starts them, Python's resource tracker), also when the main process was killed withkill -9(#209). Never set it toprocessornone.Restart=on-failure,RestartSec=10, at most 5 starts in 10 minutes.SuccessExitStatus=75andRestartForceExitStatus=75: "Restart PaperPi" in the web interface ends PaperPi with exit status 75, which counts as a clean stop and starts it again (thepaperpiuser can't runsystemctl).RuntimeDirectoryandStateDirectory: systemd makes/run/paperpiand/var/lib/paperpifor thepaperpiuser.- Protection settings: PaperPi can write only
/etc/paperpi,/var/lib/paperpi,/run/paperpiand its own/tmp, can't see/home, and can use no devices but SPI and GPIO.
Check it on the Pi¶
sudo install/check-service (in a copy of the repository, with the service running) kills the main process with kill -9, checks that systemd starts PaperPi again and that no old process is left, then checks that systemctl stop ends within the time limit. It starts the service again at the end.