Discourseをリバースプロキシ経由で推奨(サポート済み)インストール

この投稿では、サポートされているインストール方法を引き続き使用しながら、nginx リバース プロキシの背後で Discourse を実行する方法を正確に説明します。

要件:

  1. 有効なドメイン名。
  2. 有効な SSL 証明書。
  3. ドメイン名を指す有効な DNS エントリ。
  4. 有効な動作中のメール サーバーまたは SMTP プロバイダー。
  5. 動作中の Nginx リバース プロキシと、インスタンスに到達して後で使用するために SSL 証明書を作成できること。
  6. Docker を実行できる VM または LxC コンテナー。

このガイドでは、すべての機能が動作し、バックアップ、アップグレードなども可能な独自のインスタンスを例として使用します。約 2 週間テスト済みです。

私の Discourse VM の仕様:

  • CPU: 4 コア
  • RAM: 6GB
  • スワップ: 8GB (SSD スワップファイル)
  • ストレージ: 50GB (SSD)
  • OS: Ubuntu 22.04.3

テスト時には最小構成でも使用できますが、Discourse は基本的に 2GB を簡単に消費します。非アクティブな使用量で 6GB 中 1.48GB です。

注意: このインストールでは、リバース プロキシを使用して SSL 証明書を作成します。必要に応じて certbot を使用できます。

ステップ 1:

Get Ubuntu Server | Download | Ubuntu から最新の Ubuntu Server をダウンロードします。

ステップ 2:

  1. VM/LxC テンプレートに Ubuntu Server をインストールします。
    1.1 Ubuntu がすべてのサーバー パッケージで最新の状態になっていることを確認します。
  2. 次のコマンドを使用して、必要なすべてのパッケージをインストールします。
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

ステップ 3:

Discourse のインストール。Beginner Guide discourse/docs/INSTALL-cloud.md at main · discourse/discourse · GitHub に従います。

サーバーに SSH 接続し、次のコマンドを入力します。

sudo -s
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
chmod 700 containers

上記を完了したら、./discourse-setup を実行できます。

すべてのステップに従い、正しく入力してください。これは、正常なインストールに不可欠です。ステップでは、次のことが尋ねられます。セットアップ ガイドからの例:

インストールを実行させます。インターネット接続とサーバーの仕様によっては時間がかかる場合があります。私の VM セットアップを使用してインストールを完了するには、約 5 ~ 8 分かかりました。

ステップ 4:

インストールが完了すると、Docker コンテナーが使用している開始コマンドと生成されたコンテナー ID (ハッシュ) が表示されます。

注意: WAN 経由でプロキシの背後にいるため、502 エラーが表示されます。コンテナーは Docker のネットワークを使用しているため、WAN または LAN からは到達できません。ただし、172.17.0.1/16 ネットワークに接続することはできますが、これは必要ありません。

次のコマンドを使用して、インストールが完了し、Docker コンテナーが実行されていることを再確認します。

docker ps

次の出力が表示されるはずです。

CONTAINER ID   IMAGE                 COMMAND        CREATED      STATUS       PORTS     NAMES
XXXXXX   local_discourse/app   “/sbin/boot”   6 days ago   Up 7 hours             app

ステップ 5:

リバース プロキシ構成に合わせて app.yml ファイルを更新します。

好みのテキスト エディターを使用して /var/discourse/container/app.yml を開きます。
次の行を置き換える/コメントアウトします。(これはローカル Nginx によって処理されます)

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

#- "templates/web.letsencrypt.ssl.template.yml" の直後に次を追加します。

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

次に、Discourse は Web ソケットを使用するようになるため、expose セクションをコメントアウトします。これにより、Nginx はローカルで必要な 80 および 443 ポートを解放できるようになります。

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

HTTPS を使用したリンクのみを供給するように Discourse に強制するには、env セクションに次を追加します。

# FORCE SSL
DISCOURSE_FORCE_HTTPS: true

これで、すべてを機能させるために、アプリを再構築する必要があります。次を使用します。

cd /var/discourse
./launcher rebuild app

それを実行して完了させます。成功したかどうかを確認するには、Docker 実行コマンドが表示されていることを確認するか、単に docker ps を実行して、コンテナーが実行されていることを確認します。

ステップ 6:

Nginx を有効にし、デフォルトのサイトを Docker コンテナーを指すように構成します。リバース プロキシがローカル Nginx を使用してコンテナーにアクセスできるようにします。

次を実行します。

systemctl enable nginx && systemctl start nginx

実行されているかどうかを確認するには、ブラウザとローカル IP を使用して Nginx のデフォルトのランディング ページにアクセスしてみてください。
例:

http://10.10.0.4

Nginx の「おめでとうございます」ページが表示されるはずです。

ステップ 7:

デフォルトの構成を次のように更新します。
まず、構成ファイルを空にします。

echo "" > /etc/nginx/sites-available/default

テキスト エディターを使用して構成ファイルを開き、次を追加します。
注意: server_name をドメインに、ssl_certificatessl_certificate_key を SSL 証明書とキーファイルの場所に更新してください。
Certbot を使用できますが、証明書とキーをリバース プロキシから rsync しています。

server {
    listen 80; listen [::]:80;
    server_name add.yourdomain.com;
    server_tokens off;
    return 301 https://$host$request_uri;
}
# Default server configuration
#
server {
	# SSL configuration
	#
	server_tokens off;
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;

    server_name add.yourdomain.com;
	ssl_certificate /etc/ssl/certs/your_ssl_cert.bundle;
	ssl_certificate_key /etc/ssl/private/your_ssl_cert.key;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
	ssl_prefer_server_ciphers on;
	location / {
		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 $scheme;
		proxy_set_header X-Real-IP $remote_addr;
	}
}

新しいデフォルト ファイルを保存し、systemctl restart nginx を実行します。

ステップ 8:

ブラウザを開き、フォーラム ドメイン https://somedomain.com にアクセスすると、次のページが表示されます。

これで完了です。その後、登録してフォーラム/コミュニティを起動するための手順に従うことができます :)。

追加ステップ:

インストール後のメンテナンス
OS の自動セキュリティ更新を有効にすることを強くお勧めします。Ubuntu では、dpkg-reconfigure -plow unattended-upgrades を使用します。

サポートについては、このコミュニティで対応できます。ローカル Nginx については、この投稿で遠慮なく支援を求めてください。

「いいね!」 10

素晴らしいです。ありがとうございます。

このガイドの改善点として、nginx経由で静的アセットを提供できるようにしたいと考えています。

現在の設定では、すべての静的リクエストがワーカーに送られています。この回避策を見つけようとしていますが、解決したらアップデートを投稿します。

静的ファイルとは具体的にどのようなものを指しているのか、詳しく教えていただけますか?

nginxの404、302、500の静的ページのことでしょうか、それともDiscourseの静的ページのことでしょうか?

少し調べてみたところ、404ページのredirectは機能することがわかりました。設定できないのは500エラーページのみのようです。

具体的にどのようなことを調べているのか、もう少し詳しく教えていただけますでしょうか? :slight_smile:

このガイドは素晴らしいです。すべて順調に進みましたが、ウェブサイトの読み込みで問題が発生しました。「リダイレクトが多すぎます」というエラーが表示されます。IPアドレスを使用するとDiscourseは正常に読み込まれますが、リダイレクトの問題を解決できません。あと一歩なのですが。

どなたか助けていただけると幸いです。

よろしくお願いします。

この問題の解決方法を知っている方はいらっしゃいますか?サイトは動作していますが、コンテナの nginx error.log でこれらのエラーに気づきました。上記の手順に従ってリバースプロキシを設定しました。

コンテナ内の /etc/nginx/conf.d/discourse.conf を見ると、以下が表示されます。

upstream discourse { server 127.0.0.1:3000; }

これは次のようなものになるべきでしょうか?

upstream discourse { http://unix:/var/discourse/shared/standalone/nginx.http.sock; }

コンテナ内の /var/log/nginx を見ると、次のようなエラーが表示されます。

2025/02/09 21:00:21 [error] 69#69: *1 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xxx.xxx, server: _, request: "POST /message-bus/b39980c2387e4750bc1e320cb6195424/poll?dlp=t HTTP/1.1", upstream: "http://127.0.0.1:3000/message-bus/b39980c2387e4750bc1e320cb6195424/poll?dlp=t", host: "discourse.xxxx.com"

2025/02/09 21:00:23 [error] 67#67: *3 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xxx, server: _, request: "GET /chat/api/me/channels HTTP/1.1", upstream: "http://127.0.0.1:3000/chat/api/me/channels", host: "discourse.xxxx.com"

2025/02/09 21:00:23 [error] 70#70: *5 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xxx, server: _, request: "POST /message-bus/d95b6999d26242f28f4875732b195440/poll HTTP/1.1", upstream: "http://127.0.0.1:3000/message-bus/d95b6999d26242f28f4875732b195440/poll", host: "discourse.xxxx.com"

ありがとうございます!

ステップ5を正しく実行しましたか?ソケットを使用していないようです。

はい、コンテナ外のローカルリバースプロキシでソケットを使用しており、app.yml のステップ 5 に従いました。

/var/discourse/containers# grep web.socketed.template.yml app.yml
  - "templates/web.socketed.template.yml"

/var/discourse/containers# grep templates/web.ssl.template.yml app.yml
  #  - "templates/web.ssl.template.yml"

/var/discourse/containers# grep templates/web.letsencrypt.ssl.template.yml app.yml
  #  - "templates/web.letsencrypt.ssl.template.yml"

/var/discourse/containers# grep http app.yml

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

/var/discourse/containers# grep DISCOURSE_FORCE_HTTPS app.yml
DISCOURSE_FORCE_HTTPS: true
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  ## Uncomment the next line to enable the IPv6 listener
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
  ## Uncomment these two lines if you wish to add Lets Encrypt (https)
  #  - "templates/web.ssl.template.yml"
  #  - "templates/web.letsencrypt.ssl.template.yml"
  - "templates/web.socketed.template.yml"
## which TCP/IP ports should this container expose?
## If you want Discourse to share a port with another webserver like Apache or nginx,
## see https://meta.discourse.org/t/17247 for details
#expose:
#  - "80:80"   # http
#  - "443:443" # https

こちらを確認しました: Discourse working with jwilder /nginx proxy & acme-companion

しかし、私の問題に関して、それが何を意味するのかよく理解できませんでした。