434 lines
15 KiB
Bash
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# ===================================================================
# MYP Druckerverwaltung - Installer für Raspbian Kiosk-System
# Entwickelt auf Windows, ausführbar auf Raspberry Pi / Debian
# OHNE virtualenv - verwendet System-Python mit --break-system-packages
# ===================================================================
set -euo pipefail
# =========================== KONFIGURATION ===========================
APP_NAME="MYP Druckerverwaltung"
APP_DIR="/opt/myp"
SERVICE_NAME="myp-kiosk"
CURRENT_DIR="$(pwd)"
INSTALL_LOG="/var/log/myp-install.log"
# Farben für Ausgabe
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
NC='\033[0m'
# ========================== LOGGING-SYSTEM ==========================
log() {
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$INSTALL_LOG"
}
error() {
echo -e "${RED}[FEHLER] $1${NC}" | tee -a "$INSTALL_LOG"
exit 1
}
warning() {
echo -e "${YELLOW}[WARNUNG] $1${NC}" | tee -a "$INSTALL_LOG"
}
info() {
echo -e "${BLUE}[INFO] $1${NC}" | tee -a "$INSTALL_LOG"
}
progress() {
echo -e "${PURPLE}[FORTSCHRITT] $1${NC}" | tee -a "$INSTALL_LOG"
}
# ========================== SYSTEM-CHECKS ==========================
check_root() {
if [ "$EUID" -ne 0 ]; then
error "Dieses Skript muss als Root ausgeführt werden: sudo $0"
fi
export PATH="/usr/sbin:/sbin:/usr/bin:/bin:/usr/local/bin:$PATH"
}
check_debian_system() {
if [ ! -f /etc/debian_version ]; then
error "Dieses Skript ist nur für Debian/Raspbian-Systeme geeignet!"
fi
log "✅ Debian/Raspbian-System erkannt"
}
# ========================== MERCEDES ZERTIFIKATE ==========================
install_mercedes_certificates() {
log "=== INSTALLIERE MERCEDES SSL-ZERTIFIKATE ==="
progress "Aktualisiere CA-Zertifikate..."
# CA-Zertifikate Paket installieren/aktualisieren
apt-get install -y ca-certificates curl || error "CA-Zertifikate Installation fehlgeschlagen"
# Standard CA-Bundle aktualisieren
update-ca-certificates || warning "CA-Zertifikate Update teilweise fehlgeschlagen"
# Mercedes Corporate Zertifikate installieren (falls vorhanden)
if [ -d "$CURRENT_DIR/certs/mercedes" ] && [ "$(ls -A $CURRENT_DIR/certs/mercedes 2>/dev/null)" ]; then
progress "Installiere Mercedes Corporate Zertifikate..."
# Alle .crt und .pem Dateien kopieren
find "$CURRENT_DIR/certs/mercedes" -type f \( -name "*.crt" -o -name "*.pem" -o -name "*.cer" \) -exec cp {} /usr/local/share/ca-certificates/ \; 2>/dev/null || true
# Zertifikate aktualisieren
update-ca-certificates || warning "Mercedes Zertifikate Update fehlgeschlagen"
log "✅ Mercedes Zertifikate installiert"
else
info "Keine Mercedes Zertifikate gefunden - verwende Standard CA-Bundle"
fi
# Python SSL-Konfiguration optimieren
progress "Konfiguriere Python SSL-Einstellungen..."
# pip Konfiguration für SSL
mkdir -p /root/.pip
cat > /root/.pip/pip.conf << EOF
[global]
trusted-host = pypi.org
pypi.python.org
files.pythonhosted.org
cert = /etc/ssl/certs/ca-certificates.crt
timeout = 60
retries = 3
[install]
trusted-host = pypi.org
pypi.python.org
files.pythonhosted.org
EOF
# Python HTTPS-Konfiguration
export SSL_CERT_FILE="/etc/ssl/certs/ca-certificates.crt"
export REQUESTS_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"
export CURL_CA_BUNDLE="/etc/ssl/certs/ca-certificates.crt"
# Pip auf neueste Version aktualisieren
progress "Aktualisiere pip auf neueste Version..."
python3 -m pip install --upgrade pip --break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org || warning "pip Update fehlgeschlagen"
# SSL-Test durchführen
progress "Teste SSL-Verbindung zu PyPI..."
if python3 -c "import ssl, urllib.request; urllib.request.urlopen('https://pypi.org')" 2>/dev/null; then
log "✅ SSL-Verbindung zu PyPI erfolgreich"
else
warning "⚠️ SSL-Verbindung zu PyPI problematisch - Installation wird dennoch versucht"
fi
log "✅ Mercedes SSL-Zertifikate und Python-Konfiguration abgeschlossen"
}
# ========================== ABHÄNGIGKEITEN INSTALLIEREN ==========================
install_system_dependencies() {
log "=== INSTALLIERE SYSTEM-ABHÄNGIGKEITEN ==="
progress "Aktualisiere Paketlisten..."
apt-get update -y || error "APT Update fehlgeschlagen"
progress "Installiere Python 3 und grundlegende Pakete..."
apt-get install -y \
python3 \
python3-pip \
python3-dev \
python3-setuptools \
build-essential \
libssl-dev \
libffi-dev \
git \
curl \
wget \
nano \
htop \
rsync \
unzip \
sudo \
systemd \
ca-certificates \
gnupg \
lsb-release \
sqlite3 \
|| error "System-Pakete Installation fehlgeschlagen"
# WICHTIG: Mercedes Zertifikate vor Python-Paketen installieren
install_mercedes_certificates
progress "Installiere Python-Abhängigkeiten mit Mercedes SSL-Konfiguration..."
# SSL-freundliche pip-Installation mit Fallback-Optionen
PIP_OPTS="--break-system-packages --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org --timeout 60 --retries 3"
# Core Flask Framework
pip3 install $PIP_OPTS Flask==3.1.1 || pip3 install $PIP_OPTS Flask || error "Flask Installation fehlgeschlagen"
pip3 install $PIP_OPTS Flask-Login==0.6.3 || pip3 install $PIP_OPTS Flask-Login || error "Flask-Login Installation fehlgeschlagen"
pip3 install $PIP_OPTS Flask-WTF==1.2.1 || pip3 install $PIP_OPTS Flask-WTF || error "Flask-WTF Installation fehlgeschlagen"
# Datenbank
pip3 install $PIP_OPTS SQLAlchemy==2.0.36 || pip3 install $PIP_OPTS SQLAlchemy || error "SQLAlchemy Installation fehlgeschlagen"
# Sicherheit
pip3 install $PIP_OPTS bcrypt==4.2.1 || pip3 install $PIP_OPTS bcrypt || error "bcrypt Installation fehlgeschlagen"
pip3 install $PIP_OPTS cryptography==44.0.0 || pip3 install $PIP_OPTS cryptography || error "cryptography Installation fehlgeschlagen"
pip3 install $PIP_OPTS Werkzeug==3.1.3 || pip3 install $PIP_OPTS Werkzeug || error "Werkzeug Installation fehlgeschlagen"
# Smart Plug Steuerung
pip3 install $PIP_OPTS PyP100 || warning "PyP100 Installation fehlgeschlagen (optional)"
# HTTP Requests
pip3 install $PIP_OPTS requests==2.32.3 || pip3 install $PIP_OPTS requests || error "requests Installation fehlgeschlagen"
# System Monitoring
pip3 install $PIP_OPTS psutil==6.1.1 || pip3 install $PIP_OPTS psutil || error "psutil Installation fehlgeschlagen"
# Redis (optional)
pip3 install $PIP_OPTS redis==5.2.1 || warning "redis Installation fehlgeschlagen (optional)"
# Weitere Core-Abhängigkeiten
pip3 install $PIP_OPTS MarkupSafe==3.0.2 || pip3 install $PIP_OPTS MarkupSafe || error "MarkupSafe Installation fehlgeschlagen"
# Produktions-Server
pip3 install $PIP_OPTS gunicorn==23.0.0 || pip3 install $PIP_OPTS gunicorn || error "gunicorn Installation fehlgeschlagen"
log "✅ Alle Abhängigkeiten erfolgreich installiert"
}
# ========================== PRODUKTIONS-KIOSK SETUP ==========================
setup_production_kiosk() {
log "=== RICHTE PRODUKTIONS-KIOSK-MODUS EIN ==="
# Zuerst Abhängigkeiten installieren
install_system_dependencies
progress "Erstelle Zielverzeichnis /opt/myp..."
mkdir -p "$APP_DIR" || error "Konnte Zielverzeichnis nicht erstellen"
progress "Kopiere Projektdateien selektiv nach $APP_DIR..."
# Liste der zu kopierenden Dateien/Ordner (ohne unnötige Inhalte)
declare -a COPY_ITEMS=(
"app.py"
"models.py"
"requirements.txt"
"blueprints/"
"config/"
"database/"
"docs/"
"static/"
"templates/"
"uploads/"
"utils/"
"logs/"
"certs/"
)
# Sichere selektive Kopie
for item in "${COPY_ITEMS[@]}"; do
if [ -e "$CURRENT_DIR/$item" ]; then
progress "Kopiere: $item"
cp -r "$CURRENT_DIR/$item" "$APP_DIR/" || warning "Fehler beim Kopieren von $item"
else
info "Überspringe nicht vorhandenes Element: $item"
fi
done
# Spezielle Dateien einzeln kopieren (falls vorhanden)
for file in "package.json" "package-lock.json" "tailwind.config.js" "postcss.config.js"; do
if [ -f "$CURRENT_DIR/$file" ]; then
cp "$CURRENT_DIR/$file" "$APP_DIR/" || warning "Fehler beim Kopieren von $file"
fi
done
# Stelle sicher, dass app.py ausführbar ist
chmod +x "$APP_DIR/app.py" || error "Konnte app.py nicht ausführbar machen"
# Erstelle notwendige Verzeichnisse falls sie nicht existieren
mkdir -p "$APP_DIR/database/backups"
mkdir -p "$APP_DIR/logs/app"
mkdir -p "$APP_DIR/logs/auth"
mkdir -p "$APP_DIR/logs/errors"
mkdir -p "$APP_DIR/uploads/temp"
# Berechtigungen setzen
chown -R root:root "$APP_DIR"
chmod -R 755 "$APP_DIR"
chmod 750 "$APP_DIR/database"
chmod 750 "$APP_DIR/logs"
chmod 755 "$APP_DIR/uploads"
progress "Erstelle Systemd-Service myp-kiosk.service..."
cat > "/etc/systemd/system/${SERVICE_NAME}.service" << EOF
[Unit]
Description=MYP Druckerverwaltung Kiosk-Modus
After=network.target network-online.target
Wants=network-online.target
Requires=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=$APP_DIR
ExecStart=/usr/bin/python3 $APP_DIR/app.py --debug
Restart=always
RestartSec=5
StartLimitBurst=5
StartLimitInterval=60
# Umgebungsvariablen
Environment=PYTHONUNBUFFERED=1
Environment=FLASK_ENV=production
Environment=FLASK_HOST=0.0.0.0
Environment=FLASK_PORT=5000
Environment=PYTHONPATH=$APP_DIR
Environment=LC_ALL=C.UTF-8
Environment=LANG=C.UTF-8
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myp-kiosk
# Security-Einstellungen
NoNewPrivileges=true
PrivateTmp=false
ProtectSystem=strict
ReadWritePaths=$APP_DIR
[Install]
WantedBy=multi-user.target
EOF
progress "Lade Systemd-Konfiguration neu..."
systemctl daemon-reload || error "Systemd Reload fehlgeschlagen"
progress "Aktiviere und starte $SERVICE_NAME Service..."
systemctl enable "$SERVICE_NAME.service" || error "Service Enable fehlgeschlagen"
systemctl start "$SERVICE_NAME.service" || error "Service Start fehlgeschlagen"
# Service-Status prüfen
sleep 5
if systemctl is-active --quiet "$SERVICE_NAME.service"; then
log "$SERVICE_NAME Service läuft erfolgreich"
info "Service-Status: $(systemctl is-active $SERVICE_NAME.service)"
info "Port 5000: Flask-App läuft im Debug-Modus"
info "Projektverzeichnis: $APP_DIR"
# Test der Anwendung
progress "Teste Anwendungserreichbarkeit..."
sleep 3
if curl -s http://localhost:5000 > /dev/null 2>&1; then
log "✅ Anwendung ist unter http://localhost:5000 erreichbar"
else
warning "⚠️ Anwendung noch nicht erreichbar (möglicherweise noch beim Starten)"
fi
else
error "$SERVICE_NAME Service konnte nicht gestartet werden - prüfen Sie die Logs: journalctl -u $SERVICE_NAME -f"
fi
log "✅ Produktions-Kiosk-Modus erfolgreich eingerichtet"
log "🎯 Anwendung erreichbar unter: http://localhost:5000"
log "📋 Service-Befehle:"
log " • Status: sudo systemctl status $SERVICE_NAME"
log " • Stoppen: sudo systemctl stop $SERVICE_NAME"
log " • Starten: sudo systemctl start $SERVICE_NAME"
log " • Neustarten: sudo systemctl restart $SERVICE_NAME"
log " • Logs: sudo journalctl -u $SERVICE_NAME -f"
log " • Service-Info: sudo journalctl -u $SERVICE_NAME --no-pager"
}
# ========================== HAUPTMENÜ ==========================
show_menu() {
clear
echo -e "${BLUE}=================================================================${NC}"
echo -e "${GREEN} $APP_NAME - Installer für Raspbian${NC}"
echo -e "${BLUE}=================================================================${NC}"
echo ""
echo -e "${YELLOW}Aktuelles Verzeichnis:${NC} $CURRENT_DIR"
echo -e "${YELLOW}Systemzeit:${NC} $(date)"
echo -e "${YELLOW}Zielverzeichnis:${NC} $APP_DIR"
echo ""
echo -e "${PURPLE}Wählen Sie eine Option:${NC}"
echo ""
echo -e "${GREEN}1)${NC} System vorbereiten (Abhängigkeiten installieren)"
echo -e " → Installiert Python 3, pip und alle benötigten Pakete"
echo -e " → Verwendet: pip install --break-system-packages"
echo -e " → Keine virtualenv, direktes System-Python"
echo ""
echo -e "${GREEN}2)${NC} Produktions-Kiosk-Modus installieren"
echo -e " → Führt System-Vorbereitung durch"
echo -e " → Verschiebt Dateien selektiv nach /opt/myp/"
echo -e " → Erstellt systemd-Service: myp-kiosk.service"
echo -e " → Startet Flask-App mit --debug auf Port 5000"
echo -e " → Testet Anwendungserreichbarkeit"
echo ""
echo -e "${RED}0)${NC} Beenden"
echo ""
echo -e "${BLUE}=================================================================${NC}"
echo -n "Ihre Wahl [0-2]: "
}
# ========================== MAIN LOGIC ==========================
main() {
# System-Checks
check_root
check_debian_system
# Erstelle Log-Datei
mkdir -p "$(dirname "$INSTALL_LOG")"
touch "$INSTALL_LOG"
log "=== MYP INSTALLER GESTARTET ==="
log "Arbeitsverzeichnis: $CURRENT_DIR"
log "Zielverzeichnis: $APP_DIR"
log "Service-Name: $SERVICE_NAME"
log "System: $(uname -a)"
log "Debian-Version: $(cat /etc/debian_version 2>/dev/null || echo 'Unbekannt')"
while true; do
show_menu
read -r choice
case $choice in
1)
clear
log "=== OPTION 1: SYSTEM VORBEREITEN ==="
install_system_dependencies
echo ""
echo -e "${GREEN}✅ System-Vorbereitung abgeschlossen!${NC}"
echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}"
read -r
;;
2)
clear
log "=== OPTION 2: PRODUKTIONS-KIOSK-MODUS ==="
setup_production_kiosk
echo ""
echo -e "${GREEN}✅ Produktions-Kiosk-Modus erfolgreich eingerichtet!${NC}"
echo -e "${BLUE} Die Anwendung startet automatisch bei jedem Systemstart.${NC}"
echo -e "${YELLOW}Drücken Sie Enter, um fortzufahren...${NC}"
read -r
;;
0)
log "=== INSTALLER BEENDET ==="
echo -e "${GREEN}Auf Wiedersehen!${NC}"
echo -e "${BLUE}Log-Datei: $INSTALL_LOG${NC}"
exit 0
;;
*)
echo -e "${RED}Ungültige Eingabe. Bitte wählen Sie 0-2.${NC}"
sleep 2
;;
esac
done
}
# Script starten
main "$@"