#!/bin/bash # ============================================================================ # PVPlex Edge Agent - Installer # ============================================================================ # Installs the PVPlex Edge Agent on a Raspberry Pi. # Usage: curl -sSL https://cloud.pvplex.com/download/install.sh | sudo bash # # Supported: Raspberry Pi 3B+, 4, 5 with Raspberry Pi OS Bookworm # ============================================================================ set -euo pipefail INSTALL_DIR="/opt/pvplex" REPO_URL="https://github.com/pvplex-com/edge-agent.git" CLOUD_URL="https://cloud.pvplex.com" PACKAGE_URL="$CLOUD_URL/download/pvplex-edge.tar.gz" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "${GREEN}[PVPlex]${NC} $1"; } warn() { echo -e "${YELLOW}[PVPlex]${NC} $1"; } error() { echo -e "${RED}[PVPlex]${NC} $1"; exit 1; } # -- Pre-checks -- if [ "$(id -u)" -ne 0 ]; then error "Bitte als root ausfuehren: sudo bash install.sh" fi ARCH=$(uname -m) if [[ "$ARCH" != "aarch64" && "$ARCH" != "armv7l" && "$ARCH" != "armv6l" ]]; then error "Nicht unterstuetzt: $ARCH (nur Raspberry Pi armv7l/aarch64)" fi log "PVPlex Edge Agent Installer" log "================================" log "Plattform: $(uname -s) $ARCH" log "Installationsverzeichnis: $INSTALL_DIR" echo "" # -- System packages -- log "Installiere Systempakete..." apt-get update -qq apt-get install -y -qq \ python3 python3-pip python3-venv \ git \ curl \ network-manager \ dnsmasq \ > /dev/null 2>&1 # Ensure NetworkManager manages WiFi log "Konfiguriere NetworkManager..." if [ -f /etc/NetworkManager/NetworkManager.conf ]; then if ! grep -q "managed=true" /etc/NetworkManager/NetworkManager.conf 2>/dev/null; then cat >> /etc/NetworkManager/NetworkManager.conf << 'NMEOF' [device] wifi.scan-rand-mac-address=no [ifupdown] managed=true NMEOF fi fi # Disable default dnsmasq (we run our own instance for captive portal) systemctl stop dnsmasq 2>/dev/null || true systemctl disable dnsmasq 2>/dev/null || true # Restart NetworkManager to pick up changes systemctl restart NetworkManager sleep 2 # -- Download & Install PVPlex -- if [ -d "$INSTALL_DIR/pvplex" ]; then log "Aktualisiere bestehende Installation..." # Backup config if exists if [ -f "$INSTALL_DIR/data/config.yaml" ]; then cp "$INSTALL_DIR/data/config.yaml" /tmp/pvplex-config-backup.yaml fi fi mkdir -p "$INSTALL_DIR" # -- Install PVPlex (git clone for OTA updates) -- INSTALL_OK=false if [ -d "$INSTALL_DIR/.git" ]; then # Existing git repo: pull latest log "Aktualisiere bestehende Installation..." cd "$INSTALL_DIR" git fetch origin 2>/dev/null || true # Checkout latest tag if available, otherwise pull master LATEST_TAG=$(git tag --sort=-v:refname 2>/dev/null | head -1) if [ -n "$LATEST_TAG" ]; then log "Neueste Version: $LATEST_TAG" git checkout "$LATEST_TAG" 2>/dev/null || git pull origin master else git pull origin master 2>/dev/null || true fi INSTALL_OK=true else # Fresh install: try git clone first (needed for OTA updates) log "Installiere PVPlex Edge Agent..." if command -v git &>/dev/null; then log "Klone Git-Repository (fuer automatische Updates)..." if git clone --depth 1 "$REPO_URL" "$INSTALL_DIR" 2>/dev/null; then # Checkout latest tag if available cd "$INSTALL_DIR" git fetch --tags 2>/dev/null || true LATEST_TAG=$(git tag --sort=-v:refname 2>/dev/null | head -1) if [ -n "$LATEST_TAG" ]; then log "Wechsle zu Version $LATEST_TAG" git checkout "$LATEST_TAG" 2>/dev/null || true fi INSTALL_OK=true else warn "Git-Clone fehlgeschlagen, versuche Download..." fi fi fi # Fallback 1: Download tarball from cloud server if [ "$INSTALL_OK" = false ]; then log "Lade Paket von $PACKAGE_URL herunter..." if curl -sSfL "$PACKAGE_URL" -o /tmp/pvplex-edge.tar.gz 2>/dev/null; then log "Download erfolgreich, entpacke..." tar -xzf /tmp/pvplex-edge.tar.gz -C "$INSTALL_DIR" --strip-components=0 rm -f /tmp/pvplex-edge.tar.gz INSTALL_OK=true warn "Installation ohne Git - automatische Updates nicht verfuegbar." warn "Fuer Updates: git installieren und Installer erneut ausfuehren." fi fi # Fallback 2: Local files (USB stick) if [ "$INSTALL_OK" = false ]; then SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [ -f "$SCRIPT_DIR/requirements.txt" ] && [ -d "$SCRIPT_DIR/pvplex" ]; then log "Verwende lokale Dateien..." cp -r "$SCRIPT_DIR/pvplex" "$INSTALL_DIR/" cp -r "$SCRIPT_DIR/systemd" "$INSTALL_DIR/" cp "$SCRIPT_DIR/requirements.txt" "$INSTALL_DIR/" INSTALL_OK=true warn "Installation ohne Git - automatische Updates nicht verfuegbar." fi fi if [ "$INSTALL_OK" = false ]; then error "Installation fehlgeschlagen. Pruefe Internetverbindung oder nutze USB-Stick-Installation." fi # Restore config backup if [ -f /tmp/pvplex-config-backup.yaml ]; then mkdir -p "$INSTALL_DIR/data" mv /tmp/pvplex-config-backup.yaml "$INSTALL_DIR/data/config.yaml" fi # -- Python venv -- log "Erstelle Python Virtual Environment..." python3 -m venv "$INSTALL_DIR/venv" "$INSTALL_DIR/venv/bin/pip" install --upgrade pip -q "$INSTALL_DIR/venv/bin/pip" install -r "$INSTALL_DIR/requirements.txt" -q # -- Create data directory -- mkdir -p "$INSTALL_DIR/data" # Write initial state if not exists if [ ! -f "$INSTALL_DIR/data/setup_state.json" ]; then echo '{"state": "unconfigured"}' > "$INSTALL_DIR/data/setup_state.json" fi # -- Install systemd services -- log "Installiere systemd Services..." cp "$INSTALL_DIR/systemd/pvplex-boot.service" /etc/systemd/system/ cp "$INSTALL_DIR/systemd/pvplex-edge.service" /etc/systemd/system/ cp "$INSTALL_DIR/systemd/pvplex-setup.service" /etc/systemd/system/ systemctl daemon-reload # Only enable the boot manager - it handles starting edge/setup systemctl enable pvplex-boot.service systemctl disable pvplex-edge.service 2>/dev/null || true systemctl disable pvplex-setup.service 2>/dev/null || true # -- Serial port permissions -- # Add current user to dialout group for serial access if id "pi" &>/dev/null; then usermod -a -G dialout pi fi # -- Done -- echo "" log "============================================" log " Installation abgeschlossen!" log "============================================" log "" log "Naechste Schritte:" log " 1. Starte den Raspberry Pi neu: sudo reboot" log " 2. Verbinde dich mit dem WLAN 'PVPlex-XXXX'" log " 3. Der Einrichtungsassistent oeffnet sich automatisch" log " 4. Folge den 4 Schritten zur Konfiguration" log "" log "Bei Problemen:" log " sudo systemctl status pvplex-boot" log " sudo journalctl -u pvplex-boot -f" log "" read -p "Jetzt neustarten? [j/N] " -n 1 -r echo "" if [[ $REPLY =~ ^[Jj]$ ]]; then log "Neustart..." reboot fi