Auf dem Rechner des Nutzers liegt im PATH ein ssh, das sich anders verhaelt als das System-ssh - die Skripte sollen sich darauf nicht verlassen. setup_pi.sh und deploy.sh riefen ssh, scp und rsync bisher ohne vollen Pfad auf. Beide Skripte nutzen jetzt SSH_BIN/SCP_BIN mit Default /usr/bin/ssh bzw. /usr/bin/scp, ueberschreibbar per NINLIGHT_SSH_BIN/NINLIGHT_SCP_BIN - dasselbe Prinzip wie NINLIGHT_STATION_ROOT weiter unten in deploy.sh, das Tests ohne echten Pi ermoeglicht. rsync bekommt "-e $SSH_BIN", damit auch dessen Transport ueber /usr/bin/ssh laeuft. Die Beispielaufrufe in setup_pi.sh's Abschlussmeldung und in der README bleiben bewusst bei schlichtem "ssh" - dort geht es um das, was der Nutzer selbst eintippt. test: tools/station/tests/test_deploy.sh auf den neuen Override umgestellt (NINLIGHT_SSH_BIN zeigt auf den ssh-Stub) und um ein Szenario ergaenzt, das den /usr/bin/ssh- bzw. /usr/bin/scp-Default in beiden Skripten absichert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
109 lines
4.5 KiB
Bash
Executable File
109 lines
4.5 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)
|
|
# /usr/bin/ssh und /usr/bin/scp statt Varianten im PATH, die sich anders verhalten koennen.
|
|
# Ueberschreibbar (wie NINLIGHT_STATION_ROOT in deploy.sh), damit ein Test gegen Stubs statt
|
|
# einen echten Pi laufen kann.
|
|
SSH_BIN=${NINLIGHT_SSH_BIN:-/usr/bin/ssh}
|
|
SCP_BIN=${NINLIGHT_SCP_BIN:-/usr/bin/scp}
|
|
|
|
echo "== Voraussetzungen auf $HOST pruefen =="
|
|
"$SSH_BIN" "$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_BIN" -q "$HERE/station.conf.example" "$HOST:/tmp/ninlight-station.conf.example"
|
|
"$SSH_BIN" "$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_BIN" -q "$HERE/server.py" "$HERE/ninlight-station" "$HERE/ninlight-station.service" "$HOST:/tmp/"
|
|
"$SSH_BIN" "$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_BIN" "$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
|