Ubuntu 18.04 に nginx + fcgiwrap + php-fpm で CGI 環境を構築する

以前、CentOS 系の Linux で CGI on nginx をやったが、今回はそれの Ubuntu 版。

前提条件

$ nginx -v
nginx version: nginx/1.14.0 (Ubuntu)

CGI として動かす言語をインストールする

まずは CGI として動かしたい言語をインストールしていく。今回はバージョン管理など省略して、さっさと入れていく。

# Perl : 最初から入っていたので無視
$ perl -v
This is perl 5, version 32, subversion 0 (v5.32.0) built for x86_64-linux-thread-multi

# Ruby
$ apt install -y ruby
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]

# Python
$ apt install -y python3.7 python3.7-dev python3-pip
$ python -V
Python 3.7.5

# Node.js
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
$ apt install -y nodejs
$ node -v
v14.8.0
$ npm -v
6.14.7

# PHP
$ apt install -y php
$ php -v
PHP 7.2.24-0ubuntu0.18.04.6 (cli) (built: May 26 2020 13:09:11) ( NTS )

fcgiwrap を入れていく

$ apt install -y fcgiwrap spawn-fcgi libfcgi-dev php-fpm

ところで nginx の実行ユーザは…

CentOS 系だと nginx というユーザで nginx が動いていたが、Ubuntu だと www-data というユーザおよびグループで動いていた。

$ ps aux | grep nginx
root       852  0.0  0.0  33184   884 ?        Ss   Aug22   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   856  0.0  0.3  38208  3400 ?        S    Aug22   0:00 nginx: worker process

/etc/nginx/nginx.conf などにも user www-data; と書かれているので、ココだけ留意。

fcgiwrap を設定する

fcgiwrap の設定を行う。

$ vi /etc/init.d/fcgiwrap

次のように修正する。

# デフォルトでは "1" なので増やす (プロセス数)
FCGI_CHILDREN="6"

そしたら fcgiwrap を再起動する。

# 以下のような行をコメントアウトする?
FCGI_SOCKET="/var/run/$NAME.socket"

# 以下の2行を付け足す?
FCGI_PORT="8999"
FCGI_ADDR="127.0.0.1"

↑ こんなことが書いてある文献もあったのだが、自分は上手くいかなかった。9000番あたりのポートでリスンして処理するやり方は上手く動かなくて、Socket を使うやり方なら上手く行った。

# 多分以下のどちらでも動く
$ /etc/init.d/fcgiwrap restart
$ systemctl restart fcgiwrap

$ systemctl status fcgiwrap

Socket を確認する

この後の nginx 設定で使用するので、fcgiwrap.socketphp-fpm.socket の存在を確認する。

$ ls -l /var/run/*.socket
srw-rw-rw- 1 root root 0 2020-08-19 10:18 /var/run/acpid.socket=
srw-rw-rw- 1 root root 0 2020-08-25 10:57 /var/run/fcgiwrap.socket=
srw-rw-rw- 1 root root 0 2020-08-20 06:09 /var/run/snapd-snap.socket=
srw-rw-rw- 1 root root 0 2020-08-20 06:09 /var/run/snapd.socket=

$ ls -l /var/run/php/php7.2-fpm.sock
srw-rw---- 1 www-data www-data 0 2020-08-25 14:40 /var/run/php/php7.2-fpm.sock=

コレを把握しておく。

nginx 設定を変更する

nginx.confconf.d/default.conf を作って修正していく。全量貼り付けておく。

# user が CentOS 系の nginx ではないことに留意
user  www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log  warn;
pid        /var/run/nginx.pid;

events {
  worker_connections 1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;
  
  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
  access_log  /var/log/nginx/access.log;
  
  sendfile  on;
  keepalive_timeout  65;
  include  /etc/nginx/conf.d/*.conf;
}
server {
  listen       80;
  server_name  localhost;
  # HTTPS 対応している場合は以下のように書く
  #listen       443 ssl;
  #ssl_certificate      /etc/letsencrypt/live/example.com/fullchain.pem;
  #ssl_certificate_key  /etc/letsencrypt/live/example.com/privkey.pem;
  
  location / {
    root   /var/www/html;
    index  index.html index.cgi index.pl index.rb index.php;
  }
  
  #error_page  404  /404.html;
  error_page  500 502 503 504  /50x.html;
  location = /50x.html {
    root  /var/www/html;
  }
  
  # Enable 'Index Of'
  autoindex             on;
  autoindex_exact_size  off;
  autoindex_localtime   on;
  
  # For CGI : Perl Ruby
  location ~ \.(pl|rb|cgi)$ {
    try_files      $uri  /404.html;
    root           /var/www/html;
    # 以下が CentOS 系では 127.0.0.1:9001 などと設定したが、Socket を使う
    fastcgi_pass   unix:/var/run/fcgiwrap.socket;
    fastcgi_index  index.cgi;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        /etc/nginx/fastcgi_params;
  }
  
  # For PHP
  location ~ \.php$ {
    try_files      $uri  /404.html;
    root           /var/www/html;
    # 以下が CentOS 系では 127.0.0.1:9000 などと設定したが、Socket を使う
    fastcgi_pass   unix:/var/run/php/php7.2-fpm.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        /etc/nginx/fastcgi_params;
  }
}

CentOS 版と違うのは fastcgi_pass 部分。ホスト名とポート番号を指定していたのと比べて、今回は Socket 指定で行っている。

設定できたら構文チェックをして、nginx を再起動する。

$ nginx -t
$ systemctl restart nginx

テストファイルを作成する

それぞれの言語でちゃんと CGI が動作するか、確認用のファイルを作る。

$ cat << EOL > /var/www/html/example.pl
#!/usr/bin/perl
print "Content-Type: text/plain\n\n";
$my_var = 'Perl';
print "Hello World from $my_var .";
EOL

$ cat << EOL > /var/www/html/example.py
#!/usr/bin/python3
print('Content-Type: text/plain\n\n')
my_var = 'Python'
print('Hello World from ' + my_var)
EOL

$ cat << EOL > /var/www/html/example.rb
#!/usr/bin/ruby
print("Content-Type: text/plain\n\n")
my_var = 'Ruby'
print("Hello World from #{my_var} .")
EOL

# 拡張子 .cgi は Node.js を動かすことにする
$ cat << EOL > /var/www/html/example.cgi
#!/usr/bin/node
console.log('Content-Type: text/plain\n\n');
const myVar = 'Node.js';
print(`Hello World from ${myVar}`);
EOL

$ cat << EOL > /var/www/html/example.php
<?php phpinfo(); ?>
EOL

$ chmod 755 /var/www/html/example.pl
$ chmod 755 /var/www/html/example.py
$ chmod 755 /var/www/html/example.rb
$ chmod 755 /var/www/html/example.cgi
# PHP は実行権限不要

コレで

などにアクセスできれば nginx で CGI や PHP が動かせている。