“论坛”作为上一代互联网产品,已经淡出了很多人的互联网生活了。不过,我仍然很喜欢“论坛”这一讨论模式。很多像我一样的互联网遗民,依旧喜欢在各论坛中水贴。今天我们就来介绍一下国外非常著名的Discourse论坛程序的安装与配置。
1, Discourse论坛程序简介
Discourse程序基于Ruby on Rails, Ember.js, 以及PostgreSQL, 完全免费开源。它拥有丰富的功能,强劲的性能,高稳定性与安全性,以及可以高度自定义的界面。其具体功能可以参考官网:https://www.discourse.org/.
Discourse可以使用Docker搭建,也可以纯手工搭建。Docker搭建比较简单,仅在第2节稍做介绍。手动安装可以让您学习Ruby on Rails程序的部署流程,且在排错搜索中提升自己的运维能力。手动部署的Discourse也可以显著降低系统要求。本文将主要介绍在Ubuntu 18.04 LTS操作系统中Discourse的手动搭建,不使用Docker.
本文许多内容翻译自 Linuxbabe , 有删改。本文作者为香菇肥牛,原文链接为 https://qing.su/article/install-discourse-without-docker.html ,转载需注明原文链接。谢谢!
长文预警,现在开始!
2, Docker搭建简介
如果是生产环境,建议您使用Docker来部署Discourse, 因为它易于维护。 Docker版本的Discourse是唯一的可以获得官方技术支持的版本。
使用Docker搭建Discourse非常简单,且支持Linux平台。您需要首先安装git, 然后执行下面的命令即可。引导程序将自动为您安装Docker和其他所有需要的组件。
1
2 3 |
git clone
https:
//
github.com
/
discourse
/
discourse_docker.git
/
var
/
discourse
cd / var / discourse . / discourse-setup |
3, 手动安装的系统需求
手动安装的步骤仅在Ubuntu 18.04 LTS 64 bit操作系统上测试通过。Ubuntu 20.04 LTS 64 bit操作系统中可以使用一些方法非常麻烦地勉强安装成功(需要使用另一台Ubuntu 18.04的服务器做一次数据库移植),这里不做介绍了。其他Linux平台无法安装通过。
Discourse程序需要系统有至少1 GB内存。安装完毕后系统占用600 MB左右内存。安装过程需要约1-3小时,请留好时间。请将您的域名解析到服务器上。下文将以域名bbs.qing.su为例指代将要搭建的Discourse论坛域名。
4, 安装并配置PostgreSQL数据库
首先,安装PostgreSQL数据库程序
1
|
apt-get install
postgresql
|
安装完毕后,PostgreSQL会自动运行在5432端口。然后,使用postgres账户登录postgresql并新建数据库,用户名,以及密码。
1
2 3 4 5 6 7 8 9 |
sudo
-
u postgres psql
CREATE DATABASE discourse; CREATE USER discourse_user; ALTER USER discourse_user WITH encrypted password 'qing.su' ; ALTER DATABASE discourse owner TO discourse_user; \c discourse; CREATE extension hstore; CREATE extension pg_trgm; \q |
这里,我们设置数据库名为discourse, 数据库用户名为discourse_user, 密码为qing.su
5, 安装Ruby和Bundler
Discourse是基于Ruby on Rails的,因此需要安装Ruby程序,以及Ruby程序的依赖环境的管理器Bundler. Ubuntu 18.04版本的官方源中包含了Ruby 2.5版本,Ubuntu 20.04版本的官方源中包含了Ruby 2.7版本。然而,目前Discourse仅支持Ruby 2.6版本。因此,为了方便,我们使用snapd包管理器安装2.6版本的Ruby on Rails. 如果您不信邪地想要在Ubuntu 20.04上安装,这里需要手动编译安装对应的Ruby版本,不知为何snap安装的Ruby和Bundler之后会报错。
1
2 |
apt-get install
snapd
snap install ruby --classic --channel = 2.6 / stable |
第一次使用snap安装软件,需要退出SSH然后重新登录SSH. 重新登录后,继续安装Bundler.
1
|
/
snap
/
bin
/
gem
install
bundler
|
6, 构建Discourse依赖环境
首先,使用git获取Discourse源代码。
1
2 3 4 5 |
apt-get install
git
gcc
build-essential ruby-dev libxslt-dev libxml2-dev zlib1g-dev libpq-dev imagemagick
screen
redis-server optipng pngquant jhead jpegoptim gifsicle
git clone https: // github.com / discourse / discourse.git mkdir / var / www / mv discourse / / var / www / cd / var / www / discourse / |
然后前往 https://github.com/discourse/discourse/releases 查看当前的Discourse版本。我这里将使用v2.5.0.
1
|
git checkout
2.5.0
|
接下来,开始安装Discourse程序的依赖环境。这里需要安装的组件较多,时间较长,建议使用screen避免掉线后出现错误。
1
2 3 |
screen
-S
discourse
RAILS_ENV =production / snap / bin / bundle config set path '/var/www/discourse/vendor/bundle/' RAILS_ENV =production / snap / bin / bundle install |
安装完毕后,按下CTRL + A + D键退出screen.
7, 初始化Discourse数据库
依赖环境搭建完毕,我们开始配置Discourse. 编辑数据库连接文件:
1
2 |
cp
config
/
discourse_defaults.conf config
/
discourse.conf
vi config / discourse.conf |
找到下面几行,依次填入数据库信息:
1
2 3 4 5 |
db_host = localhost
db_port = 5432 db_name = discourse db_username = discourse_user db_password = qing.su |
再找到hostname这行,填写论坛的域名:
1
|
hostname
=
"bbs.qing.su"
|
保存退出。再编辑生产环境ruby配置文件:
1
|
vi
config
/
environments
/
production.rb
|
在该文件第5行添加:
1
|
require
'uglifier'
|
然后找到下面这行(我这里是第17行):
1
|
config.
assets
.
js_compressor
=
:uglifier
|
将其替换成:
1
|
config.
assets
.
js_compressor
= Uglifier.
new
(
harmony:
true
)
|
如下图所示:
保存退出。然后,执行下面的命令初始化数据库:
1
|
RAILS_ENV
=production
/
snap
/
bin
/
bundle
exec
rake db:migrate
|
如果该命令执行过程中报错,请再执行一遍。
8, 编译静态文件
接下来,我们要编译静态文件,比如javascript文件等。编辑文件 /var/www/discourse/lib/tasks/assets.rake , 找到并注释掉下面这行(我这里是第281行)。
1
|
brotli
(
path, max_compress
)
|
注释掉这一行的原因是brotli压缩和gzip压缩一起编译的时候会冲突报错。
保存退出后,编译安装静态文件:
1
|
RAILS_ENV
=production
/
snap
/
bin
/
bundle
exec
rake assets:precompile
|
9, 使用Puma服务器运行Discourse
完整的Discourse部署可以分为后端运行服务器程序与前端反代服务器程序。这一节,我们介绍使用Puma服务器运行Discourse.
编辑文件 /var/www/discourse/config/puma.rb , 找到下面这行:
1
|
APP_ROOT =
'/home/discourse/discourse'
|
将其替换为我们的Discourse安装目录:
1
|
APP_ROOT =
'/var/www/discourse'
|
然后建好Puma服务器sockets目录:
1
2 |
mkdir
/
var
/
www
/
discourse
/
tmp
/
sockets
/
mkdir / var / www / discourse / tmp / pids / |
运行Discourse:
1
|
RAILS_ENV
=production bundle
exec
puma
-C
/
var
/
www
/
discourse
/
config
/
puma.rb
|
如果没有以外,屏幕上会显示一大堆内容,比如下面这样:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 |
root
@
server:
/
srv
/
www
/
forum
/
public_html
# RAILS_ENV=production bundle exec puma -C /srv/www/forum/public_html/config/puma.rb
[ 13383 ] Puma starting in cluster mode... [ 13383 ] * Version 4.3.5 ( ruby 2.6.6-p146 ) , codename: Mysterious Traveller [ 13383 ] * Min threads: 8 , max threads: 32 [ 13383 ] * Environment: development [ 13383 ] * Process workers: 4 [ 13383 ] * Preloading application [ 13383 ] * Listening on unix: /// srv / www / forum / public_html / tmp / sockets / puma.sock [ 13383 ] ! WARNING: Detected 4 Thread ( s ) started in app boot: [ 13383 ] ! #<Thread:0x00005598f921d918@/srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb:38 sleep_forever> - /srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb:40:in `pop' [ 13383 ] ! #<Thread:0x00005598fd72a4c0@/srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:334 sleep> - /srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/activerecord-6.0.3.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:337:in `sleep' [ 13383 ] ! #<Thread:0x00005598fe4eb2f8@/srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/message_bus-3.3.1/lib/message_bus.rb:700 sleep> - /srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/redis-4.2.1/lib/redis/connection/ruby.rb:55:in `select' [ 13383 ] ! #<Thread:0x00005598fe4eb0c8@/srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/message_bus-3.3.1/lib/message_bus/timer_thread.rb:38 sleep> - /srv/www/forum/public_html/vendor/bundle/ruby/2.6.0/gems/message_bus-3.3.1/lib/message_bus/timer_thread.rb:123:in `sleep' [ 13383 ] * Daemonizing... |
最后出现一个* Daemonizing…说明运行成功。此时,Discourse运行于 /var/www/discourse/tmp/sockets/puma.sock .
10, 使用Nginx反代Discourse
上一节我们提到,Discourse部署需要后端运行服务器与前端反代服务器。这一节我们将介绍使用Nginx来反代运行了Discourse的Puma后端服务器。
首先,安装Nginx. 生产环境建议编译安装Nginx. 如果是测试环境,您可以直接用源安装Nginx.
1
|
apt-get install
nginx
|
将程序提供的nginx配置文件复制到Nginx配置文件目录中,并编辑。
1
2 |
cp
config
/
nginx.sample.conf
/
etc
/
nginx
/
conf.d
/
discourse.conf
vi / etc / nginx / conf.d / discourse.conf |
找到下面这一段,注释掉:
1
2 3 4 |
upstream discourse
{
server unix: / srv / www / forum / public_html / tmp / sockets / nginx.http.sock; server unix: / srv / www / forum / public_html / tmp / sockets / nginx.https.sock; } |
找到下面这一段,取消注释:
1
2 3 |
#upstream discourse {
# server unix:/srv/www/forum/public_html/tmp/sockets/puma.sock; #} |
找到server_name行,在后面填写您的论坛域名:
1
|
server_name bbs.qing.su;
|
找到下面这一行,注释掉:
brotli_static on;
然后保存退出。新建Nginx缓存文件夹,然后重新载入Nginx配置文件:
1
2 |
mkdir
-p
/
var
/
nginx
/
cache
/
service nginx reload |
此时,访问您的域名,比如http://bbs.qing.su, 应该可以看到Discourse页面了,如下图。
接着给Nginx配置SSL. 这里将使用Let’s Encrypt免费证书。其他的证书安装类似。
1
2 |
apt-get install
certbot python3-certbot-nginx
certbot --nginx --agree-tos --redirect --hsts --staple-ocsp -d bbs.qing.su |
请将bbs.qing.su换成您自己的域名。再编辑文件 /etc/nginx/conf.d/discourse.conf ,在SSL配置部分添加下面这一行:
1
|
add_header Content-Security-Policy upgrade-insecure-requests;
|
如下图所示:
保存退出后,重新载入Nginx配置文件。
1
|
service nginx reload
|
再次访问您的论坛域名,比如https://bbs.qing.su, 就可以看到SSL配置成功了。
11, 创建管理员账号并配置论坛参数
Discourse安装好之后,需要创建管理员账户。如果您一直跟着我的教程操作,那么您当前的目录位置为Discourse程序目录(/var/www/discourse/)。使用下面的命令可以新建管理员账户:
1
|
RAILS_ENV
=production
/
snap
/
bin
/
bundle
exec
rake admin:create
|
按照屏幕提示输入邮箱和密码,就会生成管理员账户。如下图。
然后,重启Puma服务器。
1
|
RAILS_ENV
=production bundle
exec
pumactl
-P
/
var
/
www
/
discourse
/
tmp
/
pids
/
puma.pid restart
|
此时,访问您的论坛页面,您可以看到类似于下面的窗口,可以用管理员账号登录了。
如果您打开网站后发现是502错误,说明Puma重启失败,可以执行下面的命令启动Discourse:
1
|
RAILS_ENV
=production bundle
exec
puma
-C
/
var
/
www
/
discourse
/
config
/
puma.rb
|
登录之后,点击页面上面的Setup Wizard, 开始设置Discourse参数,比如站点名,站点标题,板块,Logo, 等等。
如果您使用CloudFlare CDN反代您的网站,您需要配置CDN域名,请在后台找到settings -> security -> content security policy src, 然后添加https://bbs.qing.su/cdn-cgi/. 将bbs.qing.su换为您的域名。
12, 使用Sidekiq运行后台服务
Sidekiq是一个开源的计划任务执行程序。通过配置Sidekiq, 我们能够实现发送注册邮件等后台任务。这里,我们可以把Sidekiq简单地理解为系统里的cron job.
编辑文件 /var/www/discourse/config/sidekiq.yml ,在文件末尾添加下面这几行:
1
2 3 4 5 6 7 |
production:
:concurrency: 2 :queues: - [ critical, 4 ] - [ default, 2 ] - [ low ] - [ ultra_low ] |
如果您的访客量较大,可以提高对应的数值。
保存退出,然后新建sidekiq后台服务。新建文件 /etc/systemd/system/discourse-sidekiq.service , 内容如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[
Unit
]
Description =Discourse sidekiq background processing service After =multi-user.target [ Service ] Type =simple User =root PIDFile = / var / www / discourse / tmp / pids / sidekiq.pid WorkingDirectory = / var / www / discourse Environment = RAILS_ENV =production ExecStart = / snap / bin / bundle exec sidekiq -C config / sidekiq.yml Restart =on-failure RestartSec = 5 [ Install ] WantedBy =multi-user.target |
然后运行sidekiq服务:
1
|
service discourse-sidekiq start
|
13, 为Discourse建立系统服务
如果您一直跟着我的教程操作,那么您当前的目录位置为Discourse程序目录( /var/www/discourse/ )。先暂停Puma服务器:
1
|
RAILS_ENV
=production
/
snap
/
bin
/
bundle
exec
pumactl
-P
/
var
/
www
/
discourse
/
tmp
/
pids
/
puma.pid stop
|
编辑文件 /var/www/discourse/config/puma.rb , 然后分别找到下面这两行,注释掉。
1
|
pidfile
"#{APP_ROOT}/tmp/pids/puma.pid"
|
1
|
daemonize
true
|
然后新建puma-discourse后台服务。新建文件 /etc/systemd/system/discourse.service , 内容为如下:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[
Unit
]
Description =Discourse service [ Service ] Type =simple User =root PIDFile = / var / www / discourse / tmp / pids / puma.pid WorkingDirectory = / var / www / discourse Environment = RAILS_ENV =production ExecStart = / snap / bin / bundle exec puma -C config / puma.rb Restart =on-failure RestartSec = 5 [ Install ] WantedBy =multi-user.target |
然后,运行服务:
1
|
service discourse start
|
此时访问您的论坛,应当正常运行了。
14, 其他设置
论坛注册或者通知需要使用邮件系统。可以编辑 /var/www/discourse/config/discourse.conf 文件配置SMTP发信。
找到下面几行:
1
2 3 4 5 6 7 8 |
smtp_address =
smtp_port = 587 smtp_domain = smtp_user_name = smtp_password = smtp_authentication = plain smtp_enable_start_tls = true notification_email = |
填上您的邮件服务器信息即可。
我们还可以修改Discourse运行参数,减少其内存占用。编辑文件 /var/www/discourse/config/puma.rb , 更改workers和threads值。下面的值对于一个单核, 1 GB内存的VPS较为合适。
1
2 |
workers
2
threads 4 , 16 |
修改Discourse的任何配置文件后,需要重启服务。
1
|
service discourse restart
|
到这里,我们成功在Ubuntu 18.04 LTS 64 bit操作系统上安装并配置好了Discourse论坛程序。通过本教程,您还可以学习到Ruby on Rails程序通常的安装部署方法,Puma服务器的使用,Nginx反代与配置SSL, Systemd的写法等各种知识。如果您想在生产环境中使用,建议您使用Docker安装。
本文许多内容翻译自 Linuxbabe , 有删改。如果您在安装过程中遇到各种问题,欢迎留言与我讨论。本文作者为香菇肥牛,原文链接为 https://qing.su/article/install-discourse-without-docker.html ,转载需注明原文链接。谢谢!