NGINX

同時処理速度、メモリの軽さが特徴のWebサーバ。
Webサーバ以外にもリバースプロキシとして動かす事も出来る。
ソフトウェア実装としては珍しい、UDPリバースプロキシにも対応している。

参考サイト

インストール

  • 1. インストール
    nginxの全機能を利用するにはプログラムをソースコードからビルドする必要がある。
    特に、リバースプロキシなど最新の実装機能を利用する場合には必須となる。
    今回は機能を全部有効化してビルドするので、長くなるconfigure指定を別ファイル化しておき、
    configureする時にコマンド置換(バッククォート)で読み込む。
    # vi configure.option
    ---
     --prefix=/usr/local/nginx-1.13.9
     --with-select_module
     --with-poll_module
     --with-threads
     --with-file-aio
     --with-http_ssl_module
     --with-http_v2_module
     --with-http_realip_module
     --with-http_addition_module
     --with-http_xslt_module
     --with-http_geoip_module
     --with-http_gunzip_module
     --with-http_gzip_static_module
     --with-http_auth_request_module
     --with-http_secure_link_module
     --with-http_degradation_module
     --with-http_slice_module
     --with-http_stub_status_module
     --with-mail
     --with-mail_ssl_module
     --with-stream
     --with-stream_ssl_module
     --with-stream_realip_module
     --with-stream_geoip_module
     --with-stream_ssl_preread_module
     --with-cpp_test_module
     --with-compat
     --with-pcre
     --with-pcre-jit
     --with-libatomic
     
    # wget http://nginx.org/download/nginx-1.13.9.tar.gz
    # tar zxvf nginx-1.13.9.tar.gz
    # cd nginx-1.13.9
    # ./configure `cat ../configure.option | tr '\r\n' ''`
    # make && make install
     
  • 2. 起動準備
    実行ユーザ、systemdスクリプト、ログローテート設定を準備する。
    systemdスクリプトにPIDファイルを埋め込んでいる為、
    後で作成するコンフィグのPID指定もsystemdに記載した物と合わせる。
    # vi /usr/lib/systemd/system/nginx.service
    ---
    [Unit]
    Description=NGINX - Web server and Reverse proxy
    Documentation=http://nginx.org/en/docs/
    After=local-fs.target remote-fs.target network.target nss-lookup.target
    
    [Install]
    WantedBy=multi-user.target
    
    [Service]
    Type=forking
    NotifyAccess=all
    PIDFile=/var/run/nginx.pid
    ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf
    ExecStart=/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
    ExecReload=/bin/kill -s HUP $MAINPID
    ExecStop=/bin/kill -s QUIT $MAINPID
    
    ## Security Setting
    DevicePolicy=closed
    PrivateDevices=true
    PrivateTmp=true
    ProtectSystem=full
    ProtectHome=true
     
    # vi /etc/logrotate.d/nginx
    ---
    /var/log/nginx/*.log {
        weekly
        compress
        rotate 4
        missingok
        ifempty
        sharedscripts
        postrotate
            systemctl restart nginx > /dev/null 2>/dev/null || true
        endscript
    }
     
    # ln -s /usr/local/nginx-1.13.9 /usr/local/nginx
    # ln -s /usr/local/nginx/conf /etc/nginx
    # rm /etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/win-utf
    # mkdir /var/log/nginx
    # groupadd nginx
    # useradd -g nginx -s /sbin/nologin -d /var/nginx nginx
    # systemctl unmask nginx
    # systemctl enable nginx
     
  • 3. 基礎設定
    nginxは利用する機能に応じてコンフィグの内容が大きく変化する。
    下記では、nginxの実行ユーザなど基本的な部分のみ記載する。
    # vi /etc/nginx/nginx.conf
    ---
    user       nginx;
    pid        /var/run/nginx.pid;
    error_log  /var/log/nginx/error.log;
    
    worker_processes       auto;
    worker_rlimit_nofile   4096;
    
    events {
        worker_connections 1024;
        accept_mutex_delay 50ms;
        multi_accept       on;
        use                epoll;
    }

コンフィグ

nginxは通常のWebサーバ動作や、リバースプロキシ動作など様々な用途に利用出来る。
用途に応じて必要な設定とディレクティブ指定が変わる為、使う機能に応じて内容を変更する。
同じサーバで違う処理を実装する場合、 "include" を使って設定を外出しすると整理しやすくなる。
 


  • UDPリバースプロキシ
    UDPリバースプロキシのコンフィグは、nginxのTCPリバースプロキシ設定とほぼ同じになる。
    ただし、nginxのフロントエンドとなるlistenの箇所にudpを指定する点に注意する。
     
    下記はフロントエンドを「10.0.0.1」で待ち受け、
    バックエンドの2IPアドレス「192.168.0.1」「192.168.0.2」へUDP53で振り分ける設定となる。
    stream {
        access_log /var/log/nginx/access.log basic;
        error_log  /var/log/nginx/error.log  info;
    
        upstream DNS {
            hash   $remote_addr;
            server 192.168.0.1:53;
            server 192.168.0.2:53;
        }
    
        server {
            listen          10.0.0.1 udp;
            proxy_pass      DNS;
            proxy_timeout   1s;
            proxy_responses 1;
        }
    }
     

  • HTTP Webサーバ
    Apacheと違う所として「.htaccess」ファイルが動かない事と、
    PHPを動かす時にはPHP-FPMを起動させて代理処理する点に注意する
     
    下記はDocumentRootを "/var/nginx/html" とした上で、
    nginxをWebサーバとして稼働させる設定例となる。
    http {
        default_type    application/octet-stream;
        include         /etc/nginx/mime.types;
        access_log      /var/log/nginx/access.log combined;
    
        # Server Setting
        sendfile            on;
        tcp_nopush          on;
        autoindex           off;
        etag                off;
        server_tokens       off;
        keepalive_timeout   5;
    
        # Contents Compress
        gzip                on;
        gzip_http_version   1.0;
        gzip_disable        msie6;
        gzip_min_length     1024;
        gzip_types          text/plain
                            text/xml
                            text/css
                            application/xml
                            application/xhtml+xml
                            application/rss+xml
                            application/atom_xml
                            application/javascript
                            application/x-javascript
                            application/x-httpd-php;
    
        # HTTP Server
        server {
            listen      0.0.0.0:80 default_server;
            server_name _;
    
            location / {
                root    /var/nginx/html;
                index   index.html index.htm;
            }
    
            add_header  X-Frame-Options        SAMEORIGIN;
            add_header  X-XSS-Protection       "1; mode=block";
            add_header  X-Content-Type-Options nosniff;
        }
    }
     

  • CGI実行環境
    nginxの処理体系はイベント型の為、CGIを実行するには別途プログラムを噛ませる必要がある。
    今回はCGI実行環境としてFastCGIを利用する。
     
    下記はopenSUSE上でのCGI実行環境の構築例となる。
    # zypper install spawn-fcgi FastCGI FastCGI-devel
    # ln -s /usr/include/fastcgi/fastcgi.h     /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgi_config.h /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgi_stdio.h  /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgiapp.h     /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgimisc.h    /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgio.h       /usr/local/include/
    # ln -s /usr/include/fastcgi/fcgios.h      /usr/local/include/
     
    # cd /usr/local/src
    # git clone https://github.com/gnosek/fcgiwrap `date "+%Y%m%d"`
    # ln -s `date "+%Y%m%d"` fcgiwrap
    # cd fcgiwrap
    # autoreconf -i
    # ./configure
    # make
    # make install
     
    # vi /etc/init.d/spawn-fcgi
    # chmod 755 /etc/init.d/spawn-fcgi
    # chown root.root /etc/init.d/spawn-fcgi
    # chkconfig --add spawn-fcgi
    # systemctl enable spawn-fcgi
    # systemctl start spawn-fcgi
     /etc/init.d/spawn-fcgi
     
    # vi /etc/nginx/nginx.conf
    ---
    http {
        server {
            location ~ [^/]\.(cgi|pl)($|\?|\/) {
               root            /var/nginx/html;
               fastcgi_pass    unix:/var/run/spawn-fcgi.socket;
               fastcgi_index   index.cgi,index.pl;
               include         /etc/nginx/fastcgi_params;
               fastcgi_param   PATH_INFO $fastcgi_path_info;
               fastcgi_param   PATH_TRANSLATED $document_root$fastcgi_path_info;
               fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
            }
        }
    }
     
    FastCGIビルド時に次の様なエラーが出た場合、
    fcgiwrap.cに"FALLTHROUGH"を追記する事でエラーを抑制する
    cc -std=gnu99 -Wall -Wextra -Werror -pedantic -O2 -g3    fcgiwrap.c  -lfcgi  -o fcgiwrap
    fcgiwrap.c: In function 'handle_fcgi_request':
    fcgiwrap.c:581:4: error: this statement may fall through [-Werror=implicit-fallthrough=]
        cgi_error("502 Bad Gateway", "Cannot execute script", filename);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    fcgiwrap.c:583:3: note: here
       default: /* parent */
       ^~~~~~~
    cc1: all warnings being treated as errors
    make: *** [<builtin>: fcgiwrap] Error 1
     fcgiwrap.c
     

  • PHP実行環境
    CGIと同様に、nginx上でPHPを実行する場合も別プログラムに投げる必要がある。
    PHPを実行する手段は多種存在するが、今回はphp-fpmを利用手法をメモしておく。
    # zypper install php7 php7-devel php7-fpm
    # cp /etc/php7/fpm/php-fpm.conf.default /etc/php7/fpm/php-fpm.conf
    # cp /etc/php7/fpm/php-fpm.d/www.conf.default /etc/php7/fpm/php-fpm.d/www.conf
    # vi /etc/php7/fpm/php-fpm.d/www.conf
    ---
    [www]
    user  = nginx
    group = nginx
    listen = /var/run/php-fpm.socket
    listen.owner = nginx
    listen.group = nginx
    listen.mode  = 0660
    listen.allowed_clients = 127.0.0.1
     
    # /etc/init.d/php-fpm start
    # vi /etc/nginx/nginx.conf
    ---
    http {
        server {
            location ~ \.(php)$ {
                root            /var/nginx/html;
                fastcgi_pass    unix:/var/run/php-fpm.socket;
                fastcgi_index   index.php;
                include         /etc/nginx/fastcgi_params;
                fastcgi_param   PATH_INFO $fastcgi_path_info;
                fastcgi_param   PATH_TRANSLATED $document_root$fastcgi_path_info;
                fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
            }
        }
    }