DiscourseConnectはforce_httpsをオンにしてもHTTPリダイレクトを生成します

Discourse をカスタムセットアップで Traefik の背後で実行しています。Discourse 専用の VM はここでは選択肢にありません。

Traefik はプレーン HTTP リクエストをコンテナに到達させないため、Discourse には SSL/Let’sEncrypt テンプレートが有効になっていません。HTTP リクエストは HTTPS にリダイレクトされるように設定されています。

DiscourseConnect のセットアップに問題があります。Traefik -> nginx[Discourse] リクエストはプレーンテキスト HTTP で送信されます(nginx は SSL をセットアップしていないため)。/etc/nginx/conf.d/discourse.confto preserve the proto, must be in http context というルールにより、Discourse(Rails アプリ)はプレーンテキスト HTTP リクエストを受信し、force_https が有効になっていても、/session/sso へのプレーンテキスト HTTP リダイレクトを返します。

これはバグだと思います。私のセットアップに関係なく、force_https が有効な場合、Discourse は常に HTTPS URL を生成すべきですが、そうしていません。

原因となっているコードは application_controller#redirect_to_login だと思いますが、Discourse のソースコードをそれほど深く調査したわけではないので確信はありません。

コード自体で解決可能でしょうか?

回避策として、nginx の discourse.conf をパッチして、そのルールを削除するルールを追加しようとしています。

ヘッダーの転送に関するサポートが必要になるはずです。それらを使用して、オリジンがどこであるかをNGINXに通知します。

proxy_set_header X-Forwarded-Proto https; を設定しましたか?

私にとって最も簡単だったのは、Discourse の app.yml に追加のラベルを設定して、Traefik に X-Forwarded-Proto: https ヘッダーを追加するように指示することでしたが、その後 nginx が独自のバージョンでそのパラメーターを上書きしていました。

そして、Discourse の nginx 設定がここで役割を果たします。

ここで Discourse は、元のリクエスト(私のセットアップでは、Traefik が送信するプレーンテキストなので常にプレーンテキストです)からプロトコルを推測しようとします。そして、それを使用して X-Forwarded-Proto を設定します を複数回設定します。

最終的に、containers/app.yml を編集して、これらのヘッダーを https にハードコードしました。

run:
  - exec: echo "Beginning of custom commands"
  ## If you want to set the 'From' email address for your first registration, uncomment and change:
  ## After getting the first signup email, re-comment the line. It only needs to run once.
  # - exec: rails r "SiteSetting.notification_email='no-reply@forum.cabana.network'"
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: /# attempt to preserve the proto, must be in http context\nmap \$http_x_forwarded_proto \$thescheme {\n  default \$scheme;\n  "~https$" https;\n}/\n
     to: |
       # force https scheme so Discourse generates HTTPs links and redirects (ie, `/login`)
  - replace:
     filename: "/etc/nginx/conf.d/discourse.conf"
     from: "$thescheme"
     global: "true"
     to: "https"
  - exec: echo "End of custom commands"

繰り返しますが、force_https 設定があれば、リバースプロキシやその他の関係者が処理しているかどうかにかかわらず、Discourse-the-rails-app はそれを尊重すべきだと思います。

これは、ホスティングプラットフォームでどのように行っているかです。ダウンストリームの nginx+Discourse が消費するために X-Forwarded-Proto を設定するロードバランサーレイヤーがあります。

これが機能するために追加の仕掛けは必要ありません。ここで何がうまくいかないのかわかりません。

これは実際に起こることです。

  def self.generate_sso(return_path = "/", secure_session:)
    sso = new(secure_session: secure_session)
    sso.nonce = SecureRandom.hex
    sso.register_nonce(return_path)
    sso.return_sso_url = Discourse.base_url + "/session/sso_login"
    sso
  end

そして base_url は以下から取得されます。

  def self.base_protocol
    SiteSetting.force_https? ? "https" : "http"
  end

  def self.base_url_no_prefix
    "#{base_protocol}://#{current_hostname_with_port}"
  end

  def self.base_url
    base_url_no_prefix + base_path
  end
「いいね!」 1