maltfield
(Michael Altfield)
1
Discourse をデフォルトの Nginx ではなく、Apache の仮想ホスト上で正常にセットアップできた方はいますか?
これらのフォーラムで Apache に関する議論の多くは、すでに Apache が動作しているホスト上で Discourse を実行するものについてです。私が目にした限り、すべてのケースで Apache を Nginx にリバースプロキシする構成になっています。明確にしておきますが、私は Docker ベンダーコンテナ内で Discourse を実行する際、Nginx ではなく Apache で仮想ホストを動かしたいと考えています。
具体的には、mod_security を有効にするために、Discourse のバックエンドを Nginx ではなく Apache で実行したいと考えています。Nginx で mod_security を使用するには、Nginx をソースからコンパイルする必要があり、その複雑さを避けたいのです。
現在のプロダクションサーバーでは、すでに複数のサイト(WordPress、MediaWiki など)を運用しています。HTTPS の終端と基本的な DoS 対策としてのレート制限には Nginx を使用し、その後 Varnish キャッシュを経由して mod_security を備えた Apache バックエンドへリクエストを転送する構成です。可能であれば、Discourse でもこのアーキテクチャを維持したいと考えています。つまり、バックエンドの Discourse Docker コンテナ内で Nginx ではなく、mod_security を備えた Apache を実行したいのです。
Discourse を Apache 上で実行する構成に成功した方はいますか?
maltfield
(Michael Altfield)
2
すみません、Docker は初心者です。Docker コンテナ上で ‘/etc/nginx/conf.d/discourse.conf’ ファイルがどのように配置されているのか、どうしても見つけることができません。‘./launcher’ スクリプトによって、そのファイルがどのように生成され、コンテナ上に配置されるのか、手順をご教示いただけますでしょうか?
追記:待ってください、Discourse はすでに Nginx をソースからコンパイルしているのでしょうか?
pfaffman
(Jay Pfaffman)
3
いいえ、成功した人はいません。Discourseはnginxと非常に密接に結びついており、それをApacheに置き換えるのは困難、あるいは不可能です。また、あなたがその作業を行う唯一の人物となるため、何か問題が起きても他の誰も気にしません。
世界中の誰もが利用しているDockerコンテナを使用し、セキュリティ上の理由で必要ならその前にApacheを配置してください。
maltfield
(Michael Altfield)
5
どうやら /etc/nginx/conf.d/discourse.conf は、テンプレートファイル /var/docker/templates/web.template.yml によってコンテナ上で生成されているようです。これは $home/config/nginx.sample.conf から直接コピーされ、その後 replace yaml ブロックで変更が加えられます(これは templates/web.socketed.template.yml などの後続のテンプレートでさらに更新されます)。
私は nginx.sample.conf ファイルが、image/base/install-nginx でソースからコンパイルする際に、nginx によって直接インストールされているものだと思っていました。しかし、コンテナ上で見つけた唯一の nginx.sample.conf ファイル(/var/www/discourse/config/nginx.sample.conf)には、すでに Discourse 固有のディレクティブが含まれていました。
nginx.sample.conf はどこから来るのでしょうか?
maltfield
(Michael Altfield)
6
nginx → Varnish → Apache → nginx という構成は避けたいですね 
明確にさせておきますが、Discourse の Docker コンテナ内で mod_security サポート付きで nginx をコンパイルするために ‘image/base/install-nginx’ スクリプトを更新する方が、Apache(Nginx ではなく)の背後で Discourse の vhost を実行するようにコンテナを更新するよりも安全だとお考えですか?もしそうであれば、install-nginx スクリプトを変更することによるリスクは何でしょうか?将来的にどのようにして Discourse のインストールが破綻する可能性がありますか?
Falco
(Falco)
7
PSA: 提案されているすべてのことは、技術的には「可能」ですが、完全にサポートされていません。Discourse を Web で提供するために人々が思いつくあらゆる組み合わせを、合理的にサポートすることはできません。したがって、このフォーラムでのサポートは、discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub ガイドに従ったインストールに限定されます。
discourse/config/nginx.sample.conf at main · discourse/discourse · GitHub
やがて、多くの方法で破綻します。あなたは上流の変更を継続的にマージし、あなたのフォークを永続的に処理する責任を負うことになります。
maltfield
(Michael Altfield)
8
完璧です、ありがとうございます!まったく別のリポジトリなんですね。コンテナはどのようにしてそのファイルを別のリポジトリから取得するのでしょうか?ここでしょうか?
そして、$home とは何ですか?
Falco
(Falco)
9
Discourse の app.yml を以下のように設定して解決しました:
expose:
- "2045:80" # http
- "8443:443" # https
…そして、vhost を以下のように設定しました:
<VirtualHost *myhostIP*:443>
ServerName forum.domain.org
ServerAlias forum.domain.org
... ProxyAddHeaders Off ProxyPass / “http://localhost:2045/” ProxyPassReverse / “http://localhost:2045/” `
質問を誤解していなければいいのですが 
@ledimeo @pfaffman さんが提案した通り、今後の新バージョンリリース時に問題が深刻化しないよう、この場合それが望ましいと考えます。しかし、彼はすでにフロントに別の nginx をリバースプロキシとして使用しており、以下のような構成は望んでいないようです:
とはいえ、apache から nginx へのプロキシ(たとえ結果としてこの 4 層になるとしても)は、公式インストールで Discourse の動作方法を変更しようとするよりも、少なくとも保守性が高いと考えられます。
この目的のためには、nginx は Docker コンテナという「ブラックボックス」の中にあり、それについては気にしなくてよいと考えるのが良いでしょう。
つまり:nginx → varnish → apache → Discourse(nginx と unicorn で構成)
(上流プロキシの IP アドレスを信頼するように設定するのを除く)
maltfield
(Michael Altfield)
13
つまり、Discourse の nginx の前に Apache をプロキシとして追加するのは確かに選択肢の一つです。
プロが関与すれば将来のアップグレードが容易になるという点には同意しますし、それは重要な点です。
しかし、アーキテクチャに別のホップを追加すると、将来的な問題のデバッグが複雑になるだけでなく、@sam が2016年のこの投稿で指摘したように、ロングポーリングを使用する Web アプリケーションに対する Apache のプロキシとしてのパフォーマンスにも懸念があります。
私は一般的に mod_security 以外では Apache よりも nginx を好みます。RHEL/Cent や Debian の OS リポジトリが Apache と同様に mod_security を有効にするパッケージを nginx にも含めてくれると素晴らしいのですが、現状では RHEL/Cent と Debian 両方で mod_security を nginx で有効にするには、nginx をソースからコンパイルする必要があります。そして、私は本番環境でソースからコンパイルされたパッケージに依存することを極端に避けています。
maltfield
(Michael Altfield)
14
関連:install-nginx スクリプトを調べていたところ、小さな論理エラーを発見しました。/tmp/ からの nginx ソースを削除するはずのクリーンアップ行が、実際には何も行っていないのです。
/tmp/nginx/ ディレクトリは存在しません。/tmp/nginx-$VERSION/ です(現在は /tmp/nginx-1.17.4/)。また、tarball として /tmp/nginx-1.17.4.tar.gz もあります。
おそらく、以下のようにすべきでしょう:
rm -fr /tmp/nginx-${VERSION}*
maltfield
(Michael Altfield)
15
残念ながら、更新した /var/discourse/image/base/install-nginx スクリプトが、/var/discourse/launcher destroy app && /var/discourse/launcher rebuild app を実行した際に実行されていないようです。
この rebuild コマンドが更新された install-nginx スクリプトを再実行しない理由はあるでしょうか?
Stephen
(Stephen)
16
リビルド後にスクリプトをどのように修正していますか?フックを使っていますか?
maltfield
(Michael Altfield)
17
vim /var/discourse/image/base/install-nginx
Stephen
(Stephen)
18
再ビルド後でも変更は反映されますか?イメージ内で直接ファイルを編集しても機能しません。
app.yml からフックを使用してファイルを修正する必要があります。
Docker を使ったことはありますか?
Falco
(Falco)
19
Docker に不慣れな場合、これは難しい道になるでしょう…
discourse_docker には、パブリック Docker レジストリに存在するベース Docker イメージのソースコードが含まれています。これはローカルで実行されることはなく、再利用可能なイメージを持つことがその唯一の理由です。
maltfield
(Michael Altfield)
20
わかりました。シンプルさのために vim について嘘をつきました。実際には、スクリプトを冪等的かつ堅牢に更新するために、これらのコマンドを実行しています。
cd /var/discourse/image/base
cp install-nginx install-nginx.`date "+%Y%m%d_%H%M%S"`.orig
# nginx ソースをダウンロードする直前に、modsecurity nginx モジュールをチェックアウトするブロックを追加
grep 'ModSecurity' install-nginx || sed -i 's%\(curl.*nginx\.org/download.*\)%# mod_security --maltfield\napt-get install -y libmodsecurity-dev modsecurity-crs\ncd /tmp\ngit clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git\n\n\1%' install-nginx
# 上記でチェックアウトした ModSecurity モジュールを含むように configure 行を更新
sed -i '/ModSecurity/! s%^[^#]*./configure \(.*nginx.*\)%#./configure \1\n./configure \1 --add-module=/tmp/ModSecurity-nginx%' install-nginx
# クリーンアップセクションに行を追加
grep 'rm -fr /tmp/ModSecurity-nginx' install-nginx || sed -i 's%\(rm -fr.*/tmp/nginx.*\)%rm -fr /tmp/ModSecurity-nginx\n\1%' install-nginx
コンテナのブートストラップ時に使用される実際の install-nginx スクリプトを変更するには、これらのコマンドをどこに配置すればよいでしょうか?