もう本当に大変で、1週間潰れました。
同じように貴重な土日を潰してしまう人が一人でも減ることを願って。
環境
目標
サブディレクトリにあるCakePHPアプリを動作させたい。
いいかえるとhttp://example.com/subdir/
にアクセスして、サーバー上の/usr/shared/nginx/example.com/subdir
にあるCakePHPアプリにアクセスしたい。
stackoverflowなどに同様の質問は沢山挙がっているのですが、どのベストアンサーも私の環境では正常に動作しませんでした。
CakePHP公式サイトのnginx設定例じゃダメなの?
ダメなんです。。。
server { listen 80; server_name www.example.com; rewrite ^(.*) http://example.com$1 permanent; } server { listen 80; server_name example.com; # root directive should be global root /var/www/example.com/public/app/webroot/; index index.php; access_log /var/www/example.com/log/access.log; error_log /var/www/example.com/log/error.log; location / { try_files $uri $uri/ /index.php?$uri&$args; } location ~ \.php$ { try_files $uri =404; include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
残念ながら、これはサーバのルートディレクトリにCakePHPを設置した場合の設定例なのです。
サブディレクトリにCakePHPを配置した場合の設定を一から考える必要があります。
CakePHP公式サイトのnginx設定例は何をやっているのか
公式サイトの設定例はそのまま利用できないものの、nginxでどう設定すればよいのかヒントになるので、詳しく見ていきます。
まず、最初のserverコンテキストで設定されているものです。
server { listen 80; server_name www.example.com; rewrite ^(.*) http://example.com$1 permanent; }
これはwww.
有りでアクセスがあった際に、www.
なしのhttp://example.com/
にリダイレクトする設定です。これはCakePHPと関係がないので、以後無視します。
後半のserverコンテキストを見ます。
server { listen 80; server_name example.com; # root directive should be global root /var/www/example.com/public/app/webroot/; index index.php; access_log /var/www/example.com/log/access.log; error_log /var/www/example.com/log/error.log; location / { try_files $uri $uri/ /index.php?$uri&$args; } location ~ \.php$ { try_files $uri =404; include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
server_name example.com;
Hostがexample.com
であるアクセスは、このコンテキストの設定で処理されることを宣言しています。
root /var/www/example.com/public/app/webroot/;
URL上のルートパスに対応するサーバ上のフルパスが設定されます。apacheにおけるDocumentRootと同じ。
locationコンテキストその1
location / { try_files $uri $uri/ /index.php?$uri&$args; }
(先ほどのrootディレクティブの設定は{}の内側全域で有効であることに注意)
ここのlocationコンテキストの動作はやや複雑。
/var/www/example.com/public/app/webroot/$uri
という静的ファイルを探す- (無ければ)
/var/www/example.com/public/app/webroot/$uri/
というディレクトリを探す (それも無ければ)
/var/www/example.com/public/app/webroot/index.php?$uri&$args
に内部リダイレクトする$uri
にはクライアントから要求のあったURLから、server_name
を取り除いた文字列が入る- 例:
http://www.example.com/xxx/yyy
にアクセスがあった場合、$uri = xxx/yyy
- 例:
$args
はURLパラメータを保持したまま内部リダイレクトするための変数
locationコンテキストその2
location ~ \.php$ { try_files $uri =404; include /etc/nginx/fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; }
locationコンテキストに~
をつけると、設定を適用したいアクセスを正規表現で指定できます。
この場合、末尾が.php
で終わるファイルへのアクセスは、このlocationコンテキストの設定が適用されます。
nginx設定例
以上を踏まえて、こうなりました。
server { listen 80; server_name example.com; root /usr/share/nginx/example.com; location / { index index.php index.html; } location ~ ^/subdir/(img|css|js|files)/(.+)$ { root /usr/share/nginx/example.com/subdir/app/webroot; try_files /$1/$2 =404; } location ~ ^/subdir/(.+\.php) { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ ^/subdir/(.*)$ { index index.php index.html; try_files /subdir/$1 /subdir/$1/ /subdir/index.php?$1&$args; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
参考資料
Nginx Community
http://wiki.nginx.org/
Nginx はどのようにリクエストを処理するか
http://nginx.org/ja/docs/http/request_processing.html
Nginx で location の判定方法と優先順位を調べる
http://server-setting.info/centos/nginx-location-check.html
nginx連載5回目: nginxの設定、その3 - locationディレクティブ
http://heartbeats.jp/hbblog/2012/04/nginx05.html