Fügen Sie eine Offline-Seite hinzu, die angezeigt wird, wenn Discourse neu aufgebaut oder gestartet wird

Gibt es einen offensichtlichen Grund, warum ich keine .png-Datei mit mehr als 500 KB in meinem Forum hochladen kann, nachdem ich dieser Anleitung gefolgt bin?

Ich sehe einige Diskussionen über diese Zeile client_max_body_size 0;, aber das sollte nicht das Problem sein, oder?

EDIT: Ich habe es schnell herausgefunden, nachdem ich hier gepostet habe. Ich musste :white_check_mark: force https in den Einstellungen überprüfen. Ich werde diesen Beitrag hier lassen, falls zukünftige Leute ein Problem haben

3 „Gefällt mir“

Ich stelle fest, dass hier:

nginx empfiehlt, den Header Connection: close zu deaktivieren und proxy_http_version 1.1 zu setzen – also so etwas wie dies:

    proxy_http_version 1.1;
    # Standard \"Connection: close\" deaktivieren
    proxy_set_header \"Connection\" \"\";

Ich kann keine Dokumentation darüber finden, ob Connection: close Auswirkungen auf Unix-Domain-Sockets hat, aber da diese Dokumentation auch nützlich für die Ausführung eines externen Proxys auf einem separaten System ist und ich davon ausgehe, dass das Entfernen des Headers nicht schadet, könnte es sinnvoll sein, hier das Entfernen zu empfehlen?

1 „Gefällt mir“

Wenn Sie dies auf einem System mit SELinux (enforcing) bereitgestellt haben, können Sie den Unix-Domain-Socket nicht verwenden, damit der Host mit dem Container kommunizieren kann, da er jedes Mal, wenn Sie den Container neu starten, ohne Label neu erstellt wird, selbst wenn Sie den Unix-Domain-Socket neu beschriften. Stattdessen müssen Sie zwei Änderungen vornehmen.

Sie müssen Nginx den Zugriff auf die Fehlerseiten erlauben und vom Proxying über einen Unix-Domain-Socket zu einem Port wechseln. Dies verursacht pro Anfrage ein paar µs Latenz, da die Kosten für den Betrieb von Nginx mit SELinux als eine Sicherheitsebene anfallen, aber dies wird für Ihre Benutzer nicht wahrnehmbar sein.

Führen Sie zunächst die folgenden Befehle aus, um Nginx den Aufbau von Netzwerkverbindungen und den Zugriff auf Fehlerseiten zu ermöglichen:

setsebool -P httpd_can_network_connect 1
semanage fcontext -a -t httpd_sys_content_t /var/www
restorecon -R -v /var/www

Kommentieren Sie dann in Ihrer app.yaml die Zeile - "templates/web.socketed.template.yml" aus oder entfernen Sie sie, leiten Sie Port 80 an einen anderen Port auf dem lokalen Rechner weiter und bauen Sie den Container neu.

expose:
  - "8008:80"   # http

Verwenden Sie hier kein https – Sie haben SSL im externen Nginx beendet, und der Header X-Forwarded-Proto teilt Discourse mit, dass die Anfrage über https eingegangen ist. Stellen Sie sicher, dass Port 8008 (oder ein anderer von Ihnen gewählter Port) nicht öffentlich über Ihre Firewall-Einstellungen zugänglich ist.

Ändern Sie dann Ihre externe Nginx-Konfiguration vom Proxying über nginx.http.sock zu http://127.0.0.1:8008 (oder den von Ihnen gewählten Port) und löschen Sie den Standard-Header Connection: close, damit der externe Nginx nicht für jede Anfrage eine neue IP-Verbindung herstellen muss.

...
  location / {
    proxy_pass http://127.0.0.1:8008;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    # Deaktivieren Sie die Standardeinstellung "Connection: close"
    proxy_set_header "Connection" "";
...
1 „Gefällt mir“

Hallo @sam (und vielleicht @falco). Ich bin beauftragt, einige dieser #documentation:sysadmin-Dokumente zu bereinigen. Dieses hat sehr hohe Leserzahlen und ich denke, es ist eines der am wenigsten hilfreichen.

Glauben Sie, es macht Sinn, einen Ersatz zu schreiben, der haproxy - Official Image | Docker Hub und nginx - Official Image | Docker Hub startet, vielleicht mit Docker Compose, wobei der Nginx-Container die Zertifikate vom Discourse-Container einbindet und haproxy im TCP-Modus läuft, um so etwas zu tun (ich bin sicher, dass dies nicht funktionieren wird, aber ich gehe davon aus, dass ich herausfinden kann, was funktionieren wird):

backend my_app_be
  balance roundrobin
  option httpchk HEAD /srv/status
        server discourse app:443 check
  server fallback nginx:80 check backup

Ich denke, das könnte eine praktikable Lösung sein, die einfacher zu befolgen ist als dieses Thema. Ich würde dieses dann für historische Zwecke belassen (und vielleicht schließen?), aber auf das oben beschriebene verlinken.

3 „Gefällt mir“

Beachten Sie, dass dieses Thema erhebliche Überschneidungen mit dem folgenden aufweist:

Dieses Thema wurde in letzter Zeit erheblich aktualisiert (was die Überschneidungen noch weiter erhöhte). Vielleicht wäre es sinnvoll, den Offline-Seiten-Teil von hier dorthin als Hinweis zu verschieben (da er leicht hinzugefügt werden kann, wenn Sie bereits eine separate Nginx-Instanz betreiben) und dieses Thema dann als veraltet zu markieren (mit Links zu den Alternativen)?

Ihr vorgeschlagenes HAProxy-Thema wäre zusätzlich sinnvoll, da es der Standardweg für Leute ist, die aus anderen Gründen keine separate Nginx-Installation wünschen.

2 „Gefällt mir“

Woher sollte ich das wissen?

Oh.

Aber im Ernst, deine Lösung gefällt mir besser als meine!

Und in diesem Thema steht in großen Buchstaben, dass es sich um ein fortgeschrittenes Thema handelt.

Aber vielleicht ist das auch nicht nötig, da die meisten Leute Nginx sowieso besser verstehen. Ich habe jetzt darüber nachgedacht, also wird der schwierige Teil sein, mich davon abzuhalten. :slight_smile:

3 „Gefällt mir“

Es ist immer gut, wenn es viele Alternativen gibt. Aber diese hier ist eine der einfachsten (ziemlich viele…), und für viele vertraut.

Bitte fassen Sie diese also nicht an.

Und diese so zu belassen, hat noch einen weiteren Punkt: Suchergebnisse. Aufgrund des hohen Verkehrsaufkommens (und der sehr begrenzten Nutzung von Tags…) ist es heutzutage ziemlich schwierig, hier etwas Bestimmtes zu finden. Aber diese hier ist ziemlich leicht zu finden und hat einen sehr gezielten Zweck. Wenn dieses Thema zu einem anderen verschoben wird, wird es schwieriger zu finden sein.

Es gibt einen Grund, warum dies so beliebt ist… nicht viele sind inspiriert, Docker oder HAProxy zu verwenden.

2 „Gefällt mir“

Seufz. Nun, ich schätze, das stimmt auch, aber es ist mindestens 4 Jahre alt. Ich habe es nicht mehr kürzlich gemacht, aber Sie müssen die Dateien nicht mehr von Hand bearbeiten, da acme (oder etwas Ähnliches?) dies für Sie erledigt.

Was ich wirklich denke, ist, dass es viel mehr Sinn macht, eine Zwei-Container-Installation zu verwenden, die wenig Ausfallzeit hat, anstatt durch diese Reifen zu springen, um eine Seite online zu stellen, während Sie neu aufbauen, aber ich kann die Leute auch davon nicht überzeugen.

Also vielleicht ist es das Richtige, dies für die heutige Funktionsweise neu zu schreiben.

1 „Gefällt mir“

Und es ist viel schwieriger. Ich schätze, es ist einfacher, Anweisungen zur Installation und Verwendung von certbot zu korrigieren, als zu lehren, wie, wann und wo SQL-seitige Container usw. aktualisiert werden.

Außerdem gibt es noch einen weiteren Punkt gegen Docker (selbst Discourse funktioniert so…): Wir können viele Fragen auf ganz grundlegendem Niveau finden, wie man Docker überhaupt benutzt. Oder wie man Tippfehler in yml-Dateien vermeidet :wink:

Und trotzdem funktioniert es (außer der SSL-Abschnitt ist etwas verwirrend, aber das war schon vor 4 Jahren so :wink: )

Nein. Ich bin nicht gegen andere Lösungen. Ich bin sehr dagegen, wenn alte Links und Texte ohne sehr triftige Gründe an neue Orte verschoben werden.

2 „Gefällt mir“

Da müssen wir uns wohl uneinig sein. Aber ich glaube, es gibt wahrscheinlich viele Leute, die Ihnen zustimmen. (Vielleicht ist diese Lösung eine “Einrichten und Vergessen”-Lösung, und die Zwei-Container-Lösung erfordert Aufmerksamkeit, wenn es ein Postgres-Upgrade gibt, was etwa alle 2 Jahre vorkommt.)

OK. Da sind wir uns einig! Ich denke also, der Weg nach vorn ist, zu sehen, was ich tun kann, um diesen Teil zu bereinigen, und die Haproxy-Lösung auf Eis zu legen.

1 „Gefällt mir“

Ich würde das gerne als Teil von Discourse sehen, aber danke @fefrei dafür! Tolle Arbeit! Ich werde Apache dafür verwenden, aber zumindest die grundlegenden Schritte sollten die gleichen sein.

1 „Gefällt mir“

OK, hat nur 2 Stunden gedauert, bis es so war, wie ich es wollte!

Discourse Wartungsseite mit Apache2

Als root

cd /var/discourse
nano containers/app.yml

Kommentieren Sie diese Zeilen aus:

  #- "templates/web.ssl.template.yml"
  #- "templates/web.letsencrypt.ssl.template.yml"

expose:
  #- "80:80"   # http
  #- "443:443" # https

Fügen Sie am ENDE des Templates-Abschnitts hinzu (muss das Letzte sein):

  - "templates/web.socketed.template.yml"

Hinweis: Dadurch wird Discourse nur noch auf der internen IP lauschen und Apache2 übernimmt die Ports 80/443 und die SSL-Terminierung.

Hinweis: Discourse muss neu erstellt werden, damit dies wirksam wird:

cd /var/discourse
./launcher rebuild app

Apache2 und Certbot installieren

apt install -y apache2 certbot python3-certbot-apache

Verzeichnis für die HTML-Seite erstellen:

mkdir /var/www/discourse_maintenance

HTML-Seite:
/var/www/discourse_maintenance/discourse_maintenance.html

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="refresh" content="5">
        <title>Discourse Maintenance</title>
        <style>
            .center {
                display: flex;
                justify-content: center;
            }
            .container {
                max-width: 500px;
                padding: 50px 50px 30px 50px;
            }
            .title {
                padding-top: 20px;
            }
            h1, p {
                font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
            }
        </style>
    </head>
    <body>
        <div class="center">
            <div class="container">
                <h1 class="title">Discourse Maintenance&hellip;</h1>
                <p>We are currently upgrading the site, or performing scheduled maintenance.</p>
                <p>You'll automatically be redirected to the site once it's available.</p>
            </div>
        </div>
    </body>
</html>

Proxy-Modul aktivieren:

a2enmod proxy
a2enmod proxy_http
a2enmod headers

Apache vhost-Datei:

<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerName your.discourse.domain
  ServerAdmin your@email.com
  DocumentRoot /var/www/discourse_maintenance

  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined

  # Maintenance Mode
  RewriteEngine On
  RewriteCond /var/www/under_maintenance -f
  # safety check to prevent redirect loops 
  RewriteCond %{REQUEST_URI} !/discourse_maintenance.html$
  # redirect internally all requests to maintenance.html 
  RewriteRule ^.*$ /var/www/discourse_maintenance/discourse_maintenance.html

  ProxyPass / unix:///var/discourse/shared/standalone/nginx.http.sock|http://127.0.0.1/
  ProxyPassReverse / unix:///var/discourse/shared/standalone/nginx.http.sock|http://127.0.0.1/

  SSLCertificateFile /etc/letsencrypt/live/your.discourse.domain/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/your.discourse.domain/privkey.pem
  Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Um die Wartung zu aktivieren, führen Sie touch /var/www/under_maintenance aus.

Um die Wartung zu deaktivieren, führen Sie touch /var/www/under_maintenance aus.

Credits: Add an offline page to display when Discourse is rebuilding or starting up für die ursprüngliche Idee, die HTML-Seite (gekürzt/bearbeitet nach meinem Geschmack) und die Nginx-Konfiguration, auf der ich die Apache-Konfiguration basierte.

Bearbeitung: Vorschläge zur Automatisierung bei 502/503-Antworten sind willkommen. Ich habe es versucht, konnte es aber nicht so hinbekommen, wie ich wollte, also habe ich mich für eine bekannte Methode entschieden, die ich auf anderen Webservern verwende, wenn die Backend-Anwendung wegen Wartungsarbeiten usw. nicht verfügbar ist.

2 „Gefällt mir“

Beim Systemneustart verzögert dies die Fehler-/Wartungsseite, bis Docker hochgefahren ist, was deutlich länger dauert als das Booten des Systems. Es bietet auch nicht die Möglichkeit von systemeigenen SELinux-Schutzmaßnahmen für das System-nginx. Die Verwendung von System-nginx kann, zumindest auf einem systemd-verwalteten System mit schnellem Booten, die Fehlerseite innerhalb weniger Sekunden nach dem Booten anzeigen. Für mich bedeutet dies, dass meine Systeme während Systemaktualisierungen, die einen Neustart erfordern, sehr schnell mit der Wartungsseite antworten. (Ich betreibe AlmaLinux 9 auf dem Host, und es bootet sehr schnell zu nginx.)

Es könnte sinnvoll sein, eine haproxy-Alternative zu dokumentieren und Erfahrungen zu vergleichen, aber haproxy-in-Docker ist kein direkter Ersatz für externen nginx, und das Schließen dieses Themas wäre ein Fehler.

Es geht nicht nur um die Verfügbarkeit.
Die Verwendung von Docker für externen Datenverkehr über IPv4 verbirgt externe IPv6-Adressen vor dem internen nginx und Discourse. Sie haben das gleiche Problem mit haproxy. Schauen Sie in Ihre Protokolle nach 127.0.0.1 oder 172.* RFC1918 IP-Adressen nur für den lokalen Gebrauch. Wenn kein externer Proxy verwendet wird, erscheinen alle IPv6-Verbindungen unter derselben IP, was die Ratenbegrenzung der internen nginx-Zone unterbricht, da der gesamte IPv6-Verkehr als eine einzige Zone betrachtet wird.

IPv6 wird immer wichtiger.

2 „Gefällt mir“

Ich habe heute Morgen zufällig entdeckt, dass dieser Schritt nicht nur die Anwendung von Unix-Sockets vermeidet, sondern auch die Verwendung des real_ip-Moduls entfernt, sodass die Ratenbegrenzung auf allen Verbindungen zusammen angewendet wird und nicht auf allen Verbindungen pro IP. Ich sollte wahrscheinlich eine neue Vorlage mit Variablen beitragen, aber im Moment habe ich dies einfach zu meiner App-Container-YAML-Datei hinzugefügt:

run:
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 80;/
     to: |
       listen unix:/shared/nginx.http.sock;
       set_real_ip_from 172.0.0.0/24;
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /listen 443 ssl http2;/
     to: |
       listen unix:/shared/nginx.https.sock ssl http2;
       set_real_ip_from 172.0.0.0/24;

Ich weiß nicht, ob es sinnvoll ist, z. B. eine Datei templates/web.httpratelimit.yml mit etwas wie diesem mit einer Variablen für die Adresse zu haben, aber ohne Unix-Domain-Sockets zu verwenden. Gedanken dazu?

2 „Gefällt mir“
server {
  listen 80; listen [::]:80; listen 443 ssl http2; listen [::]:443 ssl http2;
  server_name DOMAIN;
  ssl_certificate      /etc/letsencrypt/live/DOMAIN/fullchain.pem;
  ssl_certificate_key  /etc/letsencrypt/live/DOMAIN/privkey.pem;

ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
  ssl_protocols TLSv1.2;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared:SSL:10m;

  add_header Strict-Transport-Security "max-age=63072000;";
  ssl_stapling on;
  ssl_stapling_verify on;

  client_max_body_size 0;

  location / {
    error_page 502 =502 /errorpages/offline.html;
    proxy_intercept_errors on;

    proxy_pass http://unix:/var/discourse/shared/standalone/nginx.http.sock:;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }

  location /errorpages/ {
    alias /var/www/errorpages/;
  }
}

! # Ändern Sie Ihre Domain und den Pfad der Fehlerdatei

Ich habe dieses Skript mit SSL erhalten und es funktioniert

2 „Gefällt mir“

Ich habe gerade versucht, diese Anleitung zu verwenden, und konnte sie nicht zum Laufen bringen.

Ich habe mit einem Nginx-Proxy begonnen, um zwei Websites aus einem einzigen Discourse-Container auszuführen. Ich wollte nur den Teil mit der Fehlerseite hinzufügen, also habe ich die Teile übersprungen, die sich mit Run other websites on the same machine as Discourse überschnitten zu haben schienen. Ich muss jedoch einen wichtigen Schritt übersehen haben. Am Ende habe ich das bekommen, was ich brauchte, aus diesem DigitalOcean-Tutorial. Es ist nicht schwer, dies manuell einzurichten, aber es scheint, als gäbe es einen besseren Weg.

Angesichts von Docker als Standardmethode zum Ausführen von Discourse klingt das besser. Ich gehe davon aus, dass es sich um eine Art von Einrichtung handelt, bei der man sie einrichtet und vergisst.

3 „Gefällt mir“

Die Idee in diesem Thread ist auch großartig für diejenigen unter uns, die Caddy als Reverse-Proxy verwenden, sei es als eigenständige Anwendung oder mit Cloudflare Tunnels.

discourse.example.org {
        reverse_proxy <host | ip>:port

        handle_errors 5xx {
                root * /path/to/error-pages
                rewrite * /error.html
                file_server {
                        status 404
                }
        }
}

Der Abschnitt status 404 ist nur wichtig, wenn Cloudflare Tunnels verwendet wird. Wenn Caddy 5xx an Cloudflare zurückgibt, zeigt Cloudflare Tunnel seinen eigenen Verbindungsfehler an. Das Ändern des Status zeigt Cloudflare eine gültige Live-Verbindung an, die eine Fehlerseite liefert.

2 „Gefällt mir“

Vielleicht verstehe ich nicht, wie das funktioniert, aber eine Aktualisierung aktualisiert doch nur die Seite, auf der man sich bereits befindet? Wie gelangt man dadurch zu einer anderen URL?

Es ist nicht nötig, zu einer anderen URL zu wechseln – der Trick ist, dass die Fehlerseite direkt unter der URL angezeigt wird, die der Benutzer aufgerufen hat (z. B. https://meta.discourse.org/t/add-an-offline-page-to-display-when-discourse-is-rebuilding-or-starting-up/45238/158), und genau diese URL wird aktualisiert, was entweder wieder denselben Fehler oder die gewünschte Seite anzeigt :slight_smile:

Oh, ich verstehe. Ich hatte die gesamte Einrichtung nicht sorgfältig gelesen, weil ich einen anderen Server für die Offline-Seite verwende, nur für den Fall, dass mein ganzer Rechner aus irgendeinem Grund ausfällt.
Ist auch sinnvoll. Jetzt versuche ich nur noch, mein JS zum Laufen zu bringen, das eigentlich zurück zur ursprünglichen URL umleiten soll…