Top > Blog > Linux > Tool

Passenger がシンボリックリンクを解決してくれない

Redmine を 1.3.2 から 1.4.1 にアップグレードしました。
アップグレードはいつも Redmine.JP の記述を参考にしながらやらせて頂いてますが、Redmine 1.4 系のアップグレード手順はまだ用意していないそうなので、

の両方を参照しながら作業しました。が、表題のとおり、DocumentRoot にシンボリックリンクを指定すると Rails が起動しなかったので、対応内容をまとめておきます。

設定

おおむね Redmine.JP の手順書のとおりですが、mod_passenger の読み込み用設定ファイルは、

passenger-install-apache2-module --snippet > /etc/httpd/conf.d/passenger.conf

とするとコマンド1つで作成出来るので、非常に便利です。Apache を再起動すると、Passenger 関連のプロセスが立ち上がるので、これでOK。

次にバーチャルホスト内での DocumentRoot の設定ですが、以前は、

DocumentRoot /var/www/redmine-1.3.2/public

としていたものの、アップグレードのたびにここを書き換えるのも面倒なので、新しくインストールした redmine-1.4.1/public にシンボリックリンクを張る事にしました。

ln -s redmine-1.4.1/public redmine

で、以下のようになります。

lrwxrwxrwx  1 root   root     20 Apr 23 09:12 redmine -> redmine-1.4.1/public
drwxrwxr-x 15 apache apache 4096 Mar 12 17:25 redmine-1.3.2
drwxrwxr-x 16 apache apache 4096 Apr 23 09:05 redmine-1.4.1

作成したシンボリックリンクを DocumentRoot に指定します。

DocumentRoot /var/www/redmine

Redmine.JP の手順書にもありますが、上記の設定で、無事に Redmine が起動するはず……が、しませんでした…ええっ!?

設定した URL にアクセスしても、403 Forbidden が返ってきます。Apache のエラーログには

Directory index forbidden by Options directive: /var/www/redmine/

と出力してあって、これは Options -Indexes を指定しているから、ディレクトリ一覧の出力はできませんよ、と言っているのですが…ということは /var/www/redmine/index.html にアクセスしようとしてそのファイルが無かったから、ディレクトリ一覧を出力しようとしたんだけど許可されてないし…、という事ですね。

シンボリックリンクの確認

念の為、Apache でシンボリックリンクが解決できている事を確認します。

  1. SELinux が Disabled になっているかどうか(getenforce コマンドを叩きます)
    # getenforce
    Disabled
    
    OKですね。
  2. Options ディレクティブ
    Options FollowSymLinks
    
    こちらも問題なし。<Directory /> の中なので、どのディレクトリにも効いていますし、/var/www だけ除外されているという設定も見当たりません。
  3. 実ディレクトリの中に index.html を作成してみる
    echo TEST > /var/www/redmine-1.4.1/public/index.html
    
    ブラウザでアクセスすると、「TEST」と表示されます。

やはり問題なさそうです。

Passenger の確認

Apache 側には問題ありませんでした。なので、次は Passenger です。ステータスを確認します。

# passenger-status
*** Cleaning stale folder /tmp/passenger.1.0.10981
----------- General information -----------
max      = 6
count    = 0
active   = 0
inactive = 0
Waiting on global queue: 0

----------- Application groups -----------

「Application groups」の下に何も出力されていません。Rails アプリケーションが読み込まれていないですね…試しに

DocumentRoot /var/www/redmine-1.4.1/public

とすると、ちゃんと Redmine が起動しました!ということは、Passenger がシンボリックリンクを解決出来ていない可能性大…(何をいまさら…)

ここでやっとこ Passenger のドキュメントを確認してみました。9.3. How Phusion Passenger detects whether a virtual host is a web applicationに、

Note that Phusion Passenger does not resolve any symlinks in the document root path by default since version 2.2.0 — in contrast to versions earlier than 2.2.0, which do resolve symlinks. So for example, suppose that your DocumentRoot points to /home/www/example.com, which in turn is a symlink to /webapps/example.com/public. In versions earlier than 2.2.0, Phusion Passenger will check whether /webapps/example.com/config/environment.rb exists because it resolves all symlinks. Phusion Passenger 2.2.0 and later however will check for /home/www/config/environment.rb. This file of course doesn’t exist, and as a result Phusion Passenger will not activate itself for this virtual host, and you’ll most likely see an Apache mod_dirindex directory listing.

簡単に一言で言うと、「Passenger 2.2.0 以降のバージョンでは、シンボリックリンクを解決しません。それより前のバージョンは解決してたけどね」という事です。ああ、なるほど。

詳細は前述のドキュメントに書いてありますが、 たとえば DocumentRoot が /var/www/redmine だとすると、そのディレクトリが「Railsアプリケーションなのかどうか」を確認するために、Passenger は /var/www/config/environment.rb を探しに行くようです。本来は <Railsアプリルート>/public が公開ディレクトリなのであって、その public ディレクトリにシンボリックリンクを張っているので階層構造が変わってしまい、あるはずの ../config/environment.rb が無いから Rails アプリケーションではない、と判断したもよう。

redmine-1.4.1/public ← ここが DocumentRoot なら
redmine-1.4.1/config ← ディレクトリを1つ遡って config/ ディレクトリを探し
redmine-1.4.1/config/environment.rb ← environment.rb があるので Rails !

redmine ← ここが DocumentRoot だけど
config ← このディレクトリが無いので、Rails じゃない!

なぜ仕様が変わったのかは分かりませんが、ドキュメントにも書いてあるとおり、 PassengerAppRoot ディレクティブで /var/www/redmine-1.4.1 と指定すればこの問題は解決します。

PassengerAppRoot /var/www/redmine-1.4.1

だが、しかし!そんな事するくらいなら DocumentRoot で /var/www/redmine-1.4.1/public と書けば良い話であって、当初の「アップグレードしても、ちょっとだけ楽をしたい!」という願望は叶いません、叶いません…

もうちょっとドキュメントを読むと、 PassengerResolveSymlinksInDocumentRoot という長い名前のディレクティブがあって、これの初期値は off なようなので、on にして、httpd.conf (passenger.conf) に追記します。

echo "PassengerResolveSymlinksInDocumentRoot on" >> /etc/httpd/conf.d/passenger.conf

ファイルを見るとこうなっています。

PassengerResolveSymlinksInDocumentRoot on

これで Apache を再起動すると、DocumentRoot にシンボリックリンクを指定したままで、無事に Redmine を起動できました。

全3コメント

  1. […] Passenger がシンボリックリンクを解決してくれない […]

  2. […] ◆参考サイト Redmine.JP さくらのVPS (Ubuntu12.04) にRedmine(2.4.2.stable)をインストールする Ubuntu12.04にredmineをインストールする Passengerがシンポジックリンクを解決してくれない […]

Ubuntu12.04 Redmine環境設定 | Blog for Game Science Department of Trident College へのコメント