Zum Inhalt springen

Architektur

Panel .NET 10, Minimal APIs von ASP.NET Core, EF Core mit PostgreSQL, ASP.NET Core Identity. Liefert API, Live-Updates (SignalR), den Endpoint für Agents und die Web-App aus einem Ursprung aus.
Web-App React, Vite, TypeScript, shadcn/ui, TanStack Router und Query; installierbar (PWA) mit eigenem Service Worker.
Agent ein .NET-Worker in einem Container mit dem Docker-Socket, auf jedem Node.
Datenbank PostgreSQL.

Jede Bibliothek steht unter MIT, Apache-2.0 oder der PostgreSQL-Lizenz.

  • Der Agent baut die Verbindung zum Panel auf und hält einen WebSocket offen; die Nachrichten sind Protobuf, typisiert und versioniert. WebSockets kommen durch jeden Reverse Proxy und Load Balancer, anders als gRPC-Streams, die durchgehend HTTP/2 brauchen.
  • Die Verbindung geht nur nach aussen und verwendet das HTTPS-Zertifikat des Panels: Nodes brauchen weder einen offenen Verwaltungsport noch ein Zertifikat.
  • Bei der Registrierung wird ein einmaliges Token gegen ein eigenes Secret des Nodes getauscht; das Panel behält nur einen Hash.
  • Ein Agent, der sich neu verbindet, meldet seine Server; Jobs, die er verloren hat, werden als gescheitert markiert.
  • Ein Container pro Gameserver, bei jedem Start aus den aktuellen Einstellungen des Servers erstellt.
  • Hardening: alle Capabilities entfernt, no-new-privileges, Limits für Arbeitsspeicher (ohne Swap), CPU und Prozesse, ein Docker-Netzwerk pro Tenant; optional schreibgeschützt, User Namespaces und gVisor (Node-Hardening).
  • Installationen, Updates und Steam-Anmeldungen sind Jobs in Containern, die danach weggeworfen werden.
  • Secrets werden mit Data Protection von ASP.NET Core verschlüsselt, ein Zweck pro Tenant. Der Key Ring liegt in PostgreSQL und ist selbst mit der Master-Key-Datei verschlüsselt (AES-256-GCM); ein Datenbank-Dump allein genügt deshalb nicht.
  • Steam-Passwörter erreichen nur Job-Container, in die Abfrage von SteamCMD getippt: nie in der Umgebung, auf der Kommandozeile oder in einer Datei. Umgebungsvariablen und Kommandozeilen sind in docker inspect und ps sichtbar, und reines Docker hat kein tmpfs, das sich vor dem Start eines Containers füllen liesse.
  • Steam-Anmeldungen liegen in einem Docker-Volume pro Konto und Node, das nur in Jobs eingebunden wird.
  • Der Agent bietet SFTP selbst an, wie Wings von Pterodactyl: Dateiübertragungen gehen direkt zum Node, nie durch das Panel.
  • Bei der Anmeldung fragt der Agent das Panel. Es prüft Passwort oder SSH-Schlüssel und den Zugriff des Benutzers und antwortet mit den wirksamen Datei-Berechtigungen und Pfaden. Der Agent setzt sie bei jeder Anfrage mit den Regeln des Panels durch.
  • Angeboten wird nur SFTP: keine Shell, keine Befehle, keine Portweiterleitung; symbolische Links lassen sich weder anlegen noch lesen.
  • Provider sind Module, die IExposureProvider implementieren; jeder beschreibt seine Einstellungen, aus denen ein Formular wird, mit verschlüsselt gespeicherten geheimen Feldern.
  • Das Panel berechnet die Regeln aus den verwendeten Allocations des Nodes, vergleicht sie mit denen beim Provider und wendet den Unterschied an: nach Änderungen und alle 15 Minuten, um Abweichungen zu reparieren.
  • Provider fassen nur Regeln mit dem Präfix server-panel: an.

Templates enthalten configFiles, die der Agent vor jedem Start anwendet, wie Wings bei Eggs: Ohne das würden importierte Spiele ihre zugewiesenen Ports ignorieren.