Workaround für Wartungsseite – ist das möglich?

Ja, ich würde es in Etappen tun:

  1. einen etwas leistungsstärkeren Server besorgen
  2. die Installation mit zwei Containern zum Laufen bringen

Wenn du an diesem Punkt zufrieden bist, kannst du hier aufhören, oder:

  1. die Wartungsseite nach @Lillys ausgezeichneter Anleitung oben implementieren. :+1:

Haha, ich bin froh, dass du gefragt hast, denn ich habe mir die Zeit gespart, diesen Teil zu erklären (ich hätte es tun sollen – es gibt viel zu erklären und Cloudflare ist komplex!).

Wenn die Worker-Route-Seite eingerichtet ist, wird jeder einzelne Bildladevorgang und jede Seitenaufruf im Forum durch diesen Worker geleitet.

Das kostenlose CDN-Paket von Cloudflare umfasst ein Limit von 100.000 Anfragen pro Tag für eine Worker-Route.

Wenn du also ein relativ stark frequentiertes Forum hast, ist es sinnvoll, die Route nicht dauerhaft aktiv zu lassen, um zu verhindern, dass du das Limit deiner kostenlosen Stufe innerhalb eines Tages erreichst. Dies betrifft nur die Worker-Route, nicht die Wartungsseite – du kannst die Wartungsseite jederzeit aktiv lassen; sie wird nur angesprochen, wenn die Worker-Route darauf verweist. Es geht also nur um Schritt 2, in dem du die Route zugewiesen hast (was einfach einzurichten und zu entfernen ist). Sofern du keinen bezahlten Cloudflare-Plan nutzt, ist es daher gute Praxis, die Route nur während deiner eigenen Wartungsarbeiten aktiv zu haben.

  1. Gehe zur Cloudflare Worker-Route-Seite für deine Domain und klicke auf die Schaltfläche rechts neben der Route.

  1. Klicke unten im Bearbeitungsbildschirm auf die Schaltfläche remove, um die Worker-Seite von der Route zu trennen.

  1. Keine Sorge, der Worker-Code selbst wird nicht gelöscht, nur die Routing-Regel. Beim nächsten Neuaufbau oder Update kannst du sie einfach wie in Schritt 2 oben erneut hinzufügen.

Wenn du einen bezahlten Cloudflare-Plan hast, brauchst du dir keine Sorgen zu machen. Allerdings kannst du in diesem Fall die Cloudflare-Fehlerseiten anstelle einer Worker-Seite verwenden… (habe ich schon erwähnt, dass Cloudflare ziemlich komplex ist? LOL)

:warning: erweiterte Admin-Konfiguration unten

Wenn man seine Updates auf dem kostenlosen Plan vollständig automatisieren möchte, sollte man ein Cloudflare-API-Token verwenden, seine Zone-ID und einen curl-Befehl nutzen, um die route id des Workers zu erhalten. Dann bearbeite das Skript /root/update-web.sh mit ein paar weiteren nützlichen Befehlen, um die Worker-Route automatisch ein- und auszuschalten:

#!/bin/bash
cd /var/discourse

CF_TOKEN="your_actual_token_here" #<---Cloudflare api token
ZONE_ID="xxxx" #<---from your Cloudflare profile page
ROUTE_ID="xxxx"
WORKER_NAME="my-site-maintenance-page"

echo "➡️ Pulling latest Discourse docker scripts..."
git pull

echo "➡️ Bootstrapping new web container in the background..."
./launcher bootstrap web_only

if [ $? -eq 0 ]; then
    echo "✅ Bootstrap successful!"
    
    # Turn ON the Cloudflare Maintenance Worker
    echo "🚧 Enabling Maintenance Page..."
    curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes/$ROUTE_ID" \
         -H "Authorization: Bearer $CF_TOKEN" \
         -H "Content-Type: application/json" \
         --data '{"pattern":"*your-site.com/*","script":"'$WORKER_NAME'"}' > /dev/null

    # Swap the containers (The 30-second downtime window)
    echo "🔄 Swapping containers..."
    ./launcher destroy web_only && ./launcher start web_only
    
    # Turn OFF the Cloudflare Maintenance Worker
    echo "🌍 Disabling Maintenance Page..."
    curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/workers/routes/$ROUTE_ID" \
         -H "Authorization: Bearer $CF_TOKEN" \
         -H "Content-Type: application/json" \
         --data '{"pattern":"*your-site.com/*","script":null}' > /dev/null

    echo "🚀 Done! Site updated with zero visible downtime."
else
    echo "❌ Bootstrap failed! Aborting swap to keep current site online."
fi 

Ich verwende die vorherige Version des Skripts, weil ich nicht alles automatisieren möchte und gerne bei Updates/Neuaufbauten anwesend bin. Ich füge die Worker-Route einfach kurz vor dem Update hinzu und entferne sie danach. Das dauert nur ein paar Sekunden.

Meine allgemeinen Schritte sind:

  1. Die Worker-Route auf Cloudflare hinzufügen
  2. Per SSH in Hetzner einloggen
  3. Systemupdates durchführen (z. B. sudo apt update && sudo apt upgrade -y) und den Server bei Bedarf neu starten
  4. Erneut per SSH einloggen, falls ein Neustart erforderlich war
  5. ./update-web.sh ausführen
  6. Die Worker-Route auf Cloudflare entfernen

Ich kenne mich mit Programmierung und der Entwicklerwelt überhaupt nicht aus, abgesehen davon, dass ich vor langer Zeit mal eine Hello World-Anwendung mit Visual Basic erstellt habe. Aber ich kann einige Dinge tun, weil ich besser weiß, wie ich meine WordPress- und Mastodon/Pixelfed-Server administriere, und irgendwie auch meinen Discourse-Server. Außerdem gibt es da noch diese Sache namens KI (die für einen Anfänger nicht so einfach ist, wie sie beworben wird).

Ich weiß nicht, ob das mit Discourse aufgrund von Docker überhaupt in irgendeiner Form möglich ist, aber in der gewöhnlichen Nginx-Varnish-WordPress-Welt habe ich ein System aufgebaut, bei dem ein Plesk-Server Informationen über 50x-Fehler erhält und eine Fehlerseite anzeigt. Tatsächlich habe ich drei Konfigurationen: Wenn Varnish ausfällt, zeigt der Frontend-Nginx generierte Snapshot-Inhalte an; wenn das WordPress-bezogene Backend ausfällt, beginnt Varnish, Snapshots für nicht gecachten Inhalt zu verwenden; und die dritte Option ist eine Fehlerseite, falls der Frontend-Nginx nicht antwortet.

Varnish-spezifische Dinge sind für Discourse nicht möglich, aber ich sehe keinen Grund, warum man so ein Netz nicht auch in die Docker-Welt einbauen könnte, sodass jeder 50x-Fehler eine Fehlerseite anzeigen würde.

Das könnte zwar ein sehr fehleranfälliges System sein. Und ich habe keine Ahnung, was passieren würde, wenn mehr als ein paar Handvoll Benutzer vorhanden sind.

Natürlich gibt es auch die offensichtliche Antwort: Man nutzt z. B. Nginx vor Discourse. Das habe ich früher gemacht, bevor ich auf das 2-Container-Modell umgestiegen bin.

Ich habe mir endlich die Zeit genommen, Discourse erneut zu installieren. Nachdem ich darüber nachgedacht habe, wo ich gerade stehe und wie viel Wartung zwei Container zu verlangen scheinen, werde ich vorerst bei einem bleiben. Falls ich in Zukunft zwei Container brauche, werde ich alles, was hier gesagt wurde, überdenken. Abgesehen von der Installation von Plugins, was ich scheinbar nicht so oft tun muss wie das Verwalten von Komponenten, scheint es mir derzeit ziemlich vernünftig zu sein, dass die Community für 20 Minuten in einer Tageszeit mit weniger aktiven Nutzern offline ist, begleitet von einem Banner, das die Nutzer darüber informiert, an welchem Tag und zu welcher Uhrzeit die Community offline sein wird.

Mal sehen, wie es läuft.

Es erfordert genauso viel wie ein einzelner Container :flushed_face:

Und weniger Herzschmerz :slight_smile:

Könntest du erklären, wie das funktioniert?

Bin mir nicht sicher, ob du mir oder @Jagster geantwortet hast? Was meinst du?

Da der Prozess des Bootstrappings des neuen Containers, während deine Website online bleibt, deutlich weniger Stress bereitet – wenn der Build fehlschlägt, musst du nicht in Panik geraten und hast so viel Zeit, wie du zum Beheben des Problems brauchst, ohne offline gehen zu müssen.

Okay, also ihr ermutigt dazu, beides zu nutzen, daher das „weniger Herzschmerz“.
Also, als jemand, der sich in diesem Bereich nicht so gut auskennt: Zwei Container bedeuten doch nicht, dass es zwei Instanzen von Discourse gibt, oder?

Ich lese gerade das Thema

und

um zu sehen, wie viel Arbeit das erfordert und wie viel Aufmerksamkeit ich darauf richten muss, damit ich am Ende nicht etwas habe, was ich nicht mehr im Griff habe und den Prozess dadurch noch problematischer mache als all die anderen Dinge, die mit nur einem Container schiefgehen können.

Ich möchte einfach nur Lob für die Beschreibung der Einrichtung mit zwei Containern aussprechen. Ich habe bisher nur einen verwendet, und die Aktualisierung dauert dabei in der Regel 3–5 Minuten (auf einem Dedizierten Server mit 64 GB RAM).

Könntest du mir in klaren und einfachen Beispielen erklären, wann man bei einer Dual-Installation beide Container aktualisieren sollte? Ich meine, bei welchen Discourse-Updates müssen beide neu gestartet werden und bei welchen nur der neu erstellte web_container?

Zunächst befolgst du sehr einfache Anweisungen, um die 2-Container-Konfiguration zu starten. Danach benötigst du in der Regel nur noch

./launcher bootstrap web_only && ./launcher destroy web_only && ./launcher start web_only ) 2>&1 | tee ~/$(date +%Y-%m-%d_%H-%M-%S)-upgrade.log'

Der tee-Teil dient nur dem Protokollieren, da das Durchsuchen des Logs (für mich) einfacher ist als der tmux-Feed, den ich verwende.

Im Grunde ist es aber genau dasselbe wie die Verwendung von app.yml und ein Neuaufbau, nur dass es die Benutzer deutlich weniger stört. Sicher, es gibt einen Data-Container, aber der braucht nur sehr selten Aufmerksamkeit und Pflege — und wenn du fortgeschrittenere Tricks mit Containern anwendest, weißt du vermutlich auch, was du wann mit Containern zu tun hast.

Wenn ein Upgrade mit der 2-Container-Konfiguration fehlschlägt, ist das Forum weiterhin online und erreichbar, während ein einzelner Container abstürzen würde.

Also ist nur der Einstieg etwas aufwendiger, aber die Anweisungen sind ziemlich klar. Ich würde sagen, die Verwendung von mail-reveiver ist die größere Herausforderung, insbesondere wenn Amazon SES zum Einsatz kommt.

Zum Beispiel ist dies die Art von Kommentar, die ich nicht einfach ignorieren kann, denn es scheint, dass das Aktualisieren/Aufrüsten nicht mehr so einfach ist wie das Klicken eines Buttons, sondern mehr Aufmerksamkeit und Konzentration erfordert. Das mag für erfahrene Benutzer leicht und selbstverständlich erscheinen, ist es für andere aber vielleicht nicht:

Würdest du sagen, dass die Anweisungen in diesem Thema 2026 noch aktuell sind, da sie aus dem Jahr 2015 stammen?

Ich habe nichts dagegen, es auszuprobieren, da ich Discourse heute gerade wieder installiert habe. Falls etwas schiefgeht, kann ich ja einfach auf einen einzelnen Container zurückgreifen. Ich möchte nur sicherstellen, dass ich nicht mitten drin etwas tue, das 2026 nicht mehr gültig ist…

Für mich sind die gesparten Minuten mehr als 20 Minuten. Einmal im Monat stimmt nur, wenn man auch nur einmal im Monat aktualisiert, ich aber mache das mindestens zweimal pro Woche. Und wenn ein Plugin fehlschlägt und man mehrere Versuche braucht (weil wir ja schließlich mit Live-Instanzen arbeiten :wink:), ist diese lange Ausfallzeit schlichtweg schmerzhaft.

Es gibt keine Details in den Ankündigungen jeder neuen Version, die man befolgen müsste. Mcdanlj mag das haben, aber er ist kein gewöhnlicher Sysadmin, sondern arbeitet auf einer viel höheren Ebene.

Ich bin verwirrt…

Du sagst zwar:

aber deine Antwort darüber lässt es so klingen, als wäre mehr Arbeit nötig, wenn du schreibst:

Das allein klingt so, als wäre die Wartung von zwei Containern tatsächlich aufwendiger als bei einem. Klar, die Ausfallzeiten und so – das verstehe ich – aber die Wartung der Container selbst scheint mir komplexer und fehleranfälliger zu sein als ein einfaches Upgrade mit nur einem Container. Oder übersehe ich etwas?

Das ist korrekt:

Container 1 = Website & nginx
Container 2 = Datenbank und Redis

(ich glaube, das stimmt so)

Die Inhalte von Container 1 ändern sich sehr oft

Die Inhalte von Container 2 nur sehr selten.

Und man kann Container 1 aktualisieren, ohne Container 2 aktualisieren zu müssen.

Und noch besser: Man kann einen Ersatz für Container 1 vorbereiten und diesen dann in wenigen Sekunden eins zu eins austauschen (die Vorbereitung wird „Bootstrapping“ genannt)

Du hast übersehen, dass beim Ein-Container-Setup mit ./launcher rebuild app sowohl Web als auch Daten gestoppt werden. Beide werden aktualisiert, aber die Datenseite benötigt dies nur sehr selten. Nach dem Job wird alles wieder gestartet, sofern keine Probleme auftreten.

Bei der Zwei-Container-Variante baust du nur „web“ neu auf, den Daten-Container lässt du in Ruhe. Wenn alles reibungslos verläuft, wird der alte Container zerstört und ein neuer gestartet. Sollte etwas schiefgehen, ist dein alter, funktionierender „web“-Container weiterhin in Betrieb.

Der eigentliche Unterschied besteht also nur darin, wie mit der Software und einigen anderen Datenbankaspekten umgegangen wird.

Ja, ein 1-Container-Setup ist natürlich auch eine Option. Aber der eigentliche Punkt ist, dass beim Erstellen eines 2-Container-Setups der einzige echte Unterschied im Namen der Schwierigkeit liegt, und zwar im bei der Aktualisierung verwendeten Befehl — und dafür gibt es alias :wink:

Das wurde zu den Zeiten geschrieben, in denen die Ankündigungen noch von Hand verfasst wurden und darauf hinwiesen, dass es nun Zeit ist, die Datenbank zu aktualisieren. Die neue, automatisierte Seite ist zwar aufwendiger, aber es gibt keine menschliche Anmerkung mehr dazu, was tatsächlich am wichtigsten ist, wie es früher der Fall war.

Heute muss man wohl selbst auf einen Beitrag achten, in dem steht, dass die Datenbank aktualisiert wird? Ich scheine diese Hinweise seit Monaten übersehen zu haben.

Allerdings passiert das nur alle paar Jahre, und die Datenbank wird neu aufgebaut, wenn man sie explizit neu aufbaut. Außerdem scheint CDCK die Kompatibilität mit älteren Versionen von pgsql eine Weile lang aufrechterhalten zu haben. Also ist mir das bisher nie wirklich zum Verhängnis geworden. Bisher.

Ich mag das Setup mit zwei Containern (oder mehr!) für mich selbst sehr, aber ich gebe trotzdem einen Hinweis, weil es für nicht alle die einfachste Lösung ist. Mir ist es schwer, zu beurteilen, für wen die Bereitstellung mit zwei Containern wie „selbstverständlich, das ist einfach“ wirkt und für wen es wie „äh, ich will nur auf einen Button drücken“ wirkt.