Files
archivmail/features/PROJ-68-sudo-provisionierung-dienststeuerung.md
T
sysops 7300a696ca fix(PROJ-68): sudo-Provisionierung für Admin-Dienststeuerung ergänzen
Root Cause für den HTTP-500-Bug beim Manticore-Neustart über den Dienste-Tab:
sudo war auf 132 gar nicht installiert, admin_services_handlers.go ruft aber
für JEDE Dienst-Aktion sudo systemctl auf. Betraf nicht nur Manticore,
sondern alle Dienste in der Whitelist - PROJ-67 hat es nur erstmals sichtbar
gemacht.

install.sh/update.sh installieren jetzt sudo (falls fehlend) und legen
/etc/sudoers.d/archivmail mit NOPASSWD-Regeln für genau die Service-
Whitelist an (archivmail, archivmail-web, manticore, postgresql@17-main,
postfix, nginx) - validiert per visudo -c vor dem Einspielen, damit ein
Bug im Generator nie eine kaputte sudoers-Datei live schaltet. update.sh
zieht das als Backfill für Bestandsinstallationen nach, analog zum
PROJ-67-Upgrade-Pfad-Muster.

archivmail-nft-Helper (externe Zugriffskontrolle) fehlt auf 132 ebenfalls,
aber bewusst nicht Teil dieses Tickets (vermutlich firewall-security-Skill-
Verantwortung).
2026-07-05 19:49:56 +02:00

5.2 KiB

id, title, status, created
id title status created
PROJ-68 sudo-Provisionierung für Admin-Dienststeuerung fehlte komplett In Review 2026-07-05

Kontext

Beim QA-Test der neuen Versions-Spalte im Dienste-Tab (siehe Commit 8564d7c) wurde ein Neustart-Versuch für manticore über POST /api/admin/services/manticore getestet — Ergebnis: HTTP 500, Dienst nicht neu gestartet.

Root Cause (verifiziert auf 192.168.1.132): sudo ist auf 132 gar nicht installiert (kein /usr/bin/sudo, kein /etc/sudoers//etc/sudoers.d/). internal/api/admin_services_handlers.go ruft aber für JEDE Dienst-Aktion exec.Command("sudo", "/usr/bin/systemctl", action, name+".service") auf — das schlägt fehl mit „executable file not found“, CombinedOutput() ist leer, daher writeError(500, "") (leerer Body, schwer zu diagnostizieren).

Betrifft nicht nur Manticore — jede Dienst-Aktion (Start/Stop/Restart/ Enable/Disable) für ALLE Dienste in der Whitelist war auf 132 schon vorher kaputt, das PROJ-67/Versions-Feature hat es nur erstmals sichtbar gemacht, weil vorher niemand manticore (das jetzt neu in der Liste ist) über die UI neugestartet hat — wahrscheinlich wurde die Dienststeuerung insgesamt nie über die UI getestet, seit sie gebaut wurde.

install.sh legt den archivmail-Systembenutzer an (useradd --system --shell /bin/false ...), installiert aber nie sudo und legt nie eine /etc/sudoers.d/archivmail-Regel an. Der Go-Code setzt eine Server-Provisionierung voraus, die im Repo nirgends existiert — das war vermutlich ein manueller, nie dokumentierter Schritt bei der Ersteinrichtung von 131, der bei 132 (und jeder künftigen Neuinstallation) fehlt.

Separater, verwandter Fund: /usr/local/sbin/archivmail-nft (für die "Extern sperren/freigeben"-Buttons beim archivmail-Dienst) fehlt auf 132 ebenfalls und wird von install.sh auch nicht deployt — das ist vermutlich Teil des firewall-security-Skills und bewusst außerhalb dieses Tickets (siehe Non-Goals).

User Stories

  • Als Superadmin möchte ich Dienste (inkl. Manticore) über die Web-UI starten/stoppen/neustarten können, ohne mich per SSH einzuloggen.
  • Als Betreiber möchte ich, dass eine frische Installation (install.sh) die Dienststeuerung sofort funktionsfähig macht, ohne manuelle Nacharbeit auf dem Server.

Acceptance Criteria

  • install.sh installiert sudo (falls nicht vorhanden) und legt /etc/sudoers.d/archivmail mit NOPASSWD-Regeln für systemctl {start,stop,restart,enable,disable} auf genau die Service-Whitelist aus internal/api/admin_services_handlers.go (archivmail, archivmail-web, manticore, postgresql@17-main, postfix, nginx) an — keine allgemeine ALL-Regel.
  • Sudoers-Datei wird vor dem Einspielen mit visudo -c -f validiert (Syntaxfehler dürfen niemals eine funktionierende sudoers-Config kaputt machen).
  • update.sh zieht dieselbe Provisionierung nach (idempotent, prüft ob die Datei schon existiert/aktuell ist), damit auch 132 (und jede andere Bestandsinstallation) beim nächsten Deploy automatisch nachgerüstet wird — analog zum PROJ-67-Upgrade-Pfad-Muster.
  • Nach der Provisionierung: Start/Stop/Restart über POST /api/admin/services/{name} funktioniert für alle Dienste in der Whitelist, verifiziert auf 132.
  • archivmail-nft-Fehlen ist dokumentiert (nicht Teil dieses Tickets, siehe Non-Goals), damit es nicht als überraschender Folgefehler auftaucht.

Edge Cases

  • Sudoers-Syntaxfehler durch einen Bug im Provisionierungs-Code → darf niemals live installiert werden (visudo -c VOR dem Kopieren nach /etc/sudoers.d/, bei Fehler abbrechen statt eine korrupte Datei zu hinterlassen, die den gesamten sudo-Mechanismus auf dem Server lahmlegen könnte).
  • Datei existiert schon (z.B. von einem früheren manuellen Setup mit abweichendem Inhalt) → nicht blind überschreiben, sondern nur ergänzen falls Einträge fehlen, oder zumindest den bestehenden Inhalt vor dem Überschreiben sichern (.bak).
  • 131 (Produktiv) hat vermutlich schon eine funktionierende, manuell angelegte sudoers-Config (sonst wären Service-Aktionen dort auch nie gegangen) — Provisionierung muss idempotent/additiv sein, darf eine funktionierende Config nicht durch einen abweichenden Regelsatz ersetzen und brechen.

Non-Goals

  • archivmail-nft-Helper-Script (externe Zugriffskontrolle für Port 8080) wird NICHT in diesem Ticket gebaut — vermutlich Verantwortungsbereich des firewall-security-Skills, separates Ticket falls gewünscht.
  • Kein Umbau auf D-Bus/PolicyKit als Alternative zu sudo (größerer Architektur-Schnitt, nicht durch den akuten Bug gerechtfertigt).

Technical Requirements

  • Betroffene Dateien: install.sh, update.sh.
  • Whitelist im Sudoers-Generator muss mit allowedServices in internal/api/admin_services_handlers.go synchron gehalten werden (bei künftigen neuen Diensten beide Stellen anfassen — Risiko, dass das wieder auseinanderläuft, wie es beim manticore-Eintrag ja gerade passiert ist).

Implementation Notes

wird ergänzt.

QA Test Results

wird ergänzt.

Deployment

wird ergänzt.