FastCGI в Nginx

Как использовать Nginx для работы с любым языком программирования? Использовать универсальный протокол FastCGI!

Установка fcgiwrap

Для работы Nginx с FastCGI необходимо установить пакет fcgiwrap:

sudo apt-get install fcgiwrap

Настройка Nginx

Конфиг Nginx, в примере порт 8300:

fcgi.conf
server {
 
  server_name _;
  listen 8300;
  error_log /var/log/nginx/8300-error.log error;
  access_log /var/log/nginx/8300.log combined;
 
  proxy_connect_timeout       600;
  proxy_send_timeout          600;
  proxy_read_timeout          600;
  send_timeout                600;
 
  # Для данного location будем использовать только FastCGI
 
  location ^~ /cgi/ {
    gzip           off;
    root           /var/www;
    fastcgi_pass   unix:/var/run/fcgiwrap.socket;
 
    # Эту часть можно вынести в отдельный файл и делать include fastcgi_params;
 
    fastcgi_param  QUERY_STRING       $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE       $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;
 
    fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI       $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;
 
    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
 
    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
 
    # According to RFC3875 (https://tools.ietf.org/html/rfc3875#section-4.1.14) in SERVER_NAME
    # we should put actual hostname user came to. For nginx it is in $host
    # This will allow to run multihost instances
 
    fastcgi_param  SERVER_NAME        $host;
  }
}

Пример FastCGI на bash

Bash-файл, который формирует ответ:

/var/www/cgi/index.sh
#!/bin/bash
NAME=`"cpuinfo"`
echo "Content-type:text/html"
echo
echo "<html><head>"
echo "<title>$NAME</title>"
echo '<meta name="description" content="'$NAME'">'
echo '<meta name="keywords" content="'$NAME'">'
echo '<meta http-equiv="Content-type"
content="text/html;charset=UTF-8">'
echo '<meta name="ROBOTS" content="noindex">'
echo "</head><body><pre>"
date
echo "\nuname -a"
uname -a
echo "\ncpuinfo"
cat /proc/cpuinfo
echo "</pre></body></html>"

Для CGI скриптов следует выставить атрибут выполнения (chmod +x файл-скрипта), а сам скрипт будет выполнен под пользователем, от которого работает Nginx.

Теперь по адресу http://localhost:8300/cgi/index.sh будет выполняться Bash-скрипт:

Bash-скрипт как веб-сервер

2018/09/17 16:32:09 [error] 1254#1254: *187 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: 127.0.0.1, server: _, request: "GET /cgi/index.sh HTTP/1.1", upstream: "fastcgi://unix:/var/run/fcgiwrap.socket:", host: "localhost:8300"

Такая ошибка указывает на то, что забыли выставить +x для скрипта.

Пример FastCGI на NodeJS

NodeJS в данном случае запускается каждый раз, и НЕ работает как отдельный веб-сервер.

/var/www/cgi/index.js
#!/usr/bin/node
console.log("Content-type:text/html");
console.log("");
console.log("<html><head>");
console.log("<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\">");
console.log("</head><body>");
console.log("Текущее время: ", new Date());
console.log("</body></html>");