カテゴリー : Nginx

[Nginx] http を https にリダイレクトする設定 & HTTP Strict Transport Security (HSTS) 対応

Nginx で http リクエストを https にリダイレクトする設定と HTTP Strict Transport Security (HSTS) の設定の2つをご紹介します。

http を https へリダイレクトする設定

以下のように return 301 https://$host$request_uri; の部分で 301 リダイレクトさせてます。

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}
 
server {
    # 'http2' requires nginx 1.9.5+. If using older nginx, replace with 'spdy'.
    listen 443 ssl http2;
    server_name example.com;
}

HTTP Strict Transport Security (HSTS) の設定

server {
    listen 443 ssl http2;
 
    # HTTP Strict Transport Security: tells browsers to require https:// without first checking
    # the http:// version for a redirect. Warning: it is difficult to change your mind.
    # 
    #    max-age: length of requirement in seconds (31536000 = 1 year)
    #    includeSubdomains: force TLS for *ALL* subdomains (remove if this is not what you want)
    #    preload: indicates you want browsers to ship with HSTS preloaded for your domain.
    # 
    #    Submit your domain for preloading in browsers at: https://hstspreload.appspot.com
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
 
 
    # If you won't/can't turn on HTTPS for *all* subdomains, use this simpler version:
    # add_header Strict-Transport-Security "max-age=31536000;" always;
}

HSTS Preload リストへ登録する

Google では ドメインを HSTS Pre-loaded List に登録するサービス を行っています。記載された手順に従ってドメインを登録すれば、今後ブラウザとそのドメインとの間に安全でない通信は起こらなくなります。これに登録するには Strict-Transport-Security ヘッダに preload パラメータを含める必要があります。

[引用元] HTTP Strict Transport Security – Web セキュリティ | MDN

とのことなので HSTS Preload List Submission から登録しましょう。

HSTS Preload List を登録するための条件として、

  • サブドメインは指定できないのでネイキッドドメインを指定する
  • add_header で includeSubDomains を設定する

などが必要です。

今の時代 GoogleのHTTPSサイト優遇方針で待ったなし! と言われていることもあり、未対応のサイト運営者は早めに対応したほうがよさそうです。

参考情報

[Nginx] upstream timed out (110: Connection timed out) while reading response header from upstream

当サイト codenote.net が 504 Gateway Time-out で接続しにくい状態になっていました。

まず、Nginx のエラーログを確認すると upstream timed out (110: Connection timed out) while reading response header from upstream というエラーが出てました。

$ tail -F /var/log/nginx/codenote.net/error.log 
2015/03/28 23:45:04 [error] 20407#0: *537270 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 223.135.69.50, server: codenote.net, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm/www.sock", host: "codenote.net"

ひとまず PHP-FPM のプロセスを再起動して一旦は直ったものの、またすぐに繋がらなくなりました。

$ service php-fpm restart
Stopping php-fpm:                                          [  OK  ]
Starting php-fpm:                                          [  OK  ]

調査してみると PHP-FPM の設定に問題があるようで、確認してみたら process manager の設定がほぼデフォルトのままの状態でした。ちゃんと設定していたはずなんですけど…

/etc/php-fpm.d/www.conf

以下、pm (process manager) のデフォルト設定です。

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic
 
; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
pm.max_children = 9
 
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
pm.start_servers = 3
 
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.min_spare_servers = 2
 
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
pm.max_spare_servers = 4
 
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
pm.max_requests = 200

下記の設定に変更しました。

pm = static
pm.max_children = 30
pm.max_requests = 500

pm = static は最初から小プロセスの起動数を固定する設定です。dynamic だと動的ですが、最初から確保できる static の方が利用するリソースが把握しやすいので static にします。

max_children は起動する小プロセスの最大数です。

max_requests は子プロセスが再起動するまでに実行するリクエスト数です。

PHP-FPM の process manager の設定を変更後、504 Gateway Time-out は表示されず快適にアクセスできるようになりました。

参考情報

[Nginx] Compile オプションの確認方法

Nginx のコンパイルオプションは、 nginx -V で確認できます。

# nginx -V
nginx version: nginx/1.4.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-3) (GCC) 
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-cc-opt='-O2 -g -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic'

yum 経由でインストールした場合でも、この方法で確認できます。


参考情報

SE奮闘記: nginxのgzip_staticを有効に設定

さくらVPS(CentOS6.3)で nginx + php-fpm + MySQL で WordPress環境を構築

Nginx のインストール

■ Nginx リポジトリを登録

# vim /etc/yum.repos.d/nginx.repo
 
[nginx]
name=nginx
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=0

■ インストール可能な Nginx のバージョン確認

# yum info --enablerepo=nginx nginx

■ Nginx のインストール

# yum -y install --enablerepo=nginx nginx

Nginx が正常にインストールされたことを確認する。

# nginx -v
nginx version: nginx/1.4.2

■ Nginx の各種設定

# vim /etc/nginx/nginx.conf
user  nginx;
worker_processes  2;
 
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  main;
 
    sendfile        on;
    #tcp_nopush     on;
 
    keepalive_timeout  65;
 
    # gzip
    gzip  on;
    gzip_http_version 1.0;
    gzip_vary         on;
    gzip_comp_level   6;
    gzip_types        text/xml text/css application/xhtml+xml application/xml application/rss+xml application/atom_xml application/x-javascript application/x-httpd-php;
    gzip_disable      "MSIE [1-6]\.";
 
    # reverse proxy
    proxy_cache_path  /var/cache/nginx levels=1:2 keys_zone=czone:4m max_size=50m inactive=120m;
    proxy_temp_path   /var/tmp/nginx;
    proxy_cache_key   "$scheme://$host$request_uri";
    proxy_set_header  Host               $host;
    proxy_set_header  X-Real-IP          $remote_addr;
    proxy_set_header  X-Forwarded-Host   $host;
    proxy_set_header  X-Forwarded-Server $host;
    proxy_set_header  X-Forwarded-For    $proxy_add_x_forwarded_for;
 
    upstream backend {
        ip_hash;
        server 127.0.0.1:8080;
    }
 
    include /etc/nginx/conf.d/*.conf;
}
# vim /etc/nginx/conf.d/virtual.conf
server {
 
    listen      80;
    server_name example.com;
    root        /var/www/vhosts/example.com/www;
    access_log  /var/log/nginx/example.com/access.log   main;
    error_log   /var/log/nginx/example.com/error.log;
    client_max_body_size 36M;
 
    location /wp-admin { proxy_pass http://backend; }
    location ~ .*\.php { proxy_pass http://backend; }
    location / {
        set $mobile "";
        if ($http_user_agent ~* '(DoCoMo|J-PHONE|Vodafone|MOT-|UP\.Browser|DDIPOCKET|ASTEL|PDXGW|Palmscape|Xiino|sharp pda browser|Windows CE|L-mode|WILLCOM|SoftBank|Semulator|Vemulator|J-EMULATOR|emobile|mixi-mobile-converter)') {
            set $mobile "@ktai";
        }
        if ($http_user_agent ~* '(iPhone|iPod|Opera Mini|Android.*Mobile|NetFront|PSP|BlackBerry)') {
            set $mobile "@mobile";
        }
        if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
            set $do_not_cache 1;
        }
 
        proxy_no_cache     $do_not_cache;
        proxy_cache_bypass $do_not_cache;
        proxy_cache czone;
        proxy_cache_key "$scheme://$host$request_uri$is_args$args$mobile";
        proxy_cache_valid  200 301 302 60m;
        proxy_cache_valid  404 5m;
        proxy_cache_use_stale  error timeout invalid_header updating
                               http_500 http_502 http_503 http_504;
        proxy_pass http://backend;
        proxy_redirect http://example.com:8080/ /;
    }
}
 
server {
 
    listen      8080;
    server_name example.com;
    root        /var/www/vhosts/example.com/www;
    access_log  /var/log/nginx/example.com/access.log   main;
    error_log   /var/log/nginx/example.com/error.log;
    client_max_body_size 36M;
 
    location / {
        index  index.php index.html index.htm;
        # static files
        if (-f $request_filename) {
            expires 14d;
            break;
        }
        # request to index.php
        if (!-e $request_filename) {
            rewrite ^(.+)$  /index.php?q=$1 last;
        }
    }
 
    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {
        include        fastcgi_params;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME  /var/www/vhosts/example.com/www/$fastcgi_script_name;
    }
}

ログディレクトリを作成します。

mkdir /var/log/nginx/example.com

設定ファイル編集後、文法チェックを行います。

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Port8080 を開放するためにファイアーウォールの設定に追記します。

# vim /etc/sysconfig/iptables
 
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080  -j ACCEPT

■ Nginx の自動起動設定

chkconfig nginx on

MySQL のインストール

■ インストール可能な MySQL のバージョン確認

# yum info mysql-server

■ MySQL server のインストール

yum のパッケージは mysql ではなく、mysql-server なので間違えないように。

# yum -y install --enablerepo=remi mysql-server

■ MySQL 設定ファイルの修正

# cp /etc/my.cnf /etc/my.cnf.default
# vim /etc/my.cnf
 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
 
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
 
# Settings user and group are ignored when systemd is used (fedora >= 15).
# If you need to run mysqld under different user or group, 
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
user=mysql
 
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
 
# Disabling symbolic-links is recommended to prevent assorted security risks
#symbolic-links=0
 
# Semisynchronous Replication
# http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html
# uncomment next line on MASTER
;plugin-load=rpl_semi_sync_master=semisync_master.so
# uncomment next line on SLAVE
;plugin-load=rpl_semi_sync_slave=semisync_slave.so
 
# Others options for Semisynchronous Replication
;rpl_semi_sync_master_enabled=1
;rpl_semi_sync_master_timeout=10
;rpl_semi_sync_slave_enabled=1
 
# http://dev.mysql.com/doc/refman/5.5/en/performance-schema.html
;performance_schema
 
character-set-server=utf8
 
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
 
 
# ここから下を追記する
 
[client]
default-character-set=utf8
 
[mysql]
default-character-set=utf8
 
[mysqldump]
default-character-set=utf8

■ MySQL の起動&自動起動の設定

service mysqld start
chkconfig mysqld on

■ MySQL のパスワード設定

# mysqladmin -u root password
# mysqladmin -u root -h hostname password

PHP のインストール

■ インストール可能な PHP のバージョン確認

# yum info php php-mbstring php-mysql php-pear php-gd php-pecl-apc php-fpm

■ PHP のインストール

# yum -y install php php-mbstring php-mysql php-pear php-gd php-pecl-apc php-fpm

PHP が正常にインストールされたことを確認する。

# php -v
PHP 5.3.15 (cli) (built: Jul 20 2012 12:50:06) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

■ php.ini の設定変更

# vim /etc/php.ini
expose_php = Off
 
error_log = /var/log/php_errors.log
 
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.encoding_translation = Off
 
[Date]
date.timezone = Asia/Tokyo

ログファイルの作成

# touch /var/log/php_error.log
# chmod 757 /var/log/php_error.log

■ APC の設定

mkdir -p /var/www/vhosts/example.com
cp /usr/share/doc/php-pecl-apc-3.1.10/apc.php /var/www/vhosts/example.com/
vim /var/www/vhosts/example.com/apc.php 
 
defaults('ADMIN_USERNAME','user');
defaults('ADMIN_PASSWORD','password');

■ Fast CGI のインストール確認

php-fpm が正常にインストールされたことを確認する。

# php-fpm -v
PHP 5.3.15 (fpm-fcgi) (built: Jul 20 2012 12:52:37)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

■ php-fpm の各種設定

# vim /etc/php-fpm.d/www.conf
user = nginx
group = nginx
 
pm = dynamic
pm.max_children =  30
pm.start_servers = 11
pm.min_spare_servers = 10
pm.max_spare_servers = 15
pm.max_requests = 500
 
php_admin_flag[expose_php] = off

php-fpm の起動

service php-fpm start

php-fpm の自動起動設定

chkconfig php-fpm on
# netstat -ltn | grep -E '(80|9000)'
tcp        0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN

以上です。


参考情報

さくらの VPS に nginx を入れてリバースプロキシ設定するまでの作業メモ(検証用) | ウェブル

nginx+php-fpmをyumでインストールして、WordPress/CakePHPを動かす設定 – Shin x blog

さくらVPS(CentOS6.2)でnginx + spawn-fcgi + MySQLでWordPress環境を構築【その2】 | 青田んぼ.net

こちらの設定の方が良いかも。

Nginxを使ったもう一歩進んだWordPressチューニング | cloudrop

[Mac] Nginx を Homebrew でインストール

Mac に Nginx を Homebrew でインストールしました。

% brew install nginx
% nginx -v
nginx version: nginx/1.4.1

Nginx を自動起動する設定をします。

% ln -sfv /usr/local/opt/nginx/*.plist ~/Library/LaunchAgents
% launchctl load ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

Nginx を手動で起動したい場合は、下記のコマンドを実行します。

% nginx

http://127.0.0.1:8080/ にアクセス

welcome-to-nginx

あとは、利用用途に応じて色々と設定していきます。