[Unit] Description=TESM Web App After=network.target [Service] Type=simple User=root WorkingDirectory=/srv/tesm # Markiert genau DIESEN Prozess als den echten Web-App-Dienst -- app.py # wird nämlich NICHT nur hierüber gestartet, sondern auch von # generate_ips.py (via "from app import ...") als reines Hilfsmodul # importiert, z.B. aus poe.sh/tesm-check.service heraus, alle paar # Sekunden. Ein einfacher Import führt JEDEN Modul-Level-Code in app.py # erneut aus -- ohne dieses Flag würde jeder generate_ips.py-Aufruf # _fileshare_cleanup_all_on_startup() erneut auslösen und damit gerade # aktive Fileshare-Mounts anderer, echter Sitzungen sofort wieder # aushängen. Siehe die Prüfung auf TESM_WEB_PROCESS in app.py. Environment=TESM_WEB_PROCESS=1 # Produktiver WSGI-Server (gunicorn) statt Flasks eigenem app.run()- # Entwicklungsserver -- siehe requirements.txt für die ausführliche # Begründung von "--workers 1" (In-Memory-Zustand) und "--worker-class # gthread" (blockierende WebSocket-Threads für das Browser-SSH-Terminal). # "--timeout 0" deaktiviert Gunicorns Worker-Timeout: der greift sonst # nach 30s auch bei einer offenen, aber gerade inaktiven SSH-Terminal- # WebSocket-Verbindung und würde den Worker (und damit JEDE Verbindung, # da nur ein Prozess läuft) killen. # "--bind 127.0.0.1:5000" statt 0.0.0.0: Flask/Gunicorn soll ausschließlich # über den nginx-Reverse-Proxy (siehe Einstellungen -> NGINX) erreichbar # sein, nicht zusätzlich direkt und unverschlüsselt über Port 5000 aus dem # Netz -- nginx selbst greift ohnehin nur über 127.0.0.1 zu. ExecStart=/srv/tesm/venv/bin/gunicorn --workers 1 --worker-class gthread --threads 16 \ --timeout 0 --bind 127.0.0.1:5000 app:app Restart=always RestartSec=5 [Install] WantedBy=multi-user.target