说明:本站制作的旧版中文安装指南是根据外国网友的文档制作的,当时还没有官方安装文档。后来官方发布了正式的安装文档,因此本站根据官方指南重新制作了中文安装文档。
当前版本:0.2.0,最近更新于 2013.7.8。
0 相关说明
意为“谈话”,是由 Stack Overflow 的联合创始人 Jeff Atwood 推出的下一代开源论坛程序,关于它的介绍可以看看 和 的报道。目前,网络上还没有一份详细、全面的中文 Discourse 安装指南,ofGEEK 特此整理编写本文,希望能够对需要的人有所帮助。
由于 Discourse 仍在不断更新变化之中,本指南也将随之不断调整,以适应最新的系统安装环境。更多相关信息与讨论,请访问 的 (这个讨论区就是用 Discourse 搭建而成的)。
本指南在以下环境安装成功:
- 一台 KVM VPS 服务器
- 内存 1G (Discourse 官方推荐的最小值)
- Ubuntu 12.10 x86 操作系统
1 准备安装环境
注意:为了操作的安全,不推荐直接使用 root 账户安装 Discourse,建议在 VPS 上增加一个用户(本文设为 admin,你可以任意选择喜欢的名称),专门用于安装 Discourse。本文中,VPS 的主机名即为域名 ofgeek.com,读者请根据实际情况自行修改。
1.1 登录 VPS
用 root 登录 VPS,创建新用户 admin,并将其加入 sudo 组,以获取管理员权限。(关于登录 VPS 的方法,本文不做详细介绍,如有需要请自行查阅。Mac OS X 或 Linux 用户可以直接打开终端使用 ssh 进行连接。Windows 用户推荐使用 ,非商业用途可免费使用)。
2 | $ sudo adduser admin sudo |
退出 root 账户,用 admin 账户重新登录 VPS。
更新 VPS 的操作系统:
1 | $ sudo apt-get update && sudo apt-get -y upgrade |
如果更新过程中,系统提示是否更新 grub 菜单,请选择不更新。
1.2 安装 Discourse 所需的包文件
1 | $ sudo tasksel install openssh-server |
2 | $ sudo tasksel install mail-server |
3 | $ sudo tasksel install postgresql-server |
在安装过程中,会弹出 Postfix 的配置界面,它是 Linux 系统中的邮件配置程序。如果你决定使用同一台 VPS 来发送邮件,则选择”Internet Site”,本例中,我们将使用第三方提供的邮件发送服务,所以选择“Satellite system”。然后在下一步输入你自己的域名,在本文中则是 ofgeek.com。具体的邮件设定将在下文有详细介绍。
继续安装其它所需的包文件:
1 | $ sudo apt-get -y install build-essential libssl-dev libyaml-dev git libtool libxslt-dev libxml2-dev redis-server libpq-dev gawk curl pngcrush |
1.3 设定主机名称
这里需要用到文本编辑器,你可以根据自己的喜好使用 vi、emacs 或其它,Ubuntu 12.10 系统里默认的是 nano。
在第一行下面加入你的 VPS 的 IP 和域名,本文修改成:
确认无误后,按 Ctrl+x 保存,按 y 确认后退出。
然后再修改 hostname:
1 | $ sudo nano /etc/hostname |
本文修改成:
1.4 安装最新版的 Nginx
先删除 VPS 自带的老版本 nginx(如果你的 VPS 没有安装 nginx 则无需这一步):
1 | $ sudo apt-get remove '^nginx.*$' |
更新软件源:
1 | $ cat <<'EOF' | sudo tee -a /etc/apt/sources.list |
3 | deb http://nginx.org/packages/ubuntu/ precise nginx |
4 | deb-src http://nginx.org/packages/ubuntu/ precise nginx |
加入 nginx 密钥:
1 | $ curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add - |
安装 nginx:
1 | $ sudo apt-get update && sudo apt-get -y install nginx |
1.5 安装 RVM
1 | $ \curl -s -S -L https://get.rvm.io | sudo bash -s stable |
2 | $ sudo adduser $USER rvm |
4 | $ . /etc/profile.d/rvm.sh |
如果系统报权限不够,则运行
1 | $ rvm --autolibs=read-fail requirements |
根据报告中的说明,单独安装所需的包,然后再继续安装。
1.6 安装 Ruby 2.0 和打包程序
到这里,Discourse 的安装环境就准备完成了。
2 安装 Discourse
2.1 创建 discourse 用户
按照官方的教程,我们将在 VPS 上再创建一个名为 discourse 的用户,专门用于安装 discourse 论坛。
1 | $ sudo adduser --shell /bin/bash discourse |
2 | $ sudo adduser discourse rvm |
为用户 discourse 赋予操作数据库的权限:
1 | $ sudo -u postgres createuser -s discourse |
2 | $ sudo -u postgres psql -c "alter user discourse password '[你自己设定的密码]';" |
切换到 discourse 用户:
2.2 下载并安装 discourse 源码
1 | $ git clone git://github.com/discourse/discourse.git |
3 | $ git checkout latest-release |
4 | $ bundle install --deployment --without test |
最后这一步耗时较长,请耐心等待。安装完毕后,就可以开始配置 discourse 了。
2.3 修改 Discourse 的相关配置文件
1 | $ cd ~/discourse/config |
2 | $ cp database.yml.production-sample database.yml |
3 | $ cp redis.yml.sample redis.yml |
4 | $ cp discourse.pill.sample discourse.pill |
5 | $ cp environments/production.rb.sample environments/production.rb |
2.3.1 修改 database.yml
需要修改的内容包括:
实际上,你还可以修改数据库的名称,不过这里不建议新手修改。 本文修改后的 database.yml 如下,请结合你的实际情况加以修改:
03 | database: discourse_prod |
04 | username: discourse # if using username/password auth |
05 | password: [你自己设定的密码] # if using username/password auth |
06 | # host: dbhost # if not localhost |
07 | pool: 5 # size of DB connection pool *per process* |
09 | # db_id: 0 # database ID if hosting multiple sites |
11 | - ofgeek.com # Update this to be the domain of your production site |
15 | database: discourse_test |
16 | # username: discourse_test |
17 | # password: 123123123123 |
2.3.2 修改 discourse.pill
需要修改的内容包括:
- 将 rails_root 设为 /home/discourse/discourse
- 删除# Running bluepill as a user? Use:这一行下面那行的注释符号
- 找到 if `hostname`.strip == “host to run on” 这一行,将其中的host to run on改为你自己的主机名
本文修改后的 database.yml 如下,请结合你的实际情况加以修改:
001 | rails_env = ENV['RAILS_ENV'] || "production" |
002 | rails_root = ENV['RAILS_ROOT'] || "/home/discourse/discourse" |
004 | user = ENV["DISCOURSE_USER"] || ENV['USER'] || 'discourse' |
005 | group = ENV["DISCOURSE_GROUP"] || ENV['GROUP'] || 'www-data' |
006 | num_webs = ENV["NUM_WEBS"].to_i > 0 ? ENV["NUM_WEBS"].to_i : 4 |
009 | #Bluepill.application("your_app", :foreground => true) do |app| |
011 | # Running bluepill as a user? Use: |
012 | Bluepill.application("discourse", :base_dir => ENV["HOME"] + '/.bluepill') do |app| |
014 | # Running bluepill as root? Use: |
015 | #Bluepill.application("discourse") do |app| |
020 | # getting this to work was a nightmare |
021 | # bundle exec spawns a process totally messing with the demonize option |
022 | # so we suck the environment out and set it up first |
023 | app.environment = `env -i BUNDLE_GEMFILE=#{rails_root}/Gemfile /usr/local/rvm/bin/bootup_bundle exec env`.l$ |
024 | kv = l.chomp.split('=',2) |
025 | env_hash[kv[0]] = kv[1] |
027 | end if File.exist?("/usr/local/rvm/bin/rvm") |
029 | app.environment ||= {} |
030 | app.environment['RAILS_ENV'] = rails_env |
035 | app.working_dir = rails_root |
036 | sockdir = "#{rails_root}/tmp/sockets" |
037 | File.directory? sockdir or Dir.mkdir sockdir |
038 | num_webs.times do |i| |
039 | app.process("thin-#{i}") do |process| |
040 | process.start_command = "bundle exec thin start -e production -t 0 --socket #{sockdir}/thin.#{i}.sock $ |
042 | # Alternatively, you can start with a port number instead of a socket. If you do that, then you MUST up$ |
043 | # the upstream section in the nginx config to match. |
044 | # The nginx.sample.conf file assumes you're using sockets. |
045 | # process.start_command = "bundle exec thin start -e production -t 0 -p #{9040 + i} -P #{rails_root}/t$ |
047 | process.pid_file = "#{rails_root}/tmp/pids/thin#{i}.pid" |
048 | process.start_grace_time = 30.seconds |
049 | process.stop_grace_time = 10.seconds |
050 | process.restart_grace_time = 10.seconds |
051 | process.group = "thins" |
054 | process.daemonize = false |
055 | process.stdout = process.stderr = "#{rails_root}/log/thin#{i}.log" |
060 | # app.process("thin-debug") do |process| |
061 | # process.start_command = "bundle exec thin start -e development -t 0 -p 10040 -P #{rails_root}/tmp/pid$ |
062 | # process.pid_file = "#{rails_root}/tmp/pids/thin-debug.pid" |
063 | # process.start_grace_time = 30.seconds |
064 | # process.stop_grace_time = 10.seconds |
065 | # process.restart_grace_time = 10.seconds |
066 | # process.group = "thins" |
068 | # process.gid = group |
069 | # process.daemonize = false |
070 | # process.stdout = process.stderr = "#{rails_root}/log/thin-debug.log" |
073 | app.process("sidekiq-worker") do |process| |
074 | pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid" |
076 | process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq" |
077 | process.pid_file = pidfile |
078 | process.start_grace_time = 30.seconds |
079 | process.stop_grace_time = 10.seconds |
080 | process.restart_grace_time = 10.seconds |
083 | process.daemonize = true |
086 | if `hostname`.strip == "ofgeek.com" |
087 | app.process("clockwork") do |process| |
088 | pidfile = "#{rails_root}/tmp/pids/clockwork.pid" |
090 | process.start_command = "/usr/bin/env RAILS_ENV=#{rails_env} bundle exec clockwork config/clock.rb" |
091 | process.pid_file = pidfile |
092 | process.start_grace_time = 30.seconds |
093 | process.stop_grace_time = 10.seconds |
094 | process.restart_grace_time = 10.seconds |
096 | # process.restart_grace_time = 10.seconds |
097 | # process.group = "thins" |
099 | # process.gid = group |
100 | # process.daemonize = false |
101 | # process.stdout = process.stderr = "#{rails_root}/log/thin-debug.log" |
104 | app.process("sidekiq-worker") do |process| |
105 | pidfile = "#{rails_root}/tmp/pids/sidekiq-worker.pid" |
107 | process.start_command = "/usr/bin/env PIDFILE=#{pidfile} RAILS_ENV=#{rails_env} bundle exec sidekiq" |
108 | process.pid_file = pidfile |
109 | process.start_grace_time = 30.seconds |
110 | process.stop_grace_time = 10.seconds |
111 | process.restart_grace_time = 10.seconds |
114 | process.daemonize = true |
117 | if `hostname`.strip == "ofgeek.com" |
118 | app.process("clockwork") do |process| |
119 | pidfile = "#{rails_root}/tmp/pids/clockwork.pid" |
121 | process.start_command = "/usr/bin/env RAILS_ENV=#{rails_env} bundle exec clockwork config/clock.rb" |
122 | process.pid_file = pidfile |
123 | process.start_grace_time = 30.seconds |
124 | process.stop_grace_time = 10.seconds |
125 | process.restart_grace_time = 10.seconds |
2.3.3 修改 secret_token.rb 文件
为了保证站点的安全,需要生成密钥会话令牌。
将生成的密钥记下来,打开 config/initializers/secret_token.rb 文件
1 | $ nano config/initializers/secret_token.rb |
执行以下步骤:
- 清空该文件中的所有已有内容
- 将下面这行代码拷贝到该文件中,用刚才生成的密钥代替 [TOKEN] 部分
1 | Discourse::Application.config.secret_token = "[TOKEN]" |
2.3.4 修改 production.rb 文件,设定邮件发送方式
Discourse 中,系统邮件是非常重要的,它涉及到激活用户、修改邮箱、修改密码等多项功能。如果你希望用 VPS 本身发送邮件,则需安装 sendmail(具体设置方法请自行查阅):
1 | $ sudo apt-get install sendmail |
如果你已经有了邮件服务器,则可以通过 smtp 服务发送系统邮件,本文推荐使用 提供的邮件发送服务,对于规模不大的论坛而言,它每个月 12000 封的免费方案就够用了。注册通过后,去 mandrillapp 后台生成一个 smtp 密钥。
修改 config/environments/production.rb 文件:
1 | $ nano config/environments/production.rb |
修改其中有关邮件发送的部分,本文中如下:
01 | # you may use other configuration here for mail eg: sendgrid |
03 | config.action_mailer.delivery_method = :smtp |
04 | config.action_mailer.smtp_settings = { |
05 | :address => "smtp.mandrillapp.com", |
07 | :domain => 'ofgeek.com', |
08 | :user_name => '[你在mandillapp的用户名]', |
09 | :password => '[你在mandillapp生成的smtp密钥]', |
10 | :authentication => 'login', |
11 | :enable_starttls_auto => true } |
13 | #config.action_mailer.delivery_method = :sendmail |
14 | #config.action_mailer.sendmail_settings = {arguments: '-i'} |
2.4 初始化数据库
2 | $ createdb discourse_prod |
3 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate |
4 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile |
2.5 配置服务环境
2.5.1 配置 Nginx
切换到 admin 用户
编辑 nginx.conf
1 | $ sudo nano /etc/nginx/nginx.conf |
在 http 部分加入下面一行:
1 | server_names_hash_bucket_size 64; |
如果该 VPS 上只有 discourse 一项服务,则禁用默认的 nginx 站点:
1 | $ sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled |
编辑 discourse.conf
1 | $ sudo cp ~/discourse/discourse/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf |
2 | $ sudo nano /etc/nginx/conf.d/discourse.conf |
将 server_name 改为你自己的主机名。
根据实际情况修改 socket 和 root 的路径,本文中如下:
02 | server unix:/home/discourse/discourse/tmp/sockets/thin.0.sock; |
03 | server unix:/home/discourse/discourse/tmp/sockets/thin.1.sock; |
04 | server unix:/home/discourse/discourse/tmp/sockets/thin.2.sock; |
05 | server unix:/home/discourse/discourse/tmp/sockets/thin.3.sock; |
13 | gzip_types application/json text/css application/x-javascript; |
15 | server_name ofgeek.com; |
22 | root /home/discourse/discourse/public; |
24 | location ~ ^/t\/[0-9]+\/[0-9]+\/avatar { |
26 | add_header Cache-Control public; |
30 | location ~ ^/assets/ { |
32 | add_header Cache-Control public; |
37 | proxy_set_header X-Real-IP $remote_addr; |
38 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; |
39 | proxy_set_header X-Forwarded-Proto $scheme; |
40 | proxy_set_header Host $http_host; |
42 | # If the file exists as a static file serve it directly without |
43 | # running all the other rewite tests on it |
44 | if (-f $request_filename) { |
48 | if (!-f $request_filename) { |
重启 nginx 服务:
1 | $ sudo /etc/init.d/nginx reload |
2.5.2 安装并配置 Bluepill
Discourse 官方使用 bluepill 来管理所有 discourse 的相关服务,省去了很多麻烦。
切换到 discourse 用户
安装并配置 bluepill
2 | $ echo 'alias bluepill="NOEXEC_DISABLE=1 bluepill --no-privileged -c ~/.bluepill"' >> ~/.bash_aliases |
3 | $ rvm wrapper $(rvm current) bootup bluepill |
4 | $ rvm wrapper $(rvm current) bootup bundle |
注销并重新登录以激活 bluepill
2 | $ ssh discourse@ofgeek.com |
到这里,discourse 就安装完成了,可以通过下面的命令行来启动:
1 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=4 bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill |
为了让 discourse 每次开机就能自动运行,还需要在 crontab 里写入 bluepill 服务:
在其中写入下面一行:
1 | RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=4 /usr/local/rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill |
2.6 创建管理员
登录你的 discourse 论坛地址,并注册一个用户,本文中注册的邮件地址为 admin@ofgeek.com。
然后再次用 discourse 用户登录 VPS,执行以下命令:
1 | $ ssh discourse@ofgeek.com |
3 | $ RAILS_ENV=production bundle exec rails c |
4 | > me = User.find_by_username_or_email('admin@ofgeek.com') |
2.7 启用中文支持
目前,Discourse 已经可以支持中文界面,使用管理员账户登录后,点击右上角的管理员名称进入设置界面,然后再点击右上角的小扳手 Admin 进入系统管理界面,在第二项 Settings 中,把 default_locale 从默认的 en 更改为 zh_CN,然后返回论坛主界面,按 Ctrl+F5 刷新浏览器缓存,中文界面就出来了。
3 更新
鉴于 discourse 更新很快,建议每隔几天就执行一次更新。
用 discourse 用户登录 VPS,执行以下命令:
01 | $ ssh discourse@ofgeek.com |
07 | $ bundle install --without test --deployment |
08 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake db:migrate |
09 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ENV=production rake assets:precompile |
如果启动失败并出现重试,则按 Ctrl+C 中止,然后执行以下两条命令重启 bluepill 服务:
2 | $ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse RAILS_ENV=production NUM_WEBS=4 /usr/local/rvm/bin/bootup_bluepill --no-privileged -c ~/.bluepill load ~/discourse/config/discourse.pill |
4 致谢
本指南基于以下资源创建,特此表示感谢:
- Discourse 官方。
- Christopher Baus 的 Discourse 。
- Lee Dohm 的 Discourse 。
- surrealroad 的 Discourse 。
后面再用centos安装了一下,基本差不多,天不遂人愿啊,vps提供商提供的centos好用些。
弄了个论坛在: itbbs.uwetech.com