Zum Inhalt springen

Maintenance Edge-Proxy

Der Maintenance Edge-Proxy („Edge”) ist ein von ReadyStackGo verwalteter Reverse-Proxy-Container, der pro Produkt vor dessen öffentlichem Eingang läuft. Er überlebt Redeploys des Produkts und liefert — gesteuert durch RSGOs autoritativen Deploy-Zustand und das Maintenance-Flag — entweder transparent zum Upstream durch oder eine kontrollierte Wartungsseite plus einen maschinenlesbaren Status.

Das Feature ist opt-in pro Produkt (per Manifest) und per Default inert: Ohne edge:-Block ändert sich am bestehenden Verhalten nichts.

Beim Redeploy oder Wartungsmodus entfernt RSGO die Produkt-Container — inklusive des einzigen öffentlichen Eingangs (z. B. der BFF/Gateway). Clients und Browser bekommen dann „Connection refused” statt einer verständlichen Seite. Launcher/Clients haben keine verlässliche Möglichkeit zu erkennen, warum der Dienst gerade weg ist.

Der Edge schließt diese Lücke und trennt sauber zwei Ebenen:

EbeneVerantwortungWer löst sie
Kontroll-Ebene„Soll der Dienst in Wartung?” — das UmschaltenMaintenance Mode (Flag/Observer) — bereits vorhanden
Erlebnis-Ebene„Was sieht der Client, während der Dienst unten ist?”Maintenance Edge-Proxy (diese Seite)

Vorteile:

  • Kein Connection-Refused mehr während Redeploy oder Wartung — der Edge bleibt durchgehend erreichbar.
  • Kontrollierte Wartungsseite statt Browser-Fehlerseite, voll anpassbar.
  • Maschinenlesbarer Status (GET /__status), an dem ein Launcher/Client robust erkennt, ob „läuft”, „Wartung” oder „wird deployt”.
  • Generisch: nichts produktspezifisches — jedes Produkt aktiviert es nur per Manifest.

RSGO betreibt den Edge als separaten Container (Caddy), den es im Lifecycle verwaltet — er läuft nicht im RSGO-Prozess (saubere Control-/Data-Plane-Trennung; ein RSGO-Self-Update erzeugt keinen Traffic-Abriss).

Routing — aus autoritativem Zustand, nicht geraten

Abschnitt betitelt „Routing — aus autoritativem Zustand, nicht geraten“

Der Edge rät nicht per Health-Check. Eingaben sind ausschließlich RSGOs Deploy-Zustand (ProductDeployment.Status) und das Maintenance-Flag (OperationMode):

Deploy-ZustandMaintenance-FlagEdge-Verhalten/__status state
RunningausTransparenter Proxy zum Upstreamrunning
RunninganWartungsseite, geplante Wartungmaintenance
Deploying / Redeploying / UpgradingbeliebigWartungsseite, vorübergehend nicht erreichbardeploying
Failed / Stopped / sonstausWartungsseite, vorübergehend nicht erreichbarmaintenance

Das Flag steuert nur die Wortwahl (geplante Wartung vs. vorübergehend weg); ob proxyt wird, entscheidet allein der Deploy-Zustand.

Beim Teardown eines Stacks entfernt RSGO alle Container mit dem passenden Stack-Label. Der Edge (und ein optionaler produkt-beigesteuerter Wartungs-Container) tragen Survival-Labels und werden davon ausgenommen:

LabelWertBedeutung
rsgo.scopeedgeContainer gehört zum Edge-Scope → vom Stack-Teardown ausgeschlossen
rsgo.redeployignoreGenerischer Opt-out → vom Stack-Teardown ausgeschlossen
rsgo.rolemaintenance-pageProdukt-beigesteuerter Wartungs-Container (siehe unten)

RSGO ist außerdem der einzige Schreiber der Edge-Konfiguration: Es berechnet den Soll-Zustand und pusht ihn atomar und verbindungs-erhaltend über die Caddy-Admin-API (POST /load) — ohne den Edge neu zu starten.


Füge den optionalen edge:-Block auf Produkt-Ebene hinzu (Geschwister von metadata: / services:). Der Upstream-Service muss am gemeinsamen externen Netz hängen, damit der Edge ihn per DNS-Alias erreicht:

metadata:
name: ams.project
productVersion: "1.0.0"
networks:
ams-project-edge-net:
external: true # gemeinsames Netz Edge <-> Upstream
services:
web-bff: # öffentlicher Eingang (BFF/Gateway)
image: ams/bff:1.0.0
networks: [ams-project-edge-net]
edge:
enabled: true
publicHostname: project.kunde.tld
publicPort: 443
upstream:
service: web-bff # = Service-/Alias-Name im Netz
port: 8080
network: ams-project-edge-net
tls:
mode: selfsigned
maintenancePage:
mode: default
branding:
productName: "ams.project"
supportContact: support@kunde.tld
locales: [de, en]

Deploye das Produkt wie gewohnt. RSGO erkennt den edge:-Block, provisioniert den Edge-Container und schaltet ihn nach Running auf Proxy. Im laufenden Betrieb reicht der Edge transparent durch.

Während eines Redeploys bleibt der Edge stehen und liefert die Wartungsseite (state: deploying) — kein Connection-Refused:

Edge-Proxy-Seite während eines Rollouts

Bei aktivem Maintenance-Flag zeigt er die Variante „geplante Wartung” inklusive reason:

Default-Wartungsseite des Edge-Proxy

Die Seite rendert den Live-Status aus /__status direkt als Status-Panel, aktualisiert sich automatisch im Sekundentakt und leitet automatisch in die App weiter, sobald das Produkt running meldet — niemand muss manuell neu laden. Die Akzentfarbe folgt dem Zustand (Amber bei Wartung, Blau beim Rollout).

Der maschinenlesbare Status unter /__status unterscheidet die Zustände eindeutig:

/__status im Wartungsmodus

/__status im Normalbetrieb


Es gibt drei Stufen. Der Edge löst sie in der Reihenfolge container → bundle → default auf und fällt jeweils zur nächsten Stufe zurück.

maintenancePage.mode: default liefert die mitgelieferte Seite — ein Live-Status-Panel in den RSGO-Markenfarben, das den /__status-Vertrag (Zustand, Grund, Version) spiegelt, sich automatisch aktualisiert und Besucher zurück in die App leitet, sobald sie running ist. Über branding passt du sie ohne eigenes HTML an:

maintenancePage:
mode: default
branding:
productName: "ams.project"
logoUrl: https://kunde.tld/logo.svg
supportContact: support@kunde.tld
locales: [de, en]
FeldBeschreibung
productNameAnzeigename auf der Seite / im Browser-Tab
logoUrlOptionales Logo (absolute URL)
supportContactOptionale Support-Adresse, unten eingeblendet
localesSprachen für den Umschalter auf der Seite (z. B. [de, en])

maintenancePage.mode: bundle liefert eine eigene HTML-Seite inline aus. RSGO liest sie zur Deploy-Zeit aus dem Manifest-Repository (bundlePath/index.html):

maintenancePage:
mode: bundle
bundlePath: ./maintenance/ # liest ./maintenance/index.html

b) Durch eigenen Container ersetzen (volle Kontrolle)

Abschnitt betitelt „b) Durch eigenen Container ersetzen (volle Kontrolle)“

Für volle Anpassbarkeit (eigene Assets, dynamische Inhalte, eigener Webserver) liefert das Produkt einen eigenen Wartungs-Container bei, an den der Edge im Wartungsfall durchproxt.

So geht’s:

  1. maintenancePage.mode: container setzen und Service + Port angeben.
  2. Den Wartungs-Service mit den Labels rsgo.role: maintenance-page und rsgo.redeploy: ignore versehen (damit er — wie der Edge — Redeploys überlebt).
  3. Den Service ans gemeinsame Edge-Netz hängen, damit der Edge ihn per Alias erreicht.
networks:
ams-project-edge-net:
external: true
services:
maintenance-web:
image: ams/maintenance-page:1.0
networks: [ams-project-edge-net]
labels:
rsgo.role: maintenance-page
rsgo.redeploy: ignore # überlebt den Redeploy
edge:
enabled: true
publicHostname: project.kunde.tld
upstream: { service: web-bff, port: 8080 }
network: ams-project-edge-net
maintenancePage:
mode: container
container:
service: maintenance-web # = Alias im Netz
port: 80

Im Wartungsfall reicht der Edge die Catch-All-Anfragen an maintenance-web:80 weiter. Der GET /__status-Vertrag und der /hc-Durchlass bleiben dabei unverändert — nur die sichtbare Seite stammt aus deinem Container.


Im Repository liegt unter examples/edge-maintenance/ eine einsatzbereite Vorlage für beide Anpassungswege:

VarianteInhaltOrdner
BundleEine eigenständige, gebrandete index.html + Manifest-Snippetbundle/
ContainerDockerfile (nginx:alpine), Assets (index.html, styles.css, logo.svg, status.js) + Manifest-Snippetcontainer/

Der Beispiel-Container (examples/edge-maintenance/container/) ist ein minimaler nginx:alpine, der das Verzeichnis html/ ausliefert. Du baust und pushst ihn so:

Terminal-Fenster
cd examples/edge-maintenance/container
docker build -t deine-registry/ams-maintenance-page:1.0 .
docker push deine-registry/ams-maintenance-page:1.0

Anschließend trägst du das Image im Manifest unter maintenance-web ein (siehe Snippet oben). Ersetze die Assets in html/ durch deine eigenen — Webserver und Port sind frei wählbar.

Live-Status: Beide Vorlagen pollen /__status (gleiche Origin hinter dem Edge) über ein kleines Script (status.js bzw. inline). Damit wechselt die Seite automatisch die Wortwahl zwischen „geplanter Wartung” und „Aktualisierung läuft” und lädt neu, sobald das Produkt wieder running ist.


FeldPflichtDefaultBeschreibung
enabledjafalseHauptschalter. false/fehlend → Feature inert.
publicHostnamejaHostname, den der Edge bedient (Cert-CN; SNI-Schlüssel).
publicPortnein443Öffentlicher Port, auf dem der Edge lauscht.
imageneingepinntes caddyEdge-Image; in Produktion per Digest pinnen.
upstream.servicejaInterner DNS-Alias des öffentlichen Eingangs (z. B. der BFF).
upstream.portnein8080Upstream-Port.
networkjaGemeinsames externes Netz, das Edge und Upstream verbindet (external: true).
mssneinpmtuClient-seitige TCP-Segmentgröße für VPN-Robustheit: pmtu (adaptiv, Standard), eine feste Zahl (z. B. 1360) oder off. Siehe VPN-Robustheit unten.
tls.modeneinkeineTLS-Terminierung: selfsigned, custom (certRef), reuse (RSGO-Cert), letsencrypt.
tls.certRefbei customReferenz auf das hochgeladene Zertifikat.
tls.letsencrypt.email / .dnsChallengebei letsencryptACME-Einstellungen.
maintenancePage.modeneindefaultdefault, bundle oder container.
maintenancePage.bundlePathbei bundleAsset-Verzeichnis im Manifest-Repo (index.html).
maintenancePage.container.service / .portbei container80Service-Alias + Port des Wartungs-Containers.
maintenancePage.branding.*neinproductName, logoUrl, supportContact, locales.

Ist tls.mode gesetzt, terminiert der Edge HTTPS auf publicPort mit einem Zertifikat, das RSGO verwaltet — der Edge führt nie selbst ACME aus. Erneuerte Zertifikate werden ohne Edge-Neustart nachgeladen.

tls.modeZertifikatsquelle
selfsignedRSGO erzeugt ein per-Hostname-Selfsigned-Zertifikat und erneuert es automatisch.
customVom Operator bereitgestelltes Zertifikat (certRef).
reuseRSGOs eigenes Endpoint-Zertifikat (Single-Host-Fall).
letsencryptNutzt RSGOs ACME-verwaltetes Zertifikat.

Vollständige Schema-Details: RSGo Manifest Format.


Über die Edge gehostete Produkte können im LAN einwandfrei laufen, über VPN aber teilweise nicht: Der Login (kleine Requests) funktioniert, das Laden einer größeren Seite oder einer umfangreichen Start-Konfiguration endet jedoch mit HTTP 502 oder einem Timeout.

Die Ursache ist nicht der Server, sondern die Strecke. Ein VPN-Tunnel verpackt jedes Paket in eine zusätzliche Hülle und senkt so die nutzbare Paketgröße (MTU). Normalerweise meldet das Netz „Paket zu groß” an den Absender zurück (Path MTU Discovery) — viele Firmen-VPNs filtern diese ICMP-Meldung jedoch weg. Große Antwortpakete (mit gesetztem Don’t-Fragment-Bit) werden dann lautlos verworfen: Kleine Übertragungen passen, große stocken. Das ist ein klassisches PMTU-Blackhole.

Da die Edge die Client-TCP-Verbindung terminiert und die öffentliche Vordertür ist, gehört Netzwerk-/MTU-Robustheit hierher — einmal an der Edge gelöst, gilt sie für jedes über die Edge gehostete RSGO-Produkt bei jedem Kunden, ohne Eingriff am Kunden-VPN.

edge:
enabled: true
# ...
mss: pmtu # Standard — muss normalerweise nicht gesetzt werden
WertVerhalten
pmtuStandard, empfohlen. Adaptives Kernel-Path-MTU-Probing (PLPMTUD, RFC 4821): Die Edge erkennt ein Blackhole bei großen Antworten und verkleinert ihre TCP-Segmentgröße selbstständig — ohne die (gefilterte) ICMP-Meldung und ohne einen geratenen festen Wert. Im LAN unschädlich (volle Segmentgröße, wenn die Strecke es zulässt).
eine Zahl, z. B. 1360Erzwingt eine feste maximale Segmentgröße. Nur nutzen, wenn ein exakter Wert festgelegt werden muss; gültiger Bereich 536–1460. Umgesetzt durch Absenken der Edge-Netz-MTU auf mss + 40.
offFunktion vollständig deaktivieren — die Edge behält den OS-Standard (Verhalten wie vor dieser Option). Rückwärtskompatibilitäts-Ausweg.

Fehlt mss oder ist der Wert ungültig bzw. außerhalb des Bereichs, fällt die Edge auf pmtu zurück — eine unbrauchbare Vordertür ist schlimmer als ein ignorierter Tuning-Wert.

Der Standard (pmtu) wird über namespace-lokale Kernel-Sysctls (net.ipv4.tcp_mtu_probing, net.ipv4.tcp_base_mss) nur am Edge-Container gesetzt. Der feste Modus senkt die Edge-Netz-MTU. Kein Modus benötigt die Capability NET_ADMIN oder eine Änderung am Container-Image — die Edge läuft mit denselben Rechten wie zuvor.

Einschränkung im festen Modus: Ein fester MSS-Wert wird angewendet, wenn RSGO das Edge-Netz anlegt. Existiert das Netz bereits (z. B. weil es zuerst vom Produkt-Stack erstellt wurde), lässt sich seine MTU nicht ohne Neuanlage ändern; RSGO schreibt eine Warnung ins Log und die feste Grenze greift nicht. Bevorzuge in diesem Fall pmtu (funktioniert unabhängig davon, wer das Netz besitzt) oder lass RSGO das Netz anlegen.


Der Edge liefert unter /__status ein stabiles, versioniertes JSON — identisch in allen Branding-Modi, damit ein Client/Launcher es robust parsen kann:

{
"schema": 1,
"state": "running",
"reason": null,
"until": null,
"productVersion": "1.0.0"
}
FeldBedeutung
schemaVertragsversion. Konsumenten sollten darauf verzweigen.
staterunning (Proxy), maintenance (geplant, reason gesetzt) oder deploying (Redeploy/Upgrade läuft).
reasonGrund der geplanten Wartung (aus dem Flag), sonst null.
untilAngekündigtes Ende (ISO-8601), falls verfügbar, sonst null.
productVersionAktuelle Produktversion, falls bekannt.

Damit unterscheidet ein Client zuverlässig „geplante Wartung” (Flag) von „Redeploy/temporär weg” (Deploy-Zustand) — ohne zu raten.