はじめに
NginxはCGIを標準では実行できませんが、FCGI Wrapを使うとCGIをFastCGIとして実行してくれます。
大昔に作ったRubyのCGIのアプリをNginxのサーバ上で動かしたかったので、FCGI Wrapを試してみました。
注意点として、FCGI WrapはFastCGIのインターフェースを提供してくれるだけなので、CGIと同様にユーザーから要求がある度に、プロセスの生成と破棄が行われるため、パフォーマンスは悪いみたいです。
環境
今回試した環境です。
- Conoha VPS
- Ubuntu 16.04.3 LTS (Xenial Xerus)
- Nginx/1.10.3
- Ruby 2.3.1p112 (2016-04-26)
タイトルにはRubyのCGIと書きましたが、設定のlocationの拡張子さえ変えれば、PerlやPythonやPHPなど他の言語でも同じように設定できると思います。
設定手順
FCGI Wrapの公式ページを参考にセットアップしました。
FCGI Wrapのインストール
sudo apt install fcgiwrap
設定
/etc/nginx/fcgiwrap.conf
の作成
cp /usr/share/doc/fcgiwrap/examples/nginx.conf /etc/nginx/fcgiwrap.conf
今回はRubyのCGIを動かしたかったので、以下のように修正しました。
diff --git a/usr/share/doc/fcgiwrap/examples/nginx.conf b/etc/nginx/fcgiwrap.conf
index 5bdfdf1..e218726 100644
--- a/usr/share/doc/fcgiwrap/examples/nginx.conf
+++ b/etc/nginx/fcgiwrap.conf
@@ -1,13 +1,13 @@
# Include this file on your nginx.conf to support debian cgi-bin scripts using
# fcgiwrap
-location /cgi-bin/ {
+location ~ .rb$ {
# Disable gzip (it makes scripts feel slower since they have to complete
# before getting gzipped)
gzip off;
# Set the root to /usr/lib (inside this location this means that we are
# giving access to the files under /usr/lib/cgi-bin)
- root /usr/lib;
+ #root /usr/lib;
# Fastcgi socket
fastcgi_pass unix:/var/run/fcgiwrap.socket;
@@ -16,5 +16,5 @@ location /cgi-bin/ {
include /etc/nginx/fastcgi_params;
# Adjust non standard parameters (SCRIPT_FILENAME)
- fastcgi_param SCRIPT_FILENAME /usr/lib$fastcgi_script_name;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
/etc/nginx/fcgiwrap.conf
のインクルード
Nginxの設定ファイル構成によりますが、普通は /etc/nginx/sites-available/default
の server ブロック内で読み込んでおけばいいと思います。
server {
+ # fast cgi support
+ include /etc/nginx/fcgiwrap.conf;
}
RubyのCGIスクリプト
まずは単純なスクリプトでテストしました。
適当な場所にパーミッションを正しく指定して配置してください。
#!/usr/bin/ruby
puts "Content-Type: text/html\n\n"
puts "<html>"
puts "<head><title>Test</title></head>"
puts "<body>"
puts "<h1>Hello CGI World!</h1>"
puts "</body>"
puts "</html>"
トラブルシューティング
躓いたポイントを紹介します。
SCRIPT_FILENAMEの設定
パーミッションは正しいのに403エラーとなってしまいました。
エラーログ /var/log/nginx/error.log
を見ると以下のようになっていました。
2017/10/05 11:49:03 [error] 9728#9728: *45 FastCGI sent in stderr: “Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?” while reading response header from upstream, client: xxx.xxx.xxx.xxx, server: _, request: “GET /app/test.rb HTTP/1.1", upstream: “fastcgi://unix:/var/run/fcgiwrap.socket:“, host: “xxx.xxx.xxx.xxx”
これは /etc/nginx/fcgiwrap.conf
の SCRIPT_FILENAME
を修正したら動きました。
-fastcgi_param SCRIPT_FILENAME /usr/lib$fastcgi_script_name;
+fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;