https://www.idefs.com/recorddiscourse-installation-as-well-as-local-access-oauth-authentication-1.html
Discourse是一个“下一代,为下个十年互联网所打造的百分百开源讨论平台。”,由问答网站Stackoverflow和StackExchange的联合创始人,同时也是著名博客Coding Horror的博主 Jeff Atwood创造。
在实际使用中,Discourse需要和本地现有的用户系统整合。目前Discourse并没有提供解决方案。
我们通过oauth2的plugin,搭建oauth2服务器实现了Discourse和用户系统的整合,并将整合代码开源。
本文由云计算组长朱劲寿贡献。
1.0 系统环境:
uname -a
Linux dev2 3.5.0-23-generic #35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
1.1 使用非root账号登陆(安全起见,不建议使用root),如果没有,自行创建。
sudo adduser bistu sudo adduser bistu sudo
1.2 更新linux
sudo apt-get update && sudo apt-get -y upgrade
1.3 安装 Discourse 所需的包文件
sudo tasksel install openssh-server
sudo tasksel install mail-server
sudo tasksel install postgresql-server
安装邮件服务的时候,选择“Satellite system” 或者“Internet Site” ,读者自己决定 ,然后在下一步输入你自己的域名,我用的是d.iflab.org
继续安装其它所需的包文件:
sudo apt-get -y install build-essential libssl-dev libyaml-dev git libtool libxslt-dev libxml2-dev redis-server libpq-dev gawk curl pngcrush
果你希望用 linux 本身发送邮件,则需安装 sendmail(具体设置方法请自行查阅):
sudo apt-get install sendmail
1.4 设定主机名称修改hosts:
bistu@Discourse:~$ cat /etc/hostname
Discourse
cat /etc/hosts
127.0.0.1 localhost Discourse
222.249.250.91 Discourse d.bistu.edu.cn d.iflab.org
1.5 安装最新版的 Nginx
更新软件源:
cat <<'EOF' | sudo tee -a /etc/apt/sources.list
deb https://nginx.org/packages/ubuntu/ precise nginx
deb-src https://nginx.org/packages/ubuntu/ precise nginx
EOF
加入 nginx 密钥:
curl https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
安装nginx :
sudo apt-get update && sudo apt-get -y install nginx
1.6 安装RVM
\curl -s -S -L https://get.rvm.io | sudo bash -s stable
sudo adduser $USER rvm
newgrp rvm
. /etc/profile.d/rvm.sh
rvm requirements
1.7安装 Ruby 2.0 和打包程序
rvm install 2.0.0
gem install bundler
2.安装Discourse
2.1 创建discourse用户,专门用于安装 discourse 论坛。
sudo adduser --shell /bin/bash discourse
sudo adduser discourse rvm
为用户 discourse 赋予操作数据库的权限:
sudo -u postgres createuser -s discourse
sudo -u postgres psql -c "alter user discourse password 'your password';"
新建www目录并赋予discourse权限
sudo mkdir /var/www
sudo chown discourse.discourse /var/www
切换到 discourse 用户:
sudo su - discourse
2.2下载并安装 discourse 源码
cd /var/www
git clone git://github.com/discourse/discourse.git
cd discourse
git checkout latest-release
bundle install --deployment --without test
最后这一步耗时较长,请耐心等待,大家可以更换ruby的源。安装完毕后,就可以开始配置 discourse 了。
2.3 修改 Discourse 的相关配置文件
cd discourse/config
cp database.yml.production-sample database.yml
cp redis.yml.sample redis.yml
cp discourse.pill.sample discourse.pill
cp environments/production.rb.sample environments/production.rb
2.3.1 修改 database.yml
nano database.yml
需要修改的内容包括:
用户名
密码
主机名
实际上,你还可以修改数据库的名称,不过这里不建议新手修改。 本文修改后的 database.yml 如下,请结合你的实际情况加以修改:
production:
adapter: postgresql
database: discourse_prod
username: discourse # if using username/password auth
password: [你自己设定的密码] # if using username/password auth
# host: dbhost # if not localhost
pool: 5 # size of DB connection pool *per process*
timeout: 5000
# db_id: 0 # database ID if hosting multiple sites
host_names:
- d.iflab.org # Update this to be the domain of your production site
test:
adapter: postgresql
database: discourse_test
# username: discourse_test
# password: 123123123123
min_messages: warning
host: localhost
pool: 5
timeout: 5000
host_names:
- test.localhost
2.3.2 修改 discourse.pill
nano discourse.pill
需要修改的内容包括:
将 rails_root 设为 /var/www/discourse
删除# Running bluepill as a user? Use:这一行下面那行的注释符号
本文修改后的 discourse.pill 如下,请结合你的实际情况加以修改:
rails_env = ENV['RAILS_ENV'] || "production"
rails_root = ENV['RAILS_ROOT'] || "/var/www/discourse"
user = ENV["DISCOURSE_USER"] || ENV['USER'] || 'discourse'
group = ENV["DISCOURSE_GROUP"] || ENV['GROUP'] || 'www-data'
num_webs = ENV["NUM_WEBS"].to_i > 0 ? ENV["NUM_WEBS"].to_i : 4
# to debug use
#Bluepill.application("your_app", :foreground => true) do |app|
# Running bluepill as a user? Use:
Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |app|
# Running bluepill as root? Use:
#Bluepill.application("discourse") do |app|
# getting this to work was a nightmare
# bundle exec spawns a process totally messing with the demonize option
# so we suck the environment out and set it up first
bootup_bundle = [ "#{ENV['HOME']}/.rvm/bin/rvm/bootup_bundle",
"/usr/local/rvm/bin/rvm/bootup_bundle",
`which bootup_bundle`.strip,
].each do |location|
if File.exist? location
break location
end
end
# XXX if none match, bootup_bundle is set to the array
if bootup_bundle
app.environment = `env -i BUNDLE_GEMFILE=#{rails_root}/Gemfile #{bootup_bundle} exec env`.lines.inject({}) do |env_hash,l|
kv = l.chomp.split('=',2)
env_hash[kv[0]] = kv[1]
env_hash
end
end
app.environment ||= {}
# Load .env file if there is one
if File.exist? "#{rails_root}/.env"
File.read("#{rails_root}/.env").split("\n").each do |l|
kv = l.chomp.split('=',2)
app.environment[kv[0]] = kv[1]
end
end
# Force RAILS_ENV to the value specified in the environment of the bluepill invocation
app.environment['RAILS_ENV'] = rails_env
app.gid = group
app.uid = user
app.working_dir = rails_root
sockdir = "#{rails_root}/tmp/sockets"
File.directory? sockdir or FileUtils.mkdir_p sockdir
num_webs.times do |i|
app.process("thin-#{i}") do |process|
process.start_command = "bundle exec thin start -e production -t 0 --socket #{sockdir}/thin.#{i}.sock --pid #{rails_root}/tmp/pids/thin#{i}.pid --log #{rails_root}/log/thin-#{i}.log --daemonize"
# Alternatively, you can start with a port number instead of a socket. If you do that, then you MUST update
# the upstream section in the nginx config to match.
# The nginx.sample.conf file assumes you're using sockets.
# process.start_command = "bundle exec thin start -e production -t 0 -p #{9040 + i} -P #{rails_root}/tmp/pids/thin#{i}.pid -d"
process.pid_file = "#{rails_root}/tmp/pids/thin#{i}.pid"
process.start_grace_time = 30.seconds
process.stop_grace_time = 10.seconds
process.restart_grace_time = 10.seconds
process.group = "thins"
process.uid = user
process.gid = group
process.daemonize = false
process.stdout = process.stderr = "#{rails_root}/log/thin#{i}.log"
# Thanks to: https://www.garrensmith.com/2012/09/24/Staying-up-with-Unicorn-Upstart-Bluepill.html
# If the amount of memory is exceeded 3 times out of 5, restart
process.checks :mem_usage, :every => 1.minutes, :below => 750.megabytes, :times => [3, 5]
end
end
#debug instance
# app.process("thin-debug") do |process|
# process.start_command = "bundle exec thin start -e development -t 0 -p 10040 -P #{rails_root}/tmp/pids/thin-debug.pid -l #{rails_root}/log/thin-debug.log" -d"
# process.pid_file = "#{rails_root}/tmp/pids/thin-debug.pid"
# process.start_grace_time = 30.seconds
# process.stop_grace_time = 10.seconds
# process.restart_grace_time = 10.seconds
# process.group = "thins"
# process.uid = user
# process.gid = group
# process.daemonize = false
# process.stdout = process.stderr = "#{rails_root}/log/thin-debug.log"
# end
app.process("sidekiq-worker") do |process|
pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid"
process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq -L #{rails_root}/log/sidekiq.log"
process.pid_file = pidfile
process.start_grace_time = 30.seconds
process.stop_grace_time = 10.seconds
process.restart_grace_time = 10.seconds
process.uid = user
process.gid = group
process.daemonize = true
end
end
2.3.3 修改 secret_token.rb 文件
为了保证站点的安全,需要生成密钥会话令牌。
cd /var/www/discourse
rake secret
将生成的密钥记下来,打开 config/initializers/secret_token.rb 文件
nano config/initializers/secret_token.rb
执行以下步骤:
清空该文件中的所有已有内容
将下面这行代码拷贝到该文件中,用刚才生成的密钥代替 [TOKEN] 部分
Discourse::Application.config.secret_token = "[TOKEN]"
2.3.4 修改 production.rb 文件,设定邮件发送方式
Discourse 中,系统邮件是非常重要的,它涉及到激活用户、修改邮箱、修改密码等多项功能。
如果你已经有了邮件服务器,则可以通过 smtp 服务发送系统邮件:
修改 config/environments/production.rb 文件:
nano config/environments/production.rb
修改其中有关邮件发送的部分,本文中如下:
# you may use other configuration here for mail eg: sendgrid
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "yours",
:port => 25,
:domain => 'd.iflab.org',
:user_name => 'iflab',
:password => 'yours',
:authentication => 'plain',
:enable_starttls_auto => true }
if ENV.key?('SMTP_URL')
config.action_mailer.smtp_settings = begin
uri = URI.parse(ENV['SMTP_URL'])
params = {
:address => uri.host,
:port => uri.port,
:domain => (uri.path || "").split("/")[1],
:user_name => uri.user,
:password => uri.password,
:authentication => 'plain',
:enable_starttls_auto => true
}
CGI.parse(uri.query || "").each {|k,v| params[k.to_sym] = v.first}
params
rescue
raise "Invalid SMTP_URL"
end
else
config.action_mailer.delivery_method = :sendmail
config.action_mailer.sendmail_settings = {arguments: '-i'}
end
2.4 初始化数据库:
cd /var/www/discourse
createdb discourse_prod
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile
2.5 配置服务环境
2.5.1 配置 Nginx
切换到 bistu 用户
sudo su - bistu
编辑 nginx.conf
sudo nano /etc/nginx/nginx.conf
在 http 部分加入下面一行:
server_names_hash_bucket_size 64;
如果该linux 上只有 discourse 一项服务,则禁用默认的 nginx 站点:
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled
编辑 discourse.conf
sudo cp /var/www/discourse/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf
sudo nano /etc/nginx/conf.d/discourse.conf
将 server_name 改为你自己的主机名。
根据实际情况修改 socket 和 root 的路径,本文中如下:
upstream discourse {
server unix:/var/www/discourse/tmp/sockets/thin.0.sock;
server unix:/var/www/discourse/tmp/sockets/thin.1.sock;
server unix:/var/www/discourse/tmp/sockets/thin.2.sock;
server unix:/var/www/discourse/tmp/sockets/thin.3.sock;
}
server {
listen 80;
gzip on;
gzip_min_length 1000;
gzip_types application/json text/css application/x-javascript;
server_name d.iflab.org;
sendfile on;
keepalive_timeout 65;
location / {
root /var/www/discourse/public;
location ~ ^/t\/[0-9]+\/[0-9]+\/avatar {
expires 1d;
add_header Cache-Control public;
add_header ETag "";
}
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
# If the file exists as a static file serve it directly without
# running all the other rewite tests on it
if (-f $request_filename) {
break;
}
if (!-f $request_filename) {
proxy_pass https://discourse;
break;
}
}
}
重启 nginx 服务:
sudo /etc/init.d/nginx reload
2.5.2 安装并配置 Bluepill
Discourse 官方使用 bluepill 来管理所有 discourse 的相关服务,省去了很多麻烦。
切换到 discourse 用户
sudo su - discourse
安装并配置 bluepill
gem install bluepill
echo 'alias bluepill="NOEXEC_DISABLE=1 bluepill --no-privileged -c ~/.bluepill"' >> ~/.bash_aliases
rvm wrapper $(rvm current) bootup bluepill
rvm wrapper $(rvm current) bootup bundle
注销并重新登录以激活 bluepill
logout
ssh discourse@localhost
到这里,discourse 就安装完成了,可以通过下面的命令行来启动:
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=/var/www/discourse RAILS_ENV=production NUM_WEBS=4 bluepill --no-privileged -c ~/.bluepill load /var/www/discourse/config/discourse.pill
为了让 discourse 每次开机就能自动运行,还需要在 crontab 里写入 bluepill 服务:
crontab -e
@reboot RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=/var/www/discourse RAILS_ENV=production NUM_WEBS=4 /usr/local/rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load /var/www/discourse/config/discourse.pill
2.6 创建管理员
登录你的 discourse 论坛地址,并注册一个用户,本文中注册的邮件地址为 [email protected]。
然后再次用 discourse 用户登录 linux,执行以下命令:
ssh [email protected]
cd /var/www/discourse
RAILS_ENV=production bundle exec rails c
me = User.find_by_username_or_email('[email protected]')
me.activate
me.admin = true
me.save
2.7 启用中文支持
目前,Discourse 已经可以支持中文界面,使用管理员账户登录后,点击右上角的管理员名称进入设置界面,然后再点击右上角的小扳手 Admin 进入系统管理界面,在第二项 Settings 中,把 default_locale 从默认的 en 更改为 zh_CN,然后返回论坛主界面,按 Ctrl+F5 刷新浏览器缓存,中文界面就出来了。
3 更新
鉴于 discourse 更新很快,建议每隔几天就执行一次更新。
用 discourse 用户登录 linux,执行以下命令:
ssh [email protected]
bluepill stop
cd /var/www/discourse
git checkout master
git pull
git fetch --tags
bundle install --without test --deployment
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile
bluepill start
如果启动失败并出现重试,则按 Ctrl+C 中止,然后执行以下两条命令重启 bluepill 服务:
bluepill quit
RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=/var/www/discourse RAILS_ENV=production NUM_WEBS=4 /usr/local/rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load /var/www/discourse/config/discourse.pill