Files
kundenplattform/kundenplattform.service
adminandClaude Opus 5.5 7a7450c829 Mailversand ueber Ausgangstabelle (ADR-0041)
mail.py reiht Mails in mail_ausgang ein (Migration 0009), eine
Versandschleife im Dienst liefert sie per SMTP mit Anmeldung ein und
wiederholt bei Fehlern. Voreinstellung ist Trockenlauf; das Passwort
kommt als systemd-Credential. Dazu scripts/testmail.py und Tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:43:25 +02:00

62 lines
2.1 KiB
Desktop File

[Unit]
Description=Tuxflotte Kundenplattform
After=network.target
[Service]
Type=simple
User=kundenplattform
Group=kundenplattform
WorkingDirectory=/opt/kundenplattform
EnvironmentFile=/etc/tuxflotte/kundenplattform.env
# Mailversand (mail.py, ADR-0041): Das Postfach-Passwort kommt als
# systemd-Credential, nicht über die Umgebung. Erst einkommentieren, wenn
# die Datei existiert (root:root, 0600) - ob der Dienst ohne die Quelldatei
# startet, ist nicht geprüft. Bis dahin läuft der Versand als Trockenlauf.
#LoadCredential=mail_passwort:/etc/tuxflotte/kundenplattform-mail-passwort
ExecStart=/opt/kundenplattform/.venv/bin/uvicorn app:app --host 0.0.0.0 --port 8081
Restart=always
RestartSec=3
# Härtung - läuft bewusst unter einem eigenen, unprivilegierten System-User
# statt root (anders als provisioning-server, siehe ADR-0011: exponiertere,
# kundenzugängliche Komponente).
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/kundenplattform
# Erweiterte Sandboxing-Direktiven (2026-08-07 ergänzt, systemd-analyze
# security lag zuvor bei 8.3 "EXPOSED" trotz obiger Basis-Härtung). Braucht
# der Dienst nachweislich nicht - reines Python/uvicorn mit psycopg
# (Postgres via TCP), httpx (ausgehende HTTP-Aufrufe an provisioning-server)
# und cryptography (Fernet-Verschlüsselung des WLAN-PSK, siehe
# encryption.py) - alles unter genau dieser Direktivenkombination per
# systemd-run gegen den echten Code getestet (Login/JWT, DB-Lese-/
# Schreibzugriff, ausgehender HTTP-Aufruf, Fernet-Verschlüsselung), bevor
# das hier scharf geschaltet wurde.
CapabilityBoundingSet=
AmbientCapabilities=
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
ProtectProc=invisible
ProcSubset=pid
PrivateDevices=yes
RemoveIPC=yes
RestrictRealtime=yes
SystemCallFilter=@system-service
SystemCallArchitectures=native
UMask=0077
[Install]
WantedBy=multi-user.target