nginxで悪戦苦闘。

nginxというのが軽い、速いらしいのでhttpdにはapacheを使わずにそちらを使うことにした。
で、慣れないので嵌ったという話。


目標:
ルートにwordpressを設置。
MySQL管理用のphpmyadminとメール管理用のpostfixadminをそれぞれ
/phpmyadin/
/postfixadmin/
以下で動作するようにしたい。

各々の実体は
/usr/local/share/wordpress
/usr/share/phpmyadmin
/usr/local/share/postfixadmin
(phpmyadminだけwheezyのパッケージを使用した。)

必要なパッケージはaptitudeからインストールした。

aptitude install nginx postfixadmin

あとはnginxでphp等のスクリプトを実行するためにはfastcgi経由で動作させないといけないそうなので
php5-fpmパッケージをインストールする。

あとは/etc/nginx/site-available/defaultを、ほげほげしてあげればいいのだけど、
locationディレクティブの評価順やら、fastcgiに渡されるパラメータがどう操作されるのかがイメージできなくて嵌った。
自分なりに色々調べた結果、以下のように解釈した。誤解してた場合は一報いただけるとありがたい。

locationディレクティブの評価方法と順序。比較対象はrequest

locationディレクティブの構文は

 location [プレフィックス] uriパス {
  [locationコンテキスト]
}

となっている。
プレフィックスには以下の種類がある。

種類 比較方法
なし 前方一致
= 完全一致
^~ 前方一致
~ 正規表現(大小文字区別有り)
~* 正規表現(大小文字区別無し)

また、locationコンテキスト内にlocationディレクティブを記述することで入れ子にできる。

nginxは要求された正規化uriとlocationディレクティブのuriパスを比較、評価し、
評価の一番高いディレクティブを要求に対して採用する。

評価順・方法は
=を評価し、一致したディレクティブがあれば採用する。
^~を評価し、マッチしたディレクティブがあれば採用する。複数ある場合は最長マッチしたものを採用する。
~を評価し、マッチしたディレクティブがあれば採用する。複数ある場合は最長マッチしたものを採用する。
~*を評価し、マッチしたディレクティブがあれば採用する。複数ある場合は最長マッチしたものを採用する。
(なし)を評価し、マッチしたディレクティブがあれば採用する。複数ある場合は最長マッチしたものを採用する。
どれとも一致しなかった場合は404を返す。

この理解(誤解)で、なんとなくだがlocationディレクティブの記述方法が見えてきた。

次、fastcgiに渡すパラメータがどう操作されるか

fastcgi側で実行されるスクリプトの実体パスは

fastcgi_param SCRIPT_FILENAME hogehoge;

とhogehogeを指定することで、nginx->fastcgiに渡されるようである。
では、hogehogeをどうするか?
色々調べていると、
locationディレクティブのuriのスクリプトファイル部分を正規表現の()で区切り、

fastcgi_param SCRIPT_FILENAME path/to$1

またはnginx組み込みの$fastcgi_script_nameを使用して

fastcgi_param SCRIPT_FILENAME path/to$fastcgi_script_name

という記述が多かった。

$fastcgi_script_nameには、名前の通り要求されたuriからスクリプトファイルに該当する部分を切り出した結果が入るようだ。
fastcgi_split_pathinfo命令を使用して、例えば拡張子phpのスクリプトであれば、

fastcgi_split_pathinfo ^(.+\.php)(.*)$;

とすることで、
$fastcgi_script_nameに前部分の()内のスクリプトファイル名を
$fastcgi_path_infoに後ろ部分の()内の部分を格納することができる。

以上を踏まえて今回動作させる条件に当てはまるように設定ファイルを作ってみた。(ページ下の方)

で、大体は動作したのだが、phpmyadminが、ルートにリダイレクトしやがりますので、
こちらを参考に/etc/phpmyadmin/config.inc.phpの末尾に

$cfg['PmaAbsoluteUri'] = 'http://localhost/phpmyadmin/';

を追加した。

これでOKかな?

/etc/nginx/sites-available/default

# php5-fpmインタフェース
upstream php5-fpm {
 server unix:/var/run/php5-fpm.sock;
}

# サーバー設定
server {
  listen *:80;
  server_name localhost;
  root /var/local/www;

  location = /favicon.ico
  {
	return 404;
  }
  
  # location root [wordpress]
  location / {
    root /usr/local/share/wordpress;
    index index.php;

    # .phpで終わるURLをphp-fpmに渡す
    location ~ ^(.+\.php)(.*)$ {
      fastcgi_split_path_info ^(.+\.php)(.*)$;
      if (!-f $document_root$fastcgi_script_name) { # ファイルの実体が存在しなければ404
        return 404;
      }
      fastcgi_pass php5-fpm;
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
    }
  }
  # end root
  
  # URL /wp-admin
  # wordpress管理用URLに対してアクセス制御を行う
  location ^~ /wp-admin {
    # アクセス制限
    allow 127.0.0.1;
    deny all;

    root /usr/local/share/wordpress;
    index index.php;
    
    # .phpで終わるURLをphp-fpmに渡す
    location ~ ^(.+\.php)(.*)$ {
      fastcgi_split_path_info ^(.+\.php)(.*)$;
      if (!-f $document_root$fastcgi_script_name) { # ファイルの実体が存在しなければ404
        return 404;
      }
      fastcgi_pass php5-fpm;
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
    }
  }
  # end /wp-admin

  # phpmyadmin
  location ^~ /phpmyadmin {
    # アクセス制限
    allow 127.0.0.1;
    deny all;

    alias /usr/share/phpmyadmin;
    index index.php;

    location ^~ /phpmyadmin/setup { # 前方一致でこちらが優先
      # さらにアクセス制限
      allow 127.0.0.1;
      deny all;

      location ~ ^/phpmyadmin(/setup/.+\.php)(.*)$ {
        fastcgi_split_path_info ^/phpmyadmin(/setup/.+\.php)(.*)$;
        if (!-f $document_root$fastcgi_script_name) { # ファイルの実体が存在しなければ404
          return 404;
        }
        fastcgi_pass php5-fpm;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
      }
    }

    location ~ ^/phpmyadmin(.+\.php)(.*)$ {
      fastcgi_split_path_info ^/phpmyadmin(.+\.php)(.*)$;
      if (!-f $document_root$fastcgi_script_name) { # ファイルの実体が存在しなければ404
        return 404;
      }
      fastcgi_pass php5-fpm;
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
    }
  }
  # end phpmyadmin

  # postfixadmin
  location ^~ /postfixadmin {
    # アクセス制限
    allow 127.0.0.1;
    deny all;

    alias /usr/local/share/postfixadmin;
    index index.php;

    location ~ ^/postfixadmin(.+\.php)(.*)$ {
      fastcgi_split_path_info ^/postfixadmin(.+\.php)(.*)$;
      if (!-f $document_root$fastcgi_script_name) { # ファイルの実体が存在しなければ404
        return 404;
      }
      fastcgi_pass php5-fpm;
      include /etc/nginx/fastcgi_params;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param PATH_INFO $fastcgi_path_info;
    }
  }
  # end postfixadmin
}