Ubuntu Weekly Recipe

第282回Discourseでディスカッション

人間と人間が交差するとき、ディスカッションは始まる。それはネットの世界でも同じです。今回はネット上でより快適な議論を行うためのプラットフォームである「Discourse」を紹介します。

次世代ディスカッションプラットフォーム「Discourse」

人はどんな些細なネタでも他人と論争できる生き物です[1]⁠。折しもネット選挙解禁によって、ネット上での「建設的な政策論争」がこれまで以上に活発になる……可能性もゼロだとは言い切れなくもないという希望を持つことぐらいなら、ひょっとすると許されるんじゃないかという時代が到来しようとしています。

これまでのネット上での議論と言えば、MLなどのメールを使ったもの、IRCのようなチャット、フォーラムや掲示板、SNSのような各種Webサービスなどが使われています。Ubuntuの開発コミュニティも基本はIRCでの議論、広く意見を求める場合はMLという使い分けをしており、最近はGoogle+を使った公開・非公開討論も増えてきました[2]⁠。

なぜDiscourse?

今回紹介するDiscourseは、⁠100%オープンソースな、次世代ディスカッションプラットフォーム」と名乗っています。とくにディスカッションスペースとしてよく利用されるフォーラムについては、既存のフォーラムソフトウェアがインターネットの進歩に関わらずユーザビリティがそれほど変わっていないこと、FLOSSでないソフトウェアがデファクトスタンダードとして蔓延していることから、将来的にフォーラムを置き換えられる存在になることを目標としています[3]⁠。

どんなことができるの?

Discourse自体はRuby on Rails、PostgreSQL、Redisなどを使ったWebアプリケーションです。最近のソーシャルネットワークサービスで使われている機能なども取り込んで、次のようなことができます。

マルチプラットフォームに対応

IEやFirefox、Chrome、SafariといったマルチWebブラウザだけでなく、iOSやAndroidのようなモバイルOSにも対応することで、あらゆるプラットフォームで特別なアプリを用意することなくアクセスできるようになっています。

ページの自動ロード機能

旧来のフォーラムは1ページあたり何件かのコメントが表示され、続きは次のページへと移動する必要がありました。DiscourseはTwitterのタイムラインのように、ページの下端に到達すると次のコメントを自動的にロードしてくれます。

閲覧中に新しいコメントが追加された場合は、そのことがページ内部に通知されます。もちろんこれもリロードすることなく表示できます。

返信、引用だけでなくメンションによる通知機能

最近のSNSでは、書式の違いはあるものの「@名前」という形で特定の相手にメンションを飛ばすことができますが、Discourseにもこの機能が存在します。

返信や引用、メンションがあったときは、メールやページの通知領域を使って通知されます。よってフォーラムをMLのような使い方で使うことも可能です。

ソーシャルログイン機能

Discourseは、GoogleやTwitter、Facebookといった他サービスのアカウント情報を使ってログインすることができます。このためDiscourse用にアカウントを作成したりパスワードを管理する必要はありません。

より直感的な編集機能

投稿の編集部分の見た目は既存のフォーラムとそれほど違いはありません。しかしながら、編集すると即座にプレビュー画面に結果が反映されたり、ドラッグアンドドロップで画像を貼り付けられたり、URLを記述すると有名なサイトであればその内容が自動的に展開されたりと、便利な機能が最初から実装されています。編集中のデータを一時的に保存することも可能です。

REST API

最近のインターネットサービスの例に漏れず、DiscourseにもREST APIが用意されています。今はまだ開発中なためにAPIドキュメントが揃っているわけではありませんが[4]⁠、将来的にはAPIを使ったより便利なアプリケーションが開発されるかもしれません。

Discourseのサイトにはテスト用のサンドボックス環境が用意されています。さらにUbuntuでも、Ubuntu用にカスタマイズされたDiscourseテストサイトが存在します。これらを試して、Discourseの雰囲気を掴むと良いでしょう。

それではUbuntuにインストールしてみましょう

Discourseは生まれたばかりのプロジェクトなので、パッケージなどはまだ用意されていません。ただ、公式サイトに詳細なインストールガイドが用意されていますので、それに合わせてインストールしていきましょう[5]⁠。

必要なパッケージをインストール

Discourseを動かすためには、PostgreSQL 9.1、Redis 2.6、Ruby 1.9.3が必要です。そのため、これらをインストールできるUbuntuマシンを1台用意してください。もちろん物理マシンでも仮想マシンでもかまいませんし、サーバ版かデスクトップ版かは問いません。第265回のようにテスト用のUbuntuサーバを用意するのが簡単でしょう。今回はUbuntu 12.04.2 LTSで検証しましたが12.04以降であればどのリリースでも違いはないはずです。

まずは、必要なパッケージをインストールします。Rubyの環境のみRVMを使うのでここではインストールしません。メールサーバとPostgreSQLはtaskselを使ってインストールしています。

$ sudo apt-get update
$ sudo apt-get install tasksel
$ sudo tasksel install mail-server
$ sudo tasksel install postgresql-server
$ sudo apt-get install build-essential libssl-dev libyaml-dev git libtool \
    libxslt1-dev libxml2-dev redis-server libpq-dev gawk curl pngcrush

メールサーバの設定については、Ubuntu Server Guideなどを参考にしてください。今回はインストールガイドと同様に「Satellite System」を選択し、あとはそのままにしています。

Webサーバの準備

DiscourseはWebサービスなので、Webサーバが必要です。インストールガイドにはNginxとApache2両方の設定方法が記載されていますが、今回はより簡単なNginxのほうを使用します。

Ubuntu 12.04.2 LTSのNginxは若干古いので、Nginxの公式サイトに用意されているリポジトリから新しいバージョンをインストールすることにしましょう。ただし、パッケージの構成が公式リポジトリとは異なるために、まずは既存のパッケージをすべて削除する必要があります。

$ sudo apt-get remove '^nginx.*$'

$ cat <<'EOF' | sudo tee -a /etc/apt/sources.list.d/nginx.list
>
> deb http://nginx.org/packages/ubuntu/ precise nginx
> deb-src http://nginx.org/packages/ubuntu/ precise nginx
> EOF

$ curl http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install nginx

RVMを使ったRubyのインストール

前述のとおり、RubyをRVMを使ってインストールします。ちなみに、DiscourseのためだけにRVMをインストールすることも可能です。手順はインストールガイドの「Single-user installation」の項を参照してください。

$ \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
$ rvm install 2.0.0
$ gem install bundler

やっていることは、RVMをインストールしたうえで現在使っているユーザをrvmグループに追加し、Ruby 2.0.0をインストールしているだけです。rvm requirementsの段階で、他に必要なパッケージがあれば自動的にインストールされます。

Discourseのインストールと設定

次にDiscourseをインストール、設定します。インストールガイドに合わせて、Discourse用の普通のアカウント、PostgreSQLのユーザを作成し、それを使うことにしましょう。

$ sudo adduser --shell /bin/bash discourse
$ sudo adduser discourse rvm

$ sudo -u postgres createuser -s discourse
$ sudo -u postgres psql -c "alter user discourse password 'TESTDISCOURSE';"
$ sudo su - discourse

$ git clone git://github.com/discourse/discourse.git
$ cd discourse/
$ git checkout latest-release

RVMでdiscourseアカウントのRubyのバージョンを2.0.0に設定し、Discourse用に必要なGemsをインストールします。この作業は環境によって時間がかかります。

$ rvm install 2.0.0
$ gem install bundler
$ bundle install --deployment --without test

さらに細かい設定を行うために、設定のテンプレートをコピーします。

$ 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

最低限編集しなければいけないのは、以下の3つのファイルです。

database.yml

productionのusernameとpasswordのコメントアウトを解除し、PostgreSQLのアカウント名とパスワード(今回の例だとdiscourseとTESTDISCOURSE)に変更します。host_namesの値をアクセス用のドメイン名に変更します。

discourse.pill

"host to run on"を現在のホスト名に変更します。

initializers/secret_token.rb

SET_SECRET_HEREを、⁠RAILS_ENV=production rake secret」の実行結果に置き換えます。SET_SECRET_HEREが書いてあった行のコメントアウトを解除し、それ以外の行をすべてコメントアウトします。

さらにProductionのデータベースを作成し、マイグレーションとプリコンパイルを実行します。

$ 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
$ exit

Nginxの設定

最後のコマンドで一旦、discourseアカウントからログアウトしています。DiscourseのソースコードにあるNginxの設定テンプレートをコピーして、Nginxの設定を行います。また、デフォルト設定は無効化します。

$ sudo cp ~discourse/discourse/config/nginx.sample.conf /etc/nginx/conf.d/discourse.conf
$ sudo mv /etc/nginx/conf.d/default.conf{,.disabled}

Nginxの設定である/etc/nginx/nginx.confのhttpディレクティブの中のどこか好きな場所に、次の行を追加します。

server_names_hash_bucket_size 64;

さらに、/etc/nginx/conf.d/discourse.confのserver_nameをホスト名に変更します。最後に設定を再読み込みします。

$ sudo /etc/init.d/nginx reload

BluepillによるDiscourseの起動

BluepillはRubyで書かれたプロセス監視ツールです。

$ sudo su - discourse
$ 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

既にこれまでの作業でDiscourseのためのBluepillの設定は終わっているので、あとはBluepillでその設定を読み込めばDiscourseが起動します。

$ RUBY_GC_MALLOC_LIMIT=90000000 RAILS_ROOT=~/discourse \
    RAILS_ENV=production NUM_WEBS=4 bluepill --no-privileged \
    -c ~/.bluepill load ~/discourse/config/discourse.pill

さらにインストールガイドにあるように、crontabに上記の行を追加しておけば、再起動時もDiscourseが自動的に起動するようになります。

さっそくアクセスしてみましょう

あとは設定したホスト名(たとえばhttp://localhost/)にアクセスすれば、Discourseのトップページが表示されるはずです[6]⁠。

図1 初期状態のトップページ。当然、初期状態だと何もない
図1 初期状態のトップページ。当然、初期状態だと何もない

さっそくログインしてみましょう。トップページの「Log In」をクリックすると、ログイン、アカウント作成のページが表示されます。たとえば「with Google」ボタンをクリックすれば、Googleアカウントでログインできます。さらに「Create Topic」を選択して、トピックを作成してみましょう。

図2 トピックの編集。日本語も問題なく使えるし、いくつかのヘルプがツールチップとして表示される
図2 トピックの編集。日本語も問題なく使えるし、いくつかのヘルプがツールチップとして表示される
図3 トピックを作成したら、トップページも変わる
図3 トピックを作成したら、トップページも変わる

他にもいろいろ試してみると、自動リロードやインターネットサービスとの共有、ブックマーク、メンション、モデレーションなど、今風のSNSなどには標準で備わっている機能が「最初から」使えるようになっていることがわかるはずです。

それ、Jujuなら簡単にできますよ

これまで見てきたように、Discourseのインストールはとても面倒です。ちょっとローカルで試してみたいってときにこの手順書を見てしまうと、思わず「あとでやる」タスクに放り込んで忘れてしまうのが人間というもの。そんな愛すべきめんどくさがり屋さんのために、インストール手順のほぼすべてを自動化したJuju用のCharmが用意されています

Jujuの導入については第265回の2ページ目を参照してください。簡単にまとめると、次のようなステップを踏みます。

$ sudo apt-get install juju-core
$ juju generate-config -w
ここで、~/.juju/environments.yamlを編集する。
$ juju bootstrap
$ juju status

この段階でJuju用のインスタンスが1つ立ち上がった状態になります。

DiscourseとPostgreSQLをそれぞれインストールしましょう。

$ juju deploy cs:~marcoceppi/discourse
$ juju deploy postgresql

Discourseのインストールは環境によって20分ぐらいかかります[7]⁠。juju statusでdiscourseとpostgresqlのサービスのagent-statusがともにstartedになるまで待ってください[8]⁠。

次にDiscourseとPostgreSQLを関連付けます。

$ juju add-relation discourse postgresql:db-admin

おそらくこれを実行して少し待ってからstatusを確認すると、discourseサービスのほうに以下のエラーが表示されるはずです。

agent-state-info: 'hook failed: "relation-changed"'

これはinitializers/secret_token.rbの設定(もしくはの環境変数SECRET_TOKENの設定)が抜けていることによって起こる問題です。本来ならCharmを修正するか、環境変数の設定を行うのが正しいやり方ですが、今回は簡単にsecret_token.rbを編集してしまいましょう。

$ juju ssh discourse/0
(これでインスタンスにログインできる)
$ cat /etc/init/discourse.conf | grep SECRET_TOKEN
(ここでSECRET_TOKENを確認する)
$ sudo vi ~discourse/discourse/config/initializers/secret_token.rb
(「Discourseのインストールと設定」と同じように編集する)
$ exit
$ juju resolved -r discourse/0

最後のコマンドで、失敗した処理が再実行されます。最終的にagent-statusがすべてstartedになれば成功です。

最後に、このdiscourseサービスを公開します。

$ juju expose discourse

juju statusでdiscourseサービスに表示される、⁠public-address」にWebブラウザでアクセスしてみましょう。デプロイされたDiscourseが表示されるはずです。

このように、Jujuを使えば大抵のサービスは簡単にデプロイできます。本番環境として使うとなるとカスタマイズが大変かもしれませんが、よくあるサービスをとりあえずUbuntuサーバ上に用意してみるといった目的なら積極的にJujuを使っていくと良いでしょう[9]⁠。

おすすめ記事

記事・ニュース一覧