ログインが「不明なエラー」で失敗します

こんにちは、

私は基本的な Docker インストールガイド に従って、独自の Discourse インスタンスを運用しています。問題が発生しているのは、フォーラムを数日使用した後、ログインが完全に機能しなくなってしまうことです。なお、このフォーラムのユーザーは私一人だけです。残念ながら、このバグの原因が何なのかはわかりません。

再現手順 #1:

  1. Docker インストールガイドの手順に従って、新しい Discourse サーバーをインストールします。
  2. セットアップウィザードが完了したら、ログアウトして再度ログインできることを確認します。
  3. フォーラムを通常通り使い続けます。カテゴリや投稿を作成したり、デフォルトのテーマを変更したりしてみましょう。
  4. 通常の使用を数日または数週間続けた後、ログアウトすると再度ログインできなくなります。ログイン時に「不明なエラー」が表示され(ログインフォームに表示されます)、ログインに失敗します。

再現手順 #2:

  1. Docker インストールガイドの手順に従って、新しい Discourse サーバーをインストールします。
  2. セットアップウィザードが完了したら、ログアウトして再度ログインできることを確認します。
  3. ログインが失敗していた別の Discourse インスタンスからバックアップを復元します。
  4. 復元処理中に、「ログアウトされました」というポップアップメッセージが表示されます。復元は成功しましたが、ログイン時に「不明なエラー」が表示され(ログインフォームに表示されます)、ログインに失敗します。

自分で問題のデバッグを試みましたが、関連するエラーメッセージを見つけることができませんでした。これまでに試したことは以下の通りです:

cd /var/discourse
./launcher enter app
tail -F log/production_errors.log
tail -F log/production.log
tail -F log/unicorn.stderr.log
tail -F log/unicorn.stdout.log

ログイン失敗時にこれらのログにエラーメッセージは表示されません。この問題をデバッグするために他に何ができるでしょうか?よろしくお願いいたします。

管理者としてログインした状態で、Web ブラウザで /logs を確認しましたか?

わかりました、何か見つけました。“force https” 設定を有効にするとすぐにログインが失敗します。私の Discourse インスタンスは SSL 終端付きのプロキシサーバーの背後にあります。“force https” を無効にすると、ログインが再び機能します。したがって、これはおそらく Discourse のバグではなく、インフラストラクチャ設定の問題でしょう。

また、あなたが提案したとおりに試しましたが、ログにはエラーメッセージは表示されませんでした。

ついに解決策を見つけました。クライアントがプロキシやロードバランサーに接続する際に使用したプロトコル(HTTP または HTTPS)を識別するために、X-Forwarded-Proto ヘッダーを設定する必要があります。

私はプロキシサーバーとして HAProxy を使用しているため、HAProxy の設定に以下の行を追加しました。

http-request set-header X-Forwarded-Proto https if { ssl_fc }

これで「HTTPS 強制」が有効な場合でも、ログインが正常に動作するようになりました。

Discourse サーバーに確立されるすべての接続で PROXY プロトコルを使用したいと考えています。PROXY プロトコルは、受信接続のアドレスを相手側(つまり Discourse サーバー)に通知し、クライアントのアドレスやアクセスされたパブリックアドレスを把握できるようにします。この変更を行わない場合、Nginx はクライアントのアドレスを認識できず、すべてのログにリバースプロキシサーバーのアドレスが含まれてしまいます。以下の設定で対応できます。

root@talk3:/var/discourse# git diff
diff --git a/templates/web.template.yml b/templates/web.template.yml
index a60e6ef..55cb5f2 100644
--- a/templates/web.template.yml
+++ b/templates/web.template.yml
@@ -116,6 +116,19 @@ run:
       to: daemon off;

   - replace:
+      filename: /etc/nginx/nginx.conf
+      from: /# server_tokens off;/
+      to: |
+        server_tokens off;
+        real_ip_header proxy_protocol;
+        set_real_ip_from 192.168.1.19;  # プロキシサーバーのアドレス
+
+  - replace:
+      filename: "/etc/nginx/conf.d/discourse.conf"
+      from: /listen 80;$/
+      to: "listen 80 proxy_protocol;"
+
+  - replace:
       filename: "/etc/nginx/conf.d/discourse.conf"
       from: /upstream[^\}]+\}/m
       to: "upstream discourse {

また、HAProxy にこのサーバーに対して PROXY プロトコルの使用を強制するよう指示します。

-    server server-1 192.168.1.27:80 check
+    server server-1 192.168.1.27:80 check send-proxy

最後に ./launcher rebuild app を実行し、クライアントのアドレスがログに記録されることを確認します。

tail -F /var/discourse/shared/standalone/log/var-log/nginx/access.log