使用推荐(支持)安装方式在反向代理后安装Discourse

在本帖中,我将向您展示如何在 nginx 反向代理后面运行 discourse。同时仍使用受支持的安装方法。

要求:

  1. 有效的域名。
  2. 有效的 SSL 证书。
  3. 指向域名的有效 DNS 条目。
  4. 有效的电子邮件服务器或 SMTP 提供商。
  5. 可用的 Nginx 反向代理,并且能够访问实例并创建 SSL 证书以供将来使用。
  6. 可以运行 docker 的 VM 或 LxC 容器。

在本指南中,我将以我自己的实例为例,所有功能均正常运行,包括备份、升级等。已测试约 2 周。

我的 Discourse VM 配置:

  • CPU:4 核
  • 内存:6GB
  • 交换空间:8GB(SSD 交换文件)
  • 存储:50GB(SSD)
  • 操作系统:Ubuntu 22.04.3

您可以最低配置,但在测试时。Discourse 很容易消耗 2GB 内存。非活动使用量约为 1.48GB/6GB。

**注意:**此安装使用反向代理来创建 SSL 证书。如果需要,也可以使用 certbot。

步骤 1:

Get Ubuntu Server | Download | Ubuntu 下载最新的 Ubuntu 服务器

步骤 2:

  1. 在 VM/LxC 模板上安装 Ubuntu 服务器
    1.1 确保 Ubuntu 已更新所有服务器软件包。
  2. 使用以下命令安装所有必需的软件包:
apt update -y && apt upgrade -y && apt wget curl zip git docker.io nginx -y && reboot

步骤 3:
安装 Discourse。遵循初学者指南 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 的网络。除非您连接到 172.17.0.1/16 网络,否则 WAN 或 LAN 将无法访问它,而我们不需要这样做。

使用以下命令双重检查安装是否已完成并且 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"

然后注释掉 expose 部分,因为 discourse 现在将使用 websocket,最后 nginx 将能够启动,因为它将释放本地所需的 80 和 443 端口。

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

现在强制 Discourse 只提供带有 HTTPS 的链接,请在 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,您将看到以下页面。

就是这样,全部完成。然后您可以按照步骤注册并开始您的论坛/社区 :)。

附加步骤:

安装后维护
我们强烈建议您为您的操作系统启用自动安全更新。在 Ubuntu 中,使用 dpkg-reconfigure -plow unattended-upgrades

您可以直接使用此社区寻求支持,对于本地 Nginx,您可以随时在此帖子中寻求帮助。

10 个赞

这太棒了。谢谢。

我希望对本指南进行的一项改进是能够通过 nginx 提供静态资源。

目前,所有静态请求都将转到上述配置中的工作进程。我仍在尝试找出解决方法,如果找到,我会发布更新。

您能详细说明一下是哪些静态文件吗?

您是指nginx的404、302、500静态页面还是Discourse的静态页面?

我对此进行了一些研究,发现404页面的重定向是有效的。我唯一似乎无法设置的是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

但我无法真正理解它与我的问题有什么关系……