# Befundbericht: Erster Linux-Lauf **Datum: 26.08.2026** · Prüfplan: [PRUEFPLAN-Linux-Betrieb.md](./PRUEFPLAN-Linux-Betrieb.md) · Roadmap: [A4a](../ROADMAP.md) **Testsystem:** Ubuntu 26.04 LTS, Kernel 7.0.0-30, x86_64, 31 GB RAM, 5 CPUs, Zeitzone `Europe/Berlin`. .NET SDK 10.0.111 mit Runtime 10.0.11 bereits vorhanden. Zugriff über SSH (WireGuard, Schlüssel-Authentifizierung). > **Kernaussage: PolyTrader läuft auf Linux.** Build, Tests, Publish und Start funktionieren. > Ein echter Fehler wurde gefunden und behoben. Der Durchgang ist **nicht vollständig** — für > systemd-Betrieb, Oberfläche und Zeitzonen-Nachweis fehlen eine Datenbank und `sudo`. --- ## 1. Was funktioniert | Prüfpunkt | Ergebnis | |---|---| | **Build** | `dotnet build -c Release`: **0 Fehler**, 15 Warnungen — exakt dieselben wie unter Windows. Keine plattformbedingte Abweichung | | **Tests** | **476 von 476 grün**, 3 s Laufzeit — identisch zu Windows | | **Publish** | `linux-x64`, framework-abhängig: 121 Dateien, 41 MB. Ausführbare Datei trägt bereits das Ausführungsrecht | | **Start** | Die Anwendung startet mit `--headless` und durchläuft die komplette Startsequenz | | **Native Abhängigkeiten** | **Keine nötig.** Die Vermutung aus dem Prüfplan ist bestätigt: `--headless` ruft `BuildAvaloniaApp()` nie auf, Skia und HarfBuzz werden nie geladen. `libfontconfig1` & Co. mussten **nicht** installiert werden | | **Master-Key** | Wird beim ersten Start erzeugt und mit Rechten **`0600`** abgelegt — `FilePermissions` arbeitet unter Linux korrekt. AES-256-GCM meldet sich als aktiv | | **Zeitzone** | `Europe/Berlin` wird korrekt erkannt und gemeldet | | **Lizenz-Gate** | Verhält sich exakt wie dokumentiert: Warnung, „eingeschränkter Modus", **kein** Programmabbruch | | **Logging** | `Logs/` wird angelegt und beschrieben | **Bemerkenswert:** Zwischen Windows und Linux gibt es bei Build und Tests **keinen einzigen Unterschied** — weder in der Fehler- noch in der Warnungszahl. Die Portierungsarbeit hat gehalten. --- ## 2. Befunde ### B-1 · Absturz statt Fehlermeldung ohne Datenbank · **behoben** **Beobachtet:** Ohne konfigurierten Connection-String lief die Anwendung an und starb tief im DI-Aufbau: ``` Unhandled exception. System.ArgumentException: The string argument 'connectionString' cannot be empty. at Microsoft.EntityFrameworkCore.Utilities.Check.NullButNotEmpty(...) … rund 50 weitere Zeilen … EXITCODE: 134 (SIGABRT) ``` **Warum das mehr ist als Kosmetik:** Für einen Serverbetrieb ist das doppelt schlecht. Der Betreiber sieht nicht, *was* fehlt, und systemd startet den Dienst wegen `Restart=on-failure` alle zehn Sekunden neu — im Journal stehen dann endlose Startversuche statt der Ursache. Und genau dieser Zustand ist bei einer **Erstinstallation der wahrscheinlichste**: Software liegt da, Zugangsdaten sind noch nicht gesetzt. Das betrifft direkt Schnitt D-5 (`setup.json`). **Behoben** (Commit `Verstaendlicher Abbruch statt Absturz…`): - `Program.Main` prüft die Verbindung, **bevor** der Host gebaut wird, und nennt Schlüssel, Datei, Pfad und ein Beispiel — dazu den Hinweis, dass das Schema per `dotnet ef database update` entsteht, weil die Anwendung nicht selbst migriert. - Rückgabewert **78** (`EX_CONFIG` aus den BSD-sysexits) statt eines Absturzes. - `deploy/polytrader.service` bekam **`RestartPreventExitStatus=78`** — ein Konfigurationsfehler repariert sich durch Neustarts nicht, er wird dadurch nur unsichtbar. - `AddCorePersistence` wirft als zweite Verteidigungslinie eine `InvalidOperationException` mit derselben Aussage. **Gegengeprüft auf der VM:** Verständliche Meldung, Exitcode 78, kein Stacktrace. ### B-2 · Zwei verschiedene Datumsformate in Logdateinamen · offen, klein Im selben Lauf entstanden nebeneinander: ``` 2026-08-26.jsonl ← ISO, yyyy-MM-dd 26-08-2026-Info.log ← dd-MM-yyyy 26-08-2026-Warning.log ``` Zwei Logger-Pfade mit unterschiedlicher Namenskonvention. Praktische Folgen: Eine Logrotate-Regel braucht zwei Muster, und beim Sortieren im Dateimanager landen die `.log`-Dateien in willkürlicher Reihenfolge, weil der Tag vorn steht. Kein Fehler, aber ein Stolperstein im Betrieb — sinnvollerweise mit **T2** (TerminalLogger-Umbau) zusammen zu erledigen. ### B-3 · `--smoke-ui` verlangt jetzt eine Datenbank · offen, entscheidungsbedürftig Die neue Prüfung aus B-1 läuft vor dem Host-Aufbau und trifft damit **auch** die Konstruktionsprüfung `--smoke-ui`. Die ist als CI-Werkzeug gedacht, und ein Build-Server hat typischerweise keine Datenbank. **Wichtig: Das ist keine Verschlechterung.** Vorher scheiterte `--smoke-ui` ohne Datenbank genauso — nur mit dem Stacktrace aus B-1 statt mit einer Meldung. Der Befund war vorher bloß unsichtbar. Sauber lösen ließe sich das, indem `--smoke-ui` die Persistenzschicht überspringt oder gegen EF-InMemory baut (wie die Tests). Das ist ein eigener Schnitt und hängt daran, ob die CI diesen Modus überhaupt nutzen soll — deshalb hier nur vermerkt, nicht gebaut. --- ## 3. Nicht geprüft — und warum | Prüfpunkt | Fehlt | |---|---| | Betrieb **mit** Datenbank, Migrationen | Auf der VM läuft **keine** MySQL; der Datenbankhost ist nicht bekannt | | systemd-Dienst, `WorkingDirectory`-Falle (D-11) | Braucht `sudo`; Passwörter gebe ich nicht ein | | SIGTERM-Shutdown, `Restart=on-failure` | Setzt den laufenden Dienst voraus | | **Zeitzonen-Nachweis (T2)** | Die VM steht auf `Europe/Berlin`; der Effekt zeigt sich erst unter **UTC**. Umstellen braucht `sudo` | | Logrotate | Braucht `sudo` | | Oberfläche unter Linux | Braucht eine Datenbank (siehe B-3) — die VM hat aber einen Desktop, der Test ist also möglich | **Zum Weitermachen wird gebraucht:** 1. Eine **Testdatenbank** — entweder Adresse und Zugang zu einer bestehenden MySQL, oder MariaDB lokal auf der VM installieren (`sudo`). **Nicht die Produktivdatenbank:** Der `MarketSyncService` schreibt als Hintergrunddienst hinein. 2. Für die `sudo`-Schritte: Entweder Richard führt sie aus, oder er richtet für die Dauer des Tests passwortloses `sudo` für sein Konto ein. --- ## 4. Nebenbefunde - **Rider-Konfiguration im Repo:** Mit einem `git add -A` waren vier `.idea/`-Dateien in einen Commit gerutscht. Sie blockierten den `git pull` auf der VM, wo Rider dieselben Dateien lokal anlegt. Entfernt, `.idea/` steht jetzt in `.gitignore`. - **Verbindungs-Multiplexing (`ControlMaster`) funktioniert nicht** — Windows-OpenSSH unterstützt es nicht. Aus der SSH-Konfiguration entfernt; stattdessen werden mehrere Prüfschritte pro Aufruf gebündelt. - **Speicher ist reichlich vorhanden** (31 GB, davon 25 GB frei). Die Vermutung, der Claude-Desktop-Absturz auf der VM könnte an Speichermangel liegen, ist damit **widerlegt**.