Files
ninlight-w600/tools/station/setup_pi.sh
T
Michael SauerandClaude Sonnet 5 d23b0d4e02 fix: Rechte-Bug und Passwort-Leck im NM-Profil, Loesch-Bug in deploy.sh
setup_pi.sh sourcte /etc/ninlight-station.conf (0600 root:root) als
unprivilegierter Benutzer und scheiterte damit bei jedem Lauf, bevor
das NetworkManager-Profil angelegt wurde. Die Konfiguration wird jetzt
per "sudo cat" gelesen; ninlight-station macht denselben Fallback fuer
den dokumentierten Aufruf als normaler Benutzer, ohne die Datei fuer
alle lesbar zu machen.

Das AP-Profil wird nicht mehr per "nmcli ... wifi-sec.psk $PSK"
angelegt (das WLAN-Passwort waere sonst fuer jeden lokalen Prozess in
der Kommandozeile sichtbar), sondern als NetworkManager-Keyfile
(0600 root:root) geschrieben und per "nmcli connection load"
eingelesen.

deploy.sh loeschte bei einem gezielten Deploy eines einzelnen
Geraetetyps per "rsync --delete" alle Images anderer Geraetetypen aus
dem live ausgelieferten Verzeichnis. --delete laeuft jetzt nur noch
beim Vollabgleich (kein target-Argument); ein gezielter Deploy ersetzt
nur die genannten Dateien. Dabei zusaetzlich -c (Checksumme statt
Groesse+Zeitstempel) ergaenzt, sonst uebersieht rsync ein neues Image
mit zufaellig gleicher Byte-Groesse. Ausserdem meldet deploy.sh jetzt
einen fehlgeschlagenen Dienst-Neustart als Fehler statt ihn mit "Dienst
laeuft nicht" zu verwechseln.

Stub-Tests unter tools/station/tests/test_deploy.sh (ssh/rsync im PATH
ersetzt, Installationsschritt laeuft gegen ein Sandbox-Verzeichnis)
decken beide Bugfixes sowie die bereits bestehenden Faelle ab: Image
besteht die Trailer-Pruefung nicht, keine Images gefunden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 12:52:44 +02:00

104 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Richtet einen Raspberry Pi als ninlight-Recovery-Station ein. Idempotent:
# mehrfaches Ausfuehren aendert nichts und schadet nicht.
#
# Aufruf: tools/station/setup_pi.sh <pi-host>
set -euo pipefail
HOST=${1:?Aufruf: tools/station/setup_pi.sh <pi-host>}
HERE=$(cd "$(dirname "$0")" && pwd)
echo "== Voraussetzungen auf $HOST pruefen =="
ssh "$HOST" 'set -e
systemctl is-active --quiet NetworkManager || { echo "NetworkManager laeuft nicht - dieser Plan setzt ihn voraus" >&2; exit 1; }
nmcli -t -f DEVICE,STATE device | grep -q "^wlan0:" || { echo "wlan0 wird nicht von NetworkManager verwaltet" >&2; exit 1; }
python3 -c "import sys; sys.exit(0 if sys.version_info >= (3,11) else 1)" || { echo "Python 3.11+ noetig" >&2; exit 1; }
echo " ok"'
echo "== Konfiguration =="
scp -q "$HERE/station.conf.example" "$HOST:/tmp/ninlight-station.conf.example"
ssh "$HOST" 'set -e
if [ -f /etc/ninlight-station.conf ]; then
echo " /etc/ninlight-station.conf existiert bereits, bleibt unveraendert"
else
sudo install -m 0600 /tmp/ninlight-station.conf.example /etc/ninlight-station.conf
echo " /etc/ninlight-station.conf aus der Vorlage angelegt"
fi
rm -f /tmp/ninlight-station.conf.example'
echo "== Server, CLI und Unit installieren =="
scp -q "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/"
ssh "$HOST" 'set -e
sudo install -d -m 0755 /opt/ninlight-station /opt/ninlight-station/images
sudo install -m 0755 /tmp/server.py /opt/ninlight-station/server.py
sudo install -m 0755 /tmp/ninlight-station /usr/local/bin/ninlight-station
sudo install -m 0644 /tmp/ninlight-station.service /etc/systemd/system/ninlight-station.service
rm -f /tmp/server.py /tmp/ninlight-station /tmp/ninlight-station.service
sudo systemctl daemon-reload
echo " installiert"'
echo "== NetworkManager-Profil =="
# Zwei Dinge, die man an einer echten Lampenstation nicht falsch machen darf:
# - /etc/ninlight-station.conf ist 0600 root:root (das Passwort soll nicht
# jeder lesen koennen). Der SSH-Benutzer ist aber nicht root, direktes
# ". /etc/ninlight-station.conf" wuerde also mit "Permission denied"
# abbrechen. "sudo cat" + eval liest sie dennoch ein, ohne die Rechte der
# Datei aufzuweichen.
# - "nmcli ... wifi-sec.psk $PSK" wuerde das Passwort als Kommandozeilen-
# argument an einen Prozess uebergeben - fuer jeden lokalen Benutzer per
# "ps"/"/proc/<pid>/cmdline" sichtbar. Deshalb wird das Verbindungsprofil
# stattdessen direkt als NetworkManager-Keyfile (0600 root:root)
# geschrieben; das Passwort landet nur in einer Root-Datei, nie in einer
# Prozessliste.
ssh "$HOST" bash -s <<'REMOTE'
set -e
eval "$(sudo cat /etc/ninlight-station.conf)"
CONN_FILE="/etc/NetworkManager/system-connections/${AP_CONNECTION}.nmconnection"
if sudo test -f "$CONN_FILE"; then
UUID=$(sudo sed -n 's/^uuid=//p' "$CONN_FILE" | head -n1)
ACTION="aktualisiert"
else
UUID=$(cat /proc/sys/kernel/random/uuid)
ACTION="angelegt"
fi
TMP=$(mktemp)
trap 'rm -f "$TMP"' EXIT
{
printf '%s\n' '[connection]'
printf 'id=%s\n' "$AP_CONNECTION"
printf 'uuid=%s\n' "$UUID"
printf '%s\n' 'type=wifi'
printf '%s\n' 'interface-name=wlan0'
printf '%s\n' 'autoconnect=false'
printf '\n%s\n' '[wifi]'
printf '%s\n' 'mode=ap'
printf 'ssid=%s\n' "$SSID"
printf '%s\n' 'band=bg'
printf '%s\n' 'channel=6'
printf '\n%s\n' '[wifi-security]'
printf '%s\n' 'key-mgmt=wpa-psk'
printf '%s\n' 'proto=rsn'
printf '%s\n' 'pairwise=ccmp;'
printf '%s\n' 'group=ccmp;'
printf 'psk=%s\n' "$PSK"
printf '\n%s\n' '[ipv4]'
printf '%s\n' 'method=shared'
printf '%s\n' 'address1=192.168.8.1/24'
printf '\n%s\n' '[ipv6]'
printf '%s\n' 'method=disabled'
} >"$TMP"
sudo install -o root -g root -m 0600 "$TMP" "$CONN_FILE"
rm -f "$TMP"
sudo nmcli connection load "$CONN_FILE" >/dev/null
echo " Profil $AP_CONNECTION $ACTION"
REMOTE
cat <<'EOF'
Fertig. Die Station ist absichtlich noch AUS.
Naechste Schritte:
tools/station/deploy.sh <pi-host> Images ausliefern
ssh <pi-host> ninlight-station on Station einschalten
ssh <pi-host> ninlight-station off wieder ausschalten (nicht vergessen)
EOF