zt discourse安装以及本地oauth认证接入

https://www.idefs.com/recorddiscourse-installation-as-well-as-local-access-oauth-authentication-1.html

Discourse是一个“下一代,为下个十年互联网所打造的百分百开源讨论平台。”,由问答网站StackoverflowStackExchange的联合创始人,同时也是著名博客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

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注