tDiaryを Nginx + Unicorn + さくらVPSで動かした (2)
先日の日記の続き。Nginx + Unicorn で tDiary を動かしてみたものの、フィード (index.rdf) が表示されない問題があった。なので、今回は静的コンテンツをRack環境でどう扱うかという話。
現状のおさらい
- tDiary では日記の更新時にプラグイン (makerss.rb) がフィードを書き出している
- tDiary を CGI/FastCGI で動作させたときには Web サーバがフィードを返している
- tDiary を Rack 環境で動かしたときは、リクエストはすべて AP サーバに飛ばす設定になっている
- JavaScriptやCSSは tDiary 側で assets という仕組みを使って返すが、フィードは対象外
対応方針
- Webサーバ (nginx) がフィードを返す
- APサーバ (unicorn) でフィードを返す
案1はCGI/FastCGIと同じ方式。APサーバを介さないことで、速度的には有利になる*1。案2は APサーバ単体で動作させられるのがメリット。
前提: フィードのファイルをどこに書き出すか
CGI/FastCGIで動かす場合はtDiaryのルートディレクトリに書き出しているけど、これはtDiaryのルートディレクトリとWebサーバの公開ディレクトリが一致しているから。つまり http://example.com/diary/index.rb
へのアクセスは /DocumentRoot/diary/index.rb
にマッピングされるし、 http://example.com/diary/index.rdf
へのアクセスは /DocumentRoot/diary/index.rdf
へマッピングされる。
一方、 Rack 経由で動かす場合は、tDiaryのルートディレクトリとWebサーバの公開ディレクトリは一致しない*2。そこで、Rails系のお作法と同じように、 public
ディレクトリを静的コンテンツの置き場所とする。なお、JavaScriptやCSSなどは前述の通り assets によって tDiary がよしなにしてくれる。
makerssプラグインの説明に従って、フィードを public ディレクトリに書き出すように設定する。
@options['makerss.file'] = 'public/'index.rdf'
@options['makerss.no_comments.file'] = 'public/no_comments.rdf'
案1. Webサーバ (nginx) がフィードを返す
見直し前の Nginx 設定ファイルはこれ(一部抜粋)。
server_name www.machu.jp;
location ~ ^/diary/ {
rewrite ([0-9\-]+)\.html$ /diary/index.rb?date=$1 last;
proxy_pass http://www.machu.jp;
}
これだと /diary/ 以下のアクセスがすべて Unicorn 側へ飛んでしまう。
代わりに、まずは public/ ディレクトリにファイルが存在するかどうかをチェックし、存在しない場合のみに Unicorn 側へ飛ばすように設定する。
ポイントは try_files $uri @unicorn
の設定。 $uri に相当するファイルがなければ、 @unicorn の設定へ飛ぶ。
location ~ ^/diary/ {
try_files $uri @unicorn;
}
location @unicorn {
rewrite /diary/([0-9\-]+)\.html$ /diary/index.rb?date=$1 last;
proxy_pass http://www.machu.jp;
}
あとは、 tdiary-core/public
ディレクトリを Nginx 側の DocumentRoot/diary
にリンクを張っておけばよい。
案2. 2. APサーバ (unicorn) でフィードを返す
/diary/index.rdf
へのリクエストが来た場合に、 tdiary-core/public/index.rdf
を返すように config.ru を修正した。Rack::CascadeとRack::Fileの組み合わせがポイント。
map "#{base_dir}/" do
run Rack::Cascade.new([
Rack::File.new("./public/"),
TDiary::Application.new(:index)
])
end
pull requestを送ったので、最新のGitリポジトリには修正が取り込まれている。
まとめ
- 静的ファイルは public フォルダに置くのが原則
- Webサーバ側 (Nginx) でフィードを返す場合は try_files を使う
- APサーバ側 (Unicorn) でフィードを返す場合は Rack::CascadeとRack::Fileを使う
なお、 Heroku などの PaaS 上でフィードを扱う場合には、そもそも静的コンテンツとしてフィードを生成しているところから見直す必要がある。