Sidekiq runit-Skript zu fragil: **discourse:www-data** **+ forced** **-L log/sidekiq.log** verursacht 1-sekündigen Absturz

Hallo Team,

ich melde einen Fehler im offiziellen Docker/runit-Setup, der Sidekiq (und damit KI/Hintergrundjobs) stillschweigend beenden kann, ohne dass ein Rebuild oder Upgrade erforderlich ist.

Umgebung

  • Offizielle Discourse Docker-Installation (Standard-Container + runit-Dienste).
  • Kein Rebuild/Upgrade unmittelbar vor Auftreten des Problems.
  • Discourse AI-Plugin aktiviert, aber KI antwortet nicht mehr.

Symptome

  • KI wird in der Admin-UI als aktiviert angezeigt, aber es erscheinen keine KI-Antworten.
  • Hintergrundjobs (KI/Embeddings/Auto-Reply) scheinen festzustecken.
  • sv status sidekiq zeigt, dass Sidekiq unmittelbar nach dem Start wiederholt abstürzt:
down: sidekiq: 1s, normally up, want up
  • Manuelles Starten von Sidekiq funktioniert einwandfrei, die Anwendung selbst ist also in Ordnung:
bundle exec sidekiq -C config/sidekiq.yml
# bleibt aktiv, verbindet sich mit Redis, verarbeitet Jobs

Was wir herausgefunden haben

Das standardmäßige runit-Skript war:

exec chpst -u discourse:www-data \
  bash -lc 'cd /var/www/discourse && ... bundle exec sidekiq -e production -L log/sidekiq.log'

Zwei Schwachstellen:

  1. Primäre Gruppe www-data In meinem Container gehören typische beschreibbare Pfade discourse:discourse. Jede Abweichung bei tmp/pids oder gemeinsam genutzten Pfaden kann dazu führen, dass Sidekiq beim Booten unter www-data beendet wird, obwohl der manuelle Start als discourse funktioniert.
  2. Erzwungenes -L log/sidekiq.log Schreiben in gemeinsame Logs Der Protokollpfad ist ein Symlink nach /shared/log/rails/sidekiq.log. Wenn diese Datei/dieses Verzeichnis mit anderer Eigentümerschaft/Berechtigungen neu erstellt wird, kann Sidekiq sofort beendet werden, bevor nützliche Protokolle erstellt werden.

Zugehöriger Auslöser: logrotate schlägt täglich fehl

Unabhängig davon schlug logrotate jeden Tag fehl mit:

error: skipping "...log" because parent directory has insecure permissions
Set "su" directive in config file ...

Ursache waren Standard-Debian/Ubuntu-Berechtigungen:

  • /var/log gehört root:adm mit 0775 (gruppenschreibbar).
  • logrotate verweigert die Rotation, es sei denn, eine globale su-Direktive wird festgelegt. Dies ist das erwartete Upstream-Verhalten.

Genau in dem Moment, als der tägliche logrotate-Job fehlschlug, wurden auch Dateien unter /shared/log/rails/ (einschließlich sidekiq.log) neu erstellt, was wahrscheinlich mit der erzwungenen -L-Protokollierung interagierte und zur Sidekiq „1s Crash“-Schleife beitrug.

Fix (kein Rebuild erforderlich)

  1. Logrotate korrigieren, damit es aufhört, gemeinsame Logs in einem fehlerhaften Zustand zu berühren Eine globale su-Direktive hinzufügen:
# /etc/logrotate.conf (oben)
su root adm

Danach beendet sich logrotate -v mit 0 und meldet keine unsicheren übergeordneten Berechtigungen mehr.

  1. Sidekiq runit-Skript durch eine robustere Standardeinstellung ersetzen Der Wechsel zu discourse:discourse und der Standard sidekiq.yml und das Nicht-Erzwingen von -L log/sidekiq.log stabilisiert Sidekiq:
#!/bin/bash
exec 2>&1
cd /var/www/discourse

mkdir -p tmp/pids
chown discourse:discourse tmp/pids || true

exec chpst -u discourse:discourse \
  bash -lc 'cd /var/www/discourse && rm -f tmp/pids/sidekiq*.pid; exec bundle exec sidekiq -C config/sidekiq.yml'

Danach:

  • sv status sidekiq bleibt run.
  • KI/Hintergrundjobs werden wieder aufgenommen.

Anfrage / Vorschlag

Könnten wir in Betracht ziehen, den offiziellen Docker/runit Sidekiq-Dienst standardmäßig robuster zu gestalten?

Zum Beispiel:

  • Sidekiq unter discourse:discourse ausführen (entsprechend der typischen Eigentümerschaft innerhalb des Containers).
  • Bevorzugen Sie bundle exec sidekiq -C config/sidekiq.yml.
  • Vermeiden Sie das Erzwingen einer gemeinsamen Protokolldatei über -L log/sidekiq.log oder machen Sie diese widerstandsfähig gegen Berechtigungsabweichungen von logrotate/gemeinsam genutztem Volume.

Selbst ein Dokumentationshinweis („Wenn Sidekiq down: 1s anzeigt, aber der manuelle Start funktioniert, überprüfen Sie /etc/service/sidekiq/run und vermeiden Sie erzwungene gemeinsame Protokollierung“) würde Self-Hostern sehr helfen.

Gerne stelle ich weitere Protokolle zur Verfügung, falls erforderlich. Danke!

1 „Gefällt mir“

Wo finden Sie das? Sidekiq wird über den Unicorn-Master gestartet, um Speicher zu sparen. Ich sehe diesen Code überhaupt nicht in discourse_docker. Sieht so aus, als ob Sie vielleicht ein sehr altes Setup verwenden?

2 „Gefällt mir“

Hallo — ich formuliere dies streng basierend auf den Laufzeitfakten aus dem offiziellen Docker-Container neu.

Was ich im laufenden Container sehe (Fakten)

Dies ist eine offizielle Docker-Installation mit runit (Standard-Workflow des /var/discourse-Launchers; kein erneuter Build unmittelbar vor dem Vorfall). Im Container:

  1. Ein runit Sidekiq-Dienst existiert und wird überwacht
ls -l /etc/service/sidekiq/run
sv status sidekiq

Ausgabe während des Vorfalls:

down: sidekiq: 1s, normally up, want up
  1. Manueller Sidekiq-Start funktioniert
cd /var/www/discourse
sudo -u discourse bundle exec sidekiq -C config/sidekiq.yml

Dies bleibt aktiv, verbindet sich mit Redis und verarbeitet Jobs.

  1. **Das Patchen von nur /etc/service/sidekiq/run (ohne Rebuild) behebt die Crash-Schleife sofort Ersetzt wurde /etc/service/sidekiq/run durch:
#!/bin/bash
exec 2>&1
cd /var/www/discourse
mkdir -p tmp/pids
chown discourse:discourse tmp/pids || true
exec chpst -u discourse:discourse \
  bash -lc 'cd /var/www/discourse && rm -f tmp/pids/sidekiq*.pid; exec bundle exec sidekiq -C config/sidekiq.yml'

Danach:

sv status sidekiq
run: sidekiq: (pid <PID>) <SECONDS>s

Sidekiq wird also in diesem Image nicht über den Unicorn-Master gestartet; es ist ein runit-Dienst, dessen Laufzeitskript in einer Crash-Schleife stecken bleiben kann.

Warum Sie möglicherweise nicht den exakten Code in

discourse_docker sehen

Ich stimme zu, dass der wörtliche Text möglicherweise nicht im Repository enthalten ist, da /etc/service/sidekiq/run ein Laufzeitartefakt ist, das während des Image-Builds/-Boots generiert/injiziert wird, und nicht unbedingt eine wortgetreue Datei in discourse_docker. Aber es ist der aktive überwachte Dienst in diesem offiziellen Image, wie oben gezeigt.

Was die Fragilität ausgelöst hat (Fakten + minimale Schlussfolgerung)

  • Wir beobachteten auch tägliche logrotate-Fehler aufgrund von Standard-Debian-Berechtigungen: /var/log = root:adm 0775, sodass logrotate die Rotation verweigerte, bis global su root adm hinzugefügt wurde.
  • Als logrotate fehlschlug, erstellte es Dateien unter /shared/log/rails/ neu, einschließlich sidekiq.log.
  • Das Standard-runit-Skript in diesem Image verwendete discourse:www-data und zwang -L log/sidekiq.log in /shared/log, was Sidekiq sehr empfindlich gegenüber Berechtigungsabweichungen im Shared Volume macht und zu einem sofortigen Beenden führen kann, bevor nützliche Protokolle erstellt werden.

Anfrage / Vorschlag

Angesichts dessen, könnten wir in Erwägung ziehen, den standardmäßigen Docker/runit Sidekiq-Dienst zu härten?

Vorgeschlagene Standardwerte:

  • Ausführen als discourse:discourse (entspricht der typischen Eigentümerschaft innerhalb des Containers),
  • Start über bundle exec sidekiq -C config/sidekiq.yml,
  • Vermeidung des Erzwingens eines geteilten -L log/sidekiq.log (oder es resilient machen).

Dies würde die stille down: 1s Crash-Schleife verhindern, die alle Hintergrund-/KI-Jobs stoppt.

Gerne teste ich jeden Branch/Commit, auf den Sie mich verweisen.

Schon wieder… ich bin verwirrt, woher Sie Ihr Bild beziehen:

image

Dies ist das offizielle Bild.

Dies ist eine Suche nach dem Wort sidekiq in dem offiziellen Discourse Docker.

Es gibt 3 Treffer… nichts über eine runit-Einheit. Es wird über Unicorn verwaltet.

1 „Gefällt mir“

Hallo – danke, dieser Screenshot verdeutlicht das Layout.

Ich stimme zu, dass Sidekiq im aktuellen offiziellen Image kein separater runit-Dienst ist (kein /etc/service/sidekiq/). Es wird aus der Startkette des unicorn runit-Dienstes gestartet, was Ihrer /etc/service-Auflistung entspricht.

Mein Bericht bezieht sich weiterhin auf einen Laufzeitfehler dieses Sidekiq-Startpfads, unabhängig davon, ob er in einer eigenständigen runit-Einheit oder innerhalb von unicorn/run lebt:

Fakten zur Laufzeit auf meinem VPS (offizielles Docker, keine Neuerstellung/Aktualisierung unmittelbar vor dem Vorfall):

  1. Hintergrundjobs wurden gestoppt und KI-Antworten blieben aus.

  2. Sidekiq geriet in eine sofortige Crash-Schleife (down: 1s), als es vom Supervisor/der Startkette des Containers gestartet wurde.

  3. Ein manueller Start als discourse über bundle exec sidekiq -C config/sidekiq.yml blieb aktiv und verarbeitete Jobs, sodass die App/Redis in Ordnung waren.

  4. Gleichzeitig führten logrotate-Fehler dazu, dass /shared/log/rails/sidekiq.log (und zugehörige Pfade) mit unterschiedlichen Berechtigungen neu erstellt wurden; nach der Stabilisierung des Sidekiq-Startbefehls (Ausführung als discourse:discourse, Verwendung von sidekiq.yml, Vermeidung des Erzwingens von shared -L sidekiq.log) hörte die Crash-Schleife sofort auf.

Die tatsächliche Datei /etc/service/sidekiq/run existiert in diesem Image möglicherweise nicht – einverstanden –, aber der in den unicorn runit-Dienst eingebettete Sidekiq-Startschritt ist anfällig für Berechtigungs-/logrotate-Abweichungen auf dem Shared-Volume und kann Sidekiq ohne Neuerstellung stillschweigend beenden. Das ist das Kernproblem.

Vorschlag: Bitte ziehen Sie in Betracht, den Sidekiq-Start im offiziellen unicorn runit-Skript (oder dort, wo er generiert wird) zu härten:

  • Sidekiq unter discourse:discourse ausführen,

  • bevorzugt bundle exec sidekiq -C config/sidekiq.yml,

  • vermeiden, ein erzwungenes shared -L log/sidekiq.log zu erzwingen (oder es widerstandsfähig zu machen).