[Unit] Description=EEG-Abrechnung (Flask + gunicorn, hinter Apache-Reverse-Proxy) After=network.target Wants=network.target [Service] Type=notify User=eeg Group=eeg WorkingDirectory=/var/www/html/eeg-assistent/abrechnung/v1.05_upload Environment="PATH=/var/www/html/eeg-assistent/abrechnung/venv/bin" Environment="PYTHONUNBUFFERED=1" Environment="PYTHONPATH=/var/www/html/eeg-assistent/abrechnung:/var/www/html/eeg-assistent/abrechnung/v1.05_upload" # Admin-Passwort-Hash und SMTP-Credentials aus separater Umgebungsdatei. # /etc/eeg-abrechnung.env muss owner=root, mode 0600 sein. # Erwartete Schluessel: EEG_ADMIN_PASSWORD_HASH, SMTP_SERVER, SMTP_PORT, # SMTP_USERNAME, SMTP_PASSWORD, SMTP_USE_SSL, ABRECHNUNG_LICENSE_DB. EnvironmentFile=-/etc/eeg-abrechnung.env ExecStart=/var/www/html/eeg-assistent/abrechnung/venv/bin/gunicorn \ --config /var/www/html/eeg-assistent/abrechnung/v1.05_upload/gunicorn_config.py \ app:app # Saubere Signale + Restart-Politik KillSignal=SIGTERM TimeoutStopSec=30 Restart=on-failure RestartSec=5s # Security hardening NoNewPrivileges=yes ProtectSystem=strict ProtectHome=yes PrivateTmp=yes PrivateDevices=yes ProtectControlGroups=yes ProtectKernelModules=yes ProtectKernelTunables=yes RestrictNamespaces=yes LockPersonality=yes MemoryDenyWriteExecute=no RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX CapabilityBoundingSet= AmbientCapabilities= # Schreibrechte nur auf die Daten-/Runtime-Verzeichnisse ReadWritePaths=/var/www/html/eeg-assistent/abrechnung/v1.05_upload ReadWritePaths=/var/lib/eeg-abrechnung/data ReadWritePaths=/var/www/html/eeg-assistent/abrechnung/logs StandardOutput=journal StandardError=journal SyslogIdentifier=eeg-abrechnung [Install] WantedBy=multi-user.target