Hallo zusammen,
aus aktuellem Anlass geb ich hier mal nen kurzen Setup-Leitfaden, wie man einen Raspberry Pi 2 mit Debian in ein Kiosk-System verwandelt.
Genereller Hinweis: Keine Kommandos einfach kopieren, ohne zu wissen, was da passiert. Es droht SCHON BEIM ERSTEN SCHRITT DATENVERLUST!
Benötigt:
Raspberry Pi 2 B
Speicherkarte (>= 4GB) von der Liste der funktionierenden Karten
Bildschirm (HDMI), idealerweise mit USB (dann kann man sich das RPi-Netzteil sparen)
Das Image
Collabora hat ein RPi2-Image mit Custom Kernel veröffentlicht, das mit den Repositories von Debian zusammenarbeitet. Es findet sich hier, der Thread dazu dort. User ist root, Passwort lautet 'debian' (ohne Anführungszeichen). Dass das geändert werden sollte, ist logisch. Aber der Reihe nach. Erstmal runterladen und mit den bmap-tools auf die Karte ziehen (das kann das bmaptool in einem Rutsch):
[src=bash]sudo bmaptool copy https://images.collabora.co.uk/rpi2/jessie-rpi2-20150705.img.gz /dev/sdb[/src]
(Falls eure Karte in /dev/sdb eingebunden wird - manche Kartenleser sind so angeschlossen, andere binden Karten als /dev/mmcblk0 ein)
Danach Karte rein und Raspi starten. SSH sollte schon drauf sein, also mit ssh root@$IP drauf und die erste Einrichtung anfangen.
Customizing
Das Image ist englisch, die deutschen Pakete lassen sich aber mit Umstellung der Sprache nachinstallieren. Zuerst würde ich aber die sources.list auf einen deutschen Server umstellen:
[src=bash]deb http://ftp.de.debian.org/debian/ jessie main non-free contrib
deb http://security.debian.org/ jessie/updates main contrib non-free
deb http://ftp.de.debian.org/debian/ jessie-updates main contrib non-free
deb http://ftp.de.debian.org/debian/ jessie-backports main contrib non-free[/src]
Backports sind wichtig, da wir später midori brauchen, der sich für Jessie ne Maintainer-Auszeit genommen hat und nur in den Backports verfügbar ist.
Danach Umstellung auf die Locales, verwendete Tastatur (falls nötig) und Zeit:
[src=bash]dpkg-reconfigure locales
dpkg-reconfigure keyboard-configuration
dpkg-reconfigure tzdata[/src]
Jetzt: User anlegen. Ein administrativer User, ein Kiosk-User. Grund: Der Kiosk-User wird von uns später so zusammengestrichen, dass er ein Programm ausführt, nichts anderes. Außerdem hat ein Kiosk-Benutzer, der ja potentiell allen Menschen offen steht, keine Rechte auf dem System zu haben.
[src=bash]adduser admin
adduser admin sudo
adduser kiosk[/src]
SSH-Konfiguration
Root sperren
Wichtig. Momentan ist ja noch das Collabora-Passwort drauf.
[src=bash]sudo passwd -d root
sudo passwd -l root[/src]
Und ja, wir sperren den Rootlogin doppelt. Niemand hat da rumzufuhrwerken. Die Diskussion root vs. sudo wurde an anderer Stelle schon getätigt, und für mich gilt nach wie vor: Wenn ein Angreifer deinen Benutzernamen schon weiß, ist die BruteForce-Attacke erfolgversprechend. Wenn er den Benutzernamen nicht weiß (weil root nicht einloggen darf), dann muss er zwei Felder brüten, der Aufwand ist exponentiell höher.
Programme nachinstallieren
[src=bash]sudo apt-get install xorg x11-xserver-utils xautomation midori matchbox-window-manager [/src]
Kiosk anpassen
Der User muss leicht angepasst werden, und zwar in zwei Dateien:
.xsession: X11-Login-Handling
Abzulegen in /home/kiosk als .xsession mit den Rechten 644 und User/Group jeweils root.
browser.sh: Bereitstellung und Management des Browsers
Abzulegen in /home/kiosk als browser.sh mit den Rechten 755 und User/Group jeweils root.
Außerdem werden üblicherweise Dateien in .cache .config und .local abgelegt - das macht auf Dauer die Karte kaputt und ist evtl. ein Datenleck, also ab damit in den RAM:
[src=bash]sudo ln -s /run/user/1001/.cache /home/kiosk/.cache
sudo ln -s /run/user/1001/.config /home/kiosk/.config
sudo ln -s /run/user/1001/.local /home/kiosk/.local[/src]
Autologin
Ist nicht nötig, aber ein paar Dinge müssen wir hier auch für nicht-Autologin-Systeme einrichten! Der Autologin selbst ist nur ein Parameter in Zeile 35.
Wir löschen zuerst den Symlink für das tty1-Interface im Systemd und kopieren die zugehörige Datei nach /etc
[src=bash]sudo rm /etc/systemd/system/getty.target.wants/getty\@tty.service
sudo cp /lib/systemd/system/getty\@.service /etc/systemd/system/getty.target.wants/getty\@tty1.service[/src]
Das ist nötig, weil Config-Dateien nie in /lib abgelegt werden - ein Update würde sie sofort überschreiben. In etc hingegen wir nichts überschrieben.
Die so kopierte Config passen wir nun an:
Wer keinen Autologin möchte, schreibt Zeile 35 in der Originaldatei einfach nicht um bzw. lässt das "--autologin kiosk" weg.
Automatische Neustarts etc.
Wir erstellen einen Cronjob, indem wir in /etc/cron.d/ die Datei reloader anlegen:
[src=bash]# Dealing with hickup problems
MAILTO="admin"
# Syntax
# m h dom mon dow user command
# Restart IRQ balancer once a day
0 0 * * * root /usr/sbin/service irqbalance restart
# Restart browser once a day
0 0 * * * root /home/kiosk/browser.sh restart
# Rebooting the machine once a month
0 5 1 * * root /sbin/reboot[/src]
[src=bash][/src]
Der IRQ Balancer ist ein Dienst, der aufm Raspi auch gern mal Amok läuft und irgendwann mehr Ressourcen braucht als er balanced. Bis das kritisch wird, dauert es meist zwei bis drei Wochen, aber der tägliche Restart schadet nicht (kann man auch stündlich machen, wenn man will).
Der Rest sollte selbsterklärend sein.
DISCLAIMER: Ich hab mit Sicherheit ein paar Sicherheitslücken drin, kann die aber grad nicht fixen, weil ich weder die Zeit noch den Druck von Sicherheits-Seite hab. Außerdem liegt mir grad keiner vor, den ich anpassen und testen könnte. Ich kann auch nicht garantieren, dass es hier grad vollständig ist, es ist ausm Kopf geschrieben. Wenn was fehlen sollte, oder nicht funktioniert, trag ich das später nach.
P.S.: Die Scripte hab ich geschrieben - copyleft included.
aus aktuellem Anlass geb ich hier mal nen kurzen Setup-Leitfaden, wie man einen Raspberry Pi 2 mit Debian in ein Kiosk-System verwandelt.
Genereller Hinweis: Keine Kommandos einfach kopieren, ohne zu wissen, was da passiert. Es droht SCHON BEIM ERSTEN SCHRITT DATENVERLUST!
Benötigt:
Raspberry Pi 2 B
Speicherkarte (>= 4GB) von der Liste der funktionierenden Karten
Bildschirm (HDMI), idealerweise mit USB (dann kann man sich das RPi-Netzteil sparen)
Das Image
Collabora hat ein RPi2-Image mit Custom Kernel veröffentlicht, das mit den Repositories von Debian zusammenarbeitet. Es findet sich hier, der Thread dazu dort. User ist root, Passwort lautet 'debian' (ohne Anführungszeichen). Dass das geändert werden sollte, ist logisch. Aber der Reihe nach. Erstmal runterladen und mit den bmap-tools auf die Karte ziehen (das kann das bmaptool in einem Rutsch):
[src=bash]sudo bmaptool copy https://images.collabora.co.uk/rpi2/jessie-rpi2-20150705.img.gz /dev/sdb[/src]
(Falls eure Karte in /dev/sdb eingebunden wird - manche Kartenleser sind so angeschlossen, andere binden Karten als /dev/mmcblk0 ein)
Danach Karte rein und Raspi starten. SSH sollte schon drauf sein, also mit ssh root@$IP drauf und die erste Einrichtung anfangen.
Customizing
Das Image ist englisch, die deutschen Pakete lassen sich aber mit Umstellung der Sprache nachinstallieren. Zuerst würde ich aber die sources.list auf einen deutschen Server umstellen:
Nützlich in diesem Zusammenhang:
https://www.debian.org/mirror/list
https://www.debian.org/mirror/list
deb http://security.debian.org/ jessie/updates main contrib non-free
deb http://ftp.de.debian.org/debian/ jessie-updates main contrib non-free
deb http://ftp.de.debian.org/debian/ jessie-backports main contrib non-free[/src]
Backports sind wichtig, da wir später midori brauchen, der sich für Jessie ne Maintainer-Auszeit genommen hat und nur in den Backports verfügbar ist.
Danach Umstellung auf die Locales, verwendete Tastatur (falls nötig) und Zeit:
[src=bash]dpkg-reconfigure locales
dpkg-reconfigure keyboard-configuration
dpkg-reconfigure tzdata[/src]
Jetzt: User anlegen. Ein administrativer User, ein Kiosk-User. Grund: Der Kiosk-User wird von uns später so zusammengestrichen, dass er ein Programm ausführt, nichts anderes. Außerdem hat ein Kiosk-Benutzer, der ja potentiell allen Menschen offen steht, keine Rechte auf dem System zu haben.
[src=bash]adduser admin
adduser admin sudo
adduser kiosk[/src]
SSH-Konfiguration
Wer wie ich gern remote arbeitet, will sicher die sshd_config anpassen. Meine empfohlenen Einstellungen sind:
[src=bash]# Package generated configuration file
# See the sshd_config(5) manpage for details
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes
# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication:
LoginGraceTime 1
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
# Users allowed for SSH
AllowUsers admin
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes
# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
X11Forwarding no
#X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no
#MaxStartups 10:30:60
#Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM no[/src]
Dazu muss natürlich in /home/admin das Directory .ssh (der Punkt ist wichtig) angelegt werden, in das muss der SSH-PublicKey des Administrators (also eurer) als authorized_keys hinterlegt werden. Einfach die .pub-Datei rüberkopieren und umbenennen. Nicht vergessen, über 'service ssh restart' die neue sshd_config einlesen lassen. Danach Logout und mit SSH von eurer administrativen Maschine weiter arbeiten.
[src=bash]# Package generated configuration file
# See the sshd_config(5) manpage for details
# What ports, IPs and protocols we listen for
Port 22
# Use these options to restrict which interfaces/protocols sshd will bind to
#ListenAddress ::
#ListenAddress 0.0.0.0
Protocol 2
# HostKeys for protocol version 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
#Privilege Separation is turned on for security
UsePrivilegeSeparation yes
# Lifetime and size of ephemeral version 1 server key
KeyRegenerationInterval 3600
ServerKeyBits 1024
# Logging
SyslogFacility AUTH
LogLevel INFO
# Authentication:
LoginGraceTime 1
PermitRootLogin no
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
# Users allowed for SSH
AllowUsers admin
# Don't read the user's ~/.rhosts and ~/.shosts files
IgnoreRhosts yes
# For this to work you will also need host keys in /etc/ssh_known_hosts
RhostsRSAAuthentication no
# similar for protocol version 2
HostbasedAuthentication no
# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication
#IgnoreUserKnownHosts yes
# To enable empty passwords, change to yes (NOT RECOMMENDED)
PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosGetAFSToken no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
X11Forwarding no
#X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
#UseLogin no
#MaxStartups 10:30:60
#Banner /etc/issue.net
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM no[/src]
Dazu muss natürlich in /home/admin das Directory .ssh (der Punkt ist wichtig) angelegt werden, in das muss der SSH-PublicKey des Administrators (also eurer) als authorized_keys hinterlegt werden. Einfach die .pub-Datei rüberkopieren und umbenennen. Nicht vergessen, über 'service ssh restart' die neue sshd_config einlesen lassen. Danach Logout und mit SSH von eurer administrativen Maschine weiter arbeiten.
Root sperren
Wichtig. Momentan ist ja noch das Collabora-Passwort drauf.
[src=bash]sudo passwd -d root
sudo passwd -l root[/src]
Und ja, wir sperren den Rootlogin doppelt. Niemand hat da rumzufuhrwerken. Die Diskussion root vs. sudo wurde an anderer Stelle schon getätigt, und für mich gilt nach wie vor: Wenn ein Angreifer deinen Benutzernamen schon weiß, ist die BruteForce-Attacke erfolgversprechend. Wenn er den Benutzernamen nicht weiß (weil root nicht einloggen darf), dann muss er zwei Felder brüten, der Aufwand ist exponentiell höher.
Programme nachinstallieren
[src=bash]sudo apt-get install xorg x11-xserver-utils xautomation midori matchbox-window-manager [/src]
Kiosk anpassen
Der User muss leicht angepasst werden, und zwar in zwei Dateien:
.xsession: X11-Login-Handling
Abzulegen in /home/kiosk als .xsession mit den Rechten 644 und User/Group jeweils root.
[src=bash]xset s off
xset -dpms
matchbox-window-manager &
/home/kiosk/browser.sh reload &
/home/kiosk/browser.sh browser
exit 0[/src]
Auch wenn die Datei kein Shellscript ist, wird sie trotzdem ausgeführt, und zwar vom X11, das macht sie quasi zum Script.
Die ersten zwei Optionen schalten den Bildschirmschoner und die Energieeffizienz-Einrichtungen ab, die dritte Zeile startet den matchbox-Window-Manager, der sich um Mausklicks, Tastatureingaben, Fullscreen etc. kümmert und zu den beiden folgenden Zeilen kommen wir gleich. Am Ende steht das exit-Statment (das ist eigentlich optional,
aber ich mach das generell, ein Fehlerpunkt weniger in manchen Konfigurationen).
xset -dpms
matchbox-window-manager &
/home/kiosk/browser.sh reload &
/home/kiosk/browser.sh browser
exit 0[/src]
Auch wenn die Datei kein Shellscript ist, wird sie trotzdem ausgeführt, und zwar vom X11, das macht sie quasi zum Script.
Die ersten zwei Optionen schalten den Bildschirmschoner und die Energieeffizienz-Einrichtungen ab, die dritte Zeile startet den matchbox-Window-Manager, der sich um Mausklicks, Tastatureingaben, Fullscreen etc. kümmert und zu den beiden folgenden Zeilen kommen wir gleich. Am Ende steht das exit-Statment (das ist eigentlich optional,
aber ich mach das generell, ein Fehlerpunkt weniger in manchen Konfigurationen).
browser.sh: Bereitstellung und Management des Browsers
Abzulegen in /home/kiosk als browser.sh mit den Rechten 755 und User/Group jeweils root.
[src=bash]#!/bin/bash
# Browser management script for kiosk user
case "$1" in
browser)
# Starts & restarts browser in fullscreen mode
while true
do
midori -e Fullscreen -p -a http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl
done
;;
reload)
# Reloads the web page every 10 seconds
sleep 10
while true
do
xte 'sleep 10' 'key F5'
done
;;
restart)
# Restarts the browser, so the Raspis don't have to be rebooted that often
# First: Find out midori PID & strip it from whitespaces
MIDORI_PID=`ps ax | grep midori | grep -v grep | cut -d 't' -f 1 -s | tr -d '[:space:]'`
# Second: Just kill the bastard, restart will be done by the parent script
kill $MIDORI_PID
exit 0
;;
*)
# This should not happen
exit 1
;;
esac
exit 0[/src]
Der Parameter "browser" nach Aufruf des Scripts bewirkt das Starten des Browsers im Vollbild, allerdings in einer Schleife. Ist ein User mal so frei, mit F11 den Fullscreen zu beenden und aufs Kreuzchen zu drücken, startet sich der Browser sofort neu. Die Browseroptionen sind (-a) Starte in eigener Anwendung, d. h. nicht mit irgendwelchen alten Tabs im Hintergrund, und (-p) im Privatmodus. (-e Fullscreen) dürfte selbsterklärend sein.
Der Parameter "reload" schickt ein F5 an den Browser und veranlasst damit einen Seitenreload. Das ist nützlich, wenn man eine Seite wie die vorliegende hat, die bei jedem Aufruf ein anderes Statement/Bild etc. generiert oder der automatische Reload einer Nachrichtenseite buggy ist und zu Abstürzen neigt. Letzteres war in meinem Fall zutreffend.
Der Parameter "restart" killt den Browser. Midori hat die Eigenschaft, sich nach und nach vollzufressen, ein Neustart behebt das üblicherweise. Wie das automatisiert wird, kommt noch.
Kleine Anmerkung zur Zeile, in der die Midori-PID ausgelesen wird, und zwar im Speziellen das cut-Statment: Der Denominator t ist gefährlich. In diesem Fall nicht,
weil Midori immer auf einem tty läuft, und der Denominator genau dieses erste t als ersten Bruchpunkt interpretiert, aber ich hatte schon eine Implementierung, in der ich den Denominator p für eine virtuelle Konsole hatte, die je nach aufrufendem Userkontext nicht vorhanden (also mit ? ersetzt) war. Eine bessere Lösung wäre eigentlich ein zweizeiliges Statement wie dieses hier:
[src=bash]MIDORI_PROCLINE=`ps ax | grep "$SB_IDENT" | grep -v grep`
MIDORI_PID=`echo "${MIDORI_PROCLINE:0:5}" | tr -d [:space:]`[/src]
Hier wird aus der einzigen Fundstelle der 'ps ax'-Ausgabe (Variable: MIDORI_PROCLINE) genau 5 Zeichen extrahiert, beginnend ab Position 0 (der nicht vorhandene Platz kurz vor dem 1. Zeichen). Da PIDs maximal 5 Zeichen haben, aber bei weniger Zeichen mit Leerzeichen am Beginn aufgefüllt wird, ist diese Version treffsicherer. Die Leerzeichen selbst werden am Ende einfach mit tr weggeschnitten, übrig bleibt die reine PID, allerdings ohne Zeilenumbruch. Das ist jedoch nur relevant, wenn man dieses Command direkt mit echo ausgeben würde, sobald es wie hier in eine Variable verpackt wurde, interessiert das nicht mehr. Wer möchte, kann das umschreiben, ich hab hier nur eine laufende Config genommen und es als gute Gelegenheit genutzt, etwas über kleine, nicht-alltägliche Quirks loszuwerden.
# Browser management script for kiosk user
case "$1" in
browser)
# Starts & restarts browser in fullscreen mode
while true
do
midori -e Fullscreen -p -a http://pages.cs.wisc.edu/~ballard/bofh/bofhserver.pl
done
;;
reload)
# Reloads the web page every 10 seconds
sleep 10
while true
do
xte 'sleep 10' 'key F5'
done
;;
restart)
# Restarts the browser, so the Raspis don't have to be rebooted that often
# First: Find out midori PID & strip it from whitespaces
MIDORI_PID=`ps ax | grep midori | grep -v grep | cut -d 't' -f 1 -s | tr -d '[:space:]'`
# Second: Just kill the bastard, restart will be done by the parent script
kill $MIDORI_PID
exit 0
;;
*)
# This should not happen
exit 1
;;
esac
exit 0[/src]
Der Parameter "browser" nach Aufruf des Scripts bewirkt das Starten des Browsers im Vollbild, allerdings in einer Schleife. Ist ein User mal so frei, mit F11 den Fullscreen zu beenden und aufs Kreuzchen zu drücken, startet sich der Browser sofort neu. Die Browseroptionen sind (-a) Starte in eigener Anwendung, d. h. nicht mit irgendwelchen alten Tabs im Hintergrund, und (-p) im Privatmodus. (-e Fullscreen) dürfte selbsterklärend sein.
Der Parameter "reload" schickt ein F5 an den Browser und veranlasst damit einen Seitenreload. Das ist nützlich, wenn man eine Seite wie die vorliegende hat, die bei jedem Aufruf ein anderes Statement/Bild etc. generiert oder der automatische Reload einer Nachrichtenseite buggy ist und zu Abstürzen neigt. Letzteres war in meinem Fall zutreffend.
Der Parameter "restart" killt den Browser. Midori hat die Eigenschaft, sich nach und nach vollzufressen, ein Neustart behebt das üblicherweise. Wie das automatisiert wird, kommt noch.
Kleine Anmerkung zur Zeile, in der die Midori-PID ausgelesen wird, und zwar im Speziellen das cut-Statment: Der Denominator t ist gefährlich. In diesem Fall nicht,
weil Midori immer auf einem tty läuft, und der Denominator genau dieses erste t als ersten Bruchpunkt interpretiert, aber ich hatte schon eine Implementierung, in der ich den Denominator p für eine virtuelle Konsole hatte, die je nach aufrufendem Userkontext nicht vorhanden (also mit ? ersetzt) war. Eine bessere Lösung wäre eigentlich ein zweizeiliges Statement wie dieses hier:
[src=bash]MIDORI_PROCLINE=`ps ax | grep "$SB_IDENT" | grep -v grep`
MIDORI_PID=`echo "${MIDORI_PROCLINE:0:5}" | tr -d [:space:]`[/src]
Hier wird aus der einzigen Fundstelle der 'ps ax'-Ausgabe (Variable: MIDORI_PROCLINE) genau 5 Zeichen extrahiert, beginnend ab Position 0 (der nicht vorhandene Platz kurz vor dem 1. Zeichen). Da PIDs maximal 5 Zeichen haben, aber bei weniger Zeichen mit Leerzeichen am Beginn aufgefüllt wird, ist diese Version treffsicherer. Die Leerzeichen selbst werden am Ende einfach mit tr weggeschnitten, übrig bleibt die reine PID, allerdings ohne Zeilenumbruch. Das ist jedoch nur relevant, wenn man dieses Command direkt mit echo ausgeben würde, sobald es wie hier in eine Variable verpackt wurde, interessiert das nicht mehr. Wer möchte, kann das umschreiben, ich hab hier nur eine laufende Config genommen und es als gute Gelegenheit genutzt, etwas über kleine, nicht-alltägliche Quirks loszuwerden.
Außerdem werden üblicherweise Dateien in .cache .config und .local abgelegt - das macht auf Dauer die Karte kaputt und ist evtl. ein Datenleck, also ab damit in den RAM:
[src=bash]sudo ln -s /run/user/1001/.cache /home/kiosk/.cache
sudo ln -s /run/user/1001/.config /home/kiosk/.config
sudo ln -s /run/user/1001/.local /home/kiosk/.local[/src]
Autologin
Ist nicht nötig, aber ein paar Dinge müssen wir hier auch für nicht-Autologin-Systeme einrichten! Der Autologin selbst ist nur ein Parameter in Zeile 35.
Wir löschen zuerst den Symlink für das tty1-Interface im Systemd und kopieren die zugehörige Datei nach /etc
[src=bash]sudo rm /etc/systemd/system/getty.target.wants/getty\@tty.service
sudo cp /lib/systemd/system/getty\@.service /etc/systemd/system/getty.target.wants/getty\@tty1.service[/src]
Das ist nötig, weil Config-Dateien nie in /lib abgelegt werden - ein Update würde sie sofort überschreiben. In etc hingegen wir nichts überschrieben.
Die so kopierte Config passen wir nun an:
[src=bash]# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes
# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0
[Service]
# the VT is cleared by TTYVTDisallocate
# Setting up tempfs environment
ExecStartPre=/bin/mkdir -p /run/user/1001
ExecStartPre=/bin/mkdir -p /run/user/1001/.cache
ExecStartPre=/bin/mkdir -p /run/user/1001/.config
ExecStartPre=/bin/mkdir -p /run/user/1001/.local
ExecStartPre=/bin/chown -R 1001:1001 /run/user/1001
# Logging in the user
ExecStart=-/sbin/agetty --autologin kiosk --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
[Install]
WantedBy=getty.target
DefaultInstance=tty1[/src]
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service
# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes
# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0
[Service]
# the VT is cleared by TTYVTDisallocate
# Setting up tempfs environment
ExecStartPre=/bin/mkdir -p /run/user/1001
ExecStartPre=/bin/mkdir -p /run/user/1001/.cache
ExecStartPre=/bin/mkdir -p /run/user/1001/.config
ExecStartPre=/bin/mkdir -p /run/user/1001/.local
ExecStartPre=/bin/chown -R 1001:1001 /run/user/1001
# Logging in the user
ExecStart=-/sbin/agetty --autologin kiosk --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
[Install]
WantedBy=getty.target
DefaultInstance=tty1[/src]
Automatische Neustarts etc.
Wir erstellen einen Cronjob, indem wir in /etc/cron.d/ die Datei reloader anlegen:
[src=bash]# Dealing with hickup problems
MAILTO="admin"
# Syntax
# m h dom mon dow user command
# Restart IRQ balancer once a day
0 0 * * * root /usr/sbin/service irqbalance restart
# Restart browser once a day
0 0 * * * root /home/kiosk/browser.sh restart
# Rebooting the machine once a month
0 5 1 * * root /sbin/reboot[/src]
[src=bash][/src]
Der IRQ Balancer ist ein Dienst, der aufm Raspi auch gern mal Amok läuft und irgendwann mehr Ressourcen braucht als er balanced. Bis das kritisch wird, dauert es meist zwei bis drei Wochen, aber der tägliche Restart schadet nicht (kann man auch stündlich machen, wenn man will).
Der Rest sollte selbsterklärend sein.
DISCLAIMER: Ich hab mit Sicherheit ein paar Sicherheitslücken drin, kann die aber grad nicht fixen, weil ich weder die Zeit noch den Druck von Sicherheits-Seite hab. Außerdem liegt mir grad keiner vor, den ich anpassen und testen könnte. Ich kann auch nicht garantieren, dass es hier grad vollständig ist, es ist ausm Kopf geschrieben. Wenn was fehlen sollte, oder nicht funktioniert, trag ich das später nach.
P.S.: Die Scripte hab ich geschrieben - copyleft included.
Zuletzt bearbeitet: