るいすときのこの物語

オタクエンジニアの雑記

nginx + リバースプロキシ + SSL でWordpressを動かす


1日10万PVぐらいのWordpressを管理することになってどうがんばっても8秒を切れない。 そこでテスト環境に入れた nginx + リバースプロキシ + SSL でWordpressを動かした時のコンフィグを覚書として。

nginx.conf

user  nginx;
worker_processes  7;

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

#worker_rlimit_nofile   150000;

events {
    worker_connections  1024;
    multi_accept        on;
    use epoll;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    server_names_hash_bucket_size   64;

    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;

    #gzip  on;

    proxy_buffering     on;
    proxy_buffer_size   8k;
    proxy_buffers       100 8k;
    proxy_cache_path    /var/cache/nginx levels=1:2
                        keys_zone=czone:15m max_size=512m inactive=7d;
    proxy_temp_path     /var/tmp/nginx;
    proxy_cache_key     $scheme://$host$request_uri;
    proxy_cache_valid   200 302 2h;
    proxy_cache_valid   301     4h;
    proxy_cache_valid   any     1m;
    proxy_cache_use_stale  error timeout invalid_header updating
                           http_500 http_502 http_503 http_504;

    # set header
    proxy_set_header   Host                $host;
    proxy_set_header   X-Real-IP           $remote_addr;
    proxy_set_header   X-Remote-Addr       $remote_addr;
    proxy_set_header   X-Forwarded-Proto   https;
    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;

    # backend
    upstream backend {
        ip_hash;
        server 127.0.0.1:8080;
    }

    include /etc/nginx/conf.d/*.conf;
}
proxy_set_header X-Forwarded-Proto https;

SSLで動かす際に大事なのがこれで、この記述がないと

The page at 'https://domain.com/service1/' was loaded over HTTPS, but is submitting data to an insecure location at 'http://domain.com/service1/': this content should also be submitted over HTTPS.

こんな感じにコンテンツがブロックされて、レイアウトが崩れた誰もが1度は見たことある状況になります。

ちなみに

proxy_redirect http:// https://;

この記述はなくても普通に動く。ヘッダーに設定すればこの記述は不要なのかなと思って

proxy_set_header X-Forwarded-Proto https;

これを消して

proxy_redirect http:// https://;

これだけの記述にしたけど同様に

The page at 'https://domain.com/service1/' was loaded over HTTPS, but is submitting data to an insecure location at 'http://domain.com/service1/': this content should also be submitted over HTTPS.

と怒られた。

 

default.conf

server {
    listen       80;
    server_name  luispc.com;

    return 301 https://luispc.com$request_uri;
}

server {
    listen      443     ssl;
    server_name luispc.com;

    root        /home/rerar/www;
    index       index.php;

    access_log  /var/log/nginx/access443_log;
    error_log   /var/log/nginx/error443_log;

    client_max_body_size    2G;

    ssl                 on;
    ssl_certificate     /home/rerar/nginx/ssl/ssl-bundle.crt;
    ssl_certificate_key /home/rerar/nginx/ssl/luispc_com.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers   on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    add_header X-Cache $upstream_cache_status;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

    rewrite ^/archives/(.*)$ https://luispc.com/?p=$1 last;

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }

    location ~ \.ico$ {
        log_not_found off;
        access_log off;
        expires max;
    }

    location ~ \.(css|js)$ {
        charset  UTF-8;
        access_log off;
        expires 1d;
    }

    location ~* \.(jpe?g|gif|png|ico|woff|svg|swf|inc)$ {
        expires     7d;
        access_log  off;
    }
    location /wp-content/uploads {
        expires     max;
        access_log  off;
    }

    location ~ /\. {
        deny          all;
        access_log    off;
        log_not_found off;
    }
    location = /wp-config.php {
        deny        all;
        access_log  off;
    }
    location ~ .*\.php {
        proxy_pass http://backend;
    }
    location / {
        set $do_not_cache 0;
        if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_|wordpress_logged_in" ) {
            set $do_not_cache 1;
        }
        if ($request_method != GET) {
            set $do_not_cache 1;
        }

        # mobile setting
        include /etc/nginx/mobile_cache_setting;

        proxy_no_cache         $do_not_cache;
        proxy_cache_bypass     $do_not_cache;
        proxy_cache            czone;
        proxy_cache_key        $scheme://$host$uri$is_args$args;
        proxy_pass             http://backend;
    }
}

server {
    listen      8080;
    server_name luispc.com;

    root        /home/rerar/www;
    index       index.php;

    access_log  /home/rerar/log/access8080.log;
    error_log   /home/rerar/log/error8080.log;

    location / {
        location ~ /wp-content  {
            access_log  off;
            include     /etc/nginx/php_exec;
        }
        location ~ /wp-includes {
            access_log  off;
            include     /etc/nginx/php_exec;
        }
        location ~ /wp-cron.php {
            access_log  off;
            include     /etc/nginx/php_exec;
        }
        location ~ /wp-comments {
            access_log  off;
            include     /etc/nginx/php_exec;
        }
        location ~ /wp-admin {
            access_log  off;
            include    /etc/nginx/php_exec;
        }
        location ~ /wp-login.php {
            access_log  off;
            include     /etc/nginx/php_exec;
        }
        include /etc/nginx/php_exec;
    }
}

 

 

mobile_cache_setting

#  -- is wap device ?
if ($http_x_wap_profile ~ ^[a-z0-9\"]+) {
    set $do_not_cache 1;
}

#  -- is cellular ?
if ($http_profile ~ ^[a-z0-9\"]+) {
    set $do_not_cache 1;
}

#  -- is mobile browser ?
if ($http_user_agent ~ ^.*(2.0\ MMP|240x320|400X240|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|Googlebot-Mobile|hiptop|IEMobile|KYOCERA/WX310K|LG/U990|MIDP-2.|MMEF20|MOT-V|NetFront|Newt|Nintendo\ Wii|Nitro|Nokia|Opera\ Mini|Palm|PlayStation\ Portable|portalmmm|Proxinet|ProxiNet|SHARP-TQ-GX10|SHG-i900|Small|SonyEricsson|Symbian\ OS|SymbianOS|TS21i-10|UP.Browser|UP.Link|webOS|Windows\ CE|WinWAP|YahooSeeker/M1A1-R2D2|iPhone|iPod|Android|BlackBerry9530|LG-TU915\ Obigo|LGE\ VX|webOS|Nokia5800).*) {
    set $do_not_cache 1;
}

#  -- is mobile browser ?
if ($http_user_agent ~ ^(w3c\ |w3c-|acs-|alav|alca|amoi|audi|avan|benq|bird|blac|blaz|brew|cell|cldc|cmd-|dang|doco|eric|hipt|htc_|inno|ipaq|ipod|jigs|kddi|keji|leno|lg-c|lg-d|lg-g|lge-|lg/u|maui|maxo|midp|mits|mmef|mobi|mot-|moto|mwbp|nec-|newt|noki|palm|pana|pant|phil|play|port|prox|qwap|sage|sams|sany|sch-|sec-|send|seri|sgh-|shar|sie-|siem|smal|smar|sony|sph-|symb|t-mo|teli|tim-|tosh|tsm-|upg1|upsi|vk-v|voda|wap-|wapa|wapi|wapp|wapr|webc|winw|winw|xda\ |xda-).*) {
    set $do_not_cache 1;
}

#  -- is mobile browser ?
if ($http_user_agent ~ ^(DoCoMo/|J-PHONE/|J-EMULATOR/|Vodafone/|MOT(EMULATOR)?-|SoftBank/|[VS]emulator/|KDDI-|UP\.Browser/|emobile/|Huawei/|IAC/|Nokia|mixi-mobile-converter/)) {
    set $do_not_cache 1;
}

#  -- is other cellular, game, pda ?
if ($http_user_agent ~ (DDIPOCKET\;|WILLCOM\;|Opera\ Mini|Opera\ Mobi|PalmOS|Windows\ CE\;|PDA\;\ SL-|PlayStation\ Portable\;|SONY/COM|Nitro|Nintendo)) {
    set $do_not_cache 1;
}

 

 

php_exec

location ~\.php$ {
    expires          off;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass     127.0.0.1:9000;
    fastcgi_index    index.php;
    fastcgi_param    SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include          fastcgi_params;

    fastcgi_buffers              16 16k;
    fastcgi_buffer_size          32k;
    fastcgi_busy_buffers_size    32k;
    fastcgi_temp_file_write_size 256k;
}

 

Wordpressで記事更新時などのキャッシュ削除は Nginx Cache Controller を使うようにした。 もう1つ名のしれてるやつは、パッケージから入れた場合 ngn_cache_purge モジュールが入ってないために使えない”らしい”。

Nginx Cache Controller はキャッシュディレクトリと、レベルを指定することで同じことを実現してるのかな? ngn_cache_purge モジュールを使ったことないので適当に言いました!