title: WordPress站点如何配置Nginx date: 2017-06-17T00:48:35+08:00 draft: false tags:
从LAMP换到LNMP环境有相当一段时间了,一直在研究怎么配置Nginx最科学,这里就简单分享一下经验。
众所周知,Apache是全球使用最广泛的Web服务器,各种模块很多、教程也多,几乎可以满足你的各种需求。Nginx是一个高性能的Web服务器,它占用资源少,能轻松应对高并发的连接,相比Apache更加轻量化。可以说Nginx与Apache风格迥异,然而,网上很多关于Nginx的教程都是用的Apache的思路,一个配置文件各种写法的都有,让人很疑惑。也许是Nginx配置文件比较智能吧,感觉怎么写都能正常访问,然而作为强迫症,找不到最正确最科学的配置方法,简直难受。
好好看了一下Nginx的官方文档,结合了codex.wordpress.org以及Nginx Wiki上的教程,姑且认为我现在Nginx的配置文件写对了吧,有什么不妥的欢迎讨论……
在运行WordPress时,Nginx与Apache有些区别是你必须要了解的:
这一部分配置应该写在http {}
块中。
# Upstream to abstract backend connection(s) for php
upstream php {
server unix:/run/php/php7.0-fpm.socket; #使用unix socket
server 127.0.0.1:9000; #使用TCP端口
# 上面两个取决于php-fpm的配置,二选一即可
}
# Main server
#
server {
listen 443 ssl http2;
server_name www.xxxlbox.com; # 你的网址
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # 开启HSTS
ssl on;
ssl_certificate fullchain.pem; # 指定ssl证书路径
ssl_certificate_key privkey.pem;
ssl_dhparam dhparams.pem;
ssl_session_cache shared:SSL:15m;
ssl_session_timeout 30m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS;
ssl_prefer_server_ciphers on;
root html/wordpress; # 指定网站根目录
index index.php index.html;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args?;
}
location ~ \.php$ {
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
fastcgi_pass php;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
}
其中,location / {}
块的try_files
非常机智。网上很多教程都是在这里用了if判断加rewrite,就像这样:
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /index.php;
}
这很类似Apache的.htaccess的写法,这样配置必然是可以正常访问的。然而,Nginx官方并不推荐使用if,请参见《If Is Evil》。
try_files
语句的作用就是按顺序检查文件或文件夹是否存在,返回第一个找到的文件或文件夹,如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。拿这里的try_files $uri $uri/ /index.php?$args?
举个例子:当客户端请求https://www.xxxlbox.com/post/2031
时,此时uri$
就是post/2031
(还是/post/2031
?我不知道)。很明显,这是一个为了美观的“假”链接,网站目录下没有post这个文件夹,$uri
和$uri/
都是不存在的,所以请求会被重定向为https://www.xxxlbox.com/index.php?$args?
。结果请求就被发送到php-fpm了,WordPress自己会判断请求的地址,因此就能显示正确的内容。另一个例子:当客户端请求https://www.xxxlbox.com/wp-content/uploads/2017/10/img1.png
时,显然,此时$uri能找到,该png文件会直接被发送给客户端。由此可见,try_files
能很好地支持WordPress的自定义固定链接功能,同时避免了每次都进行if判断,十分高效,推荐使用。
# Redirect non-www to www
#
server {
listen 80;
listen 443 ssl http2;
server_name xxxlbox.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
ssl_certificate 1_xxxlbox.com_bundle.crt;
ssl_certificate_key 2_xxxlbox.com.key;
ssl_dhparam dhparams.pem;
return 301 https://www.xxxlbox.com$request_uri;
}
# Redirect http to https
#
server {
listen 80;
server_name www.xxxlbox.com;
return 301 https://www.xxxlbox.com$request_uri;
}
在网上搜索“Nginx 301跳转”,很多地方都是这么做的:
server {
listen 80;
server_name www.example.org example.org;
if ($http_host = example.org) {
rewrite (.*) http://www.example.org$1;
}
Nginx官方文档上是这么写的,强烈建议大家去看看这一页:
This is a wrong, cumbersome, and ineffective way. The right way is to define a separate server for
example.org
这里使用的是return 301
,也是新版Nginx推荐的用法。
Apache下,WP Super Cache可以自己生成rewrite规则并写入.htaccess文件中,而Nginx没有.htaccess这样的机制,因此rewrite规则需要自己配置。这个规则可以直接放入server {}
块中。
# WP Super Cache rules.
#
set $cache_uri $request_uri;
# POST requests and urls with a query string should always go to PHP
if ($request_method = POST) {
set $cache_uri 'null cache';
}
if ($query_string != "") {
set $cache_uri 'null cache';
}
# Don't cache uris containing the following segments
if ($request_uri ~* "(/wp-admin/|/xmlrpc.php|/wp-(app|cron|login|register|mail).php|wp-.*.php|/feed/|index.php|wp-comments-popup.php|wp-links-opml.php|wp-locations.php|sitemap(_index)?.xml|[a-z0-9_-]+-sitemap([0-9]+)?.xml)") {
set $cache_uri 'null cache';
}
# Don't use the cache for logged in users or recent commenters
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_logged_in") {
set $cache_uri 'null cache';
}
# 这一部分用于支持WP Super Cache的“移动设备支持”功能。由于现在一般主题都是响应式的,这个功能很少会用到,所以这一块默认被注释。
# START MOBILE
# Mobile browsers section to server them non-cached version. COMMENTED by default as most modern wordpress themes including twenty-eleven are responsive. Uncomment config lines in this section if you want to use a plugin like WP-Touch
#if ($http_x_wap_profile) {
# set $cache_uri 'null cache';
#}
#if ($http_profile) {
# set $cache_uri 'null cache';
#}
#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 $cache_uri 'null cache';
#}
#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 $cache_uri 'null cache';
#}
# END MOBILE
此时你的location / {}
块中try_files $uri $uri/ /index.php?$args?
应加上WP Super Cache的路径,即:
location / {
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index-https.html $uri $uri/ /index.php?$args?;
}
当然如果你的不是https站点,应稍作修改:
location / {
try_files /wp-content/cache/supercache/$http_host/$cache_uri/index-http.html $uri $uri/ /index.php?$args?;
}
把WP Super Cache设置为Mod_rewrite模式,这样的话,借助WP Super Cache生成静态html文件,当条件符合时,Nginx可以直接把这些静态文件发送给用户,完全绕过php,实现全站伪静态。
另外,WordPress上还有一个很有名的缓存插件叫W3 Total Cache,它的Nginx规则在WordPress文档里也能找到:https://codex.wordpress.org/Nginx#W3_Total_Cache_Rules
我们知道WordPress能上传文件的最大体积是由php.ini的配置决定的。除此之外,Nginx对文件的上传大小也有限制(默认好像是2MB),超过这个大小WordPress会报http错误。因此nginx.conf的http {}
块中需加一句client_max_body_size 64m;
(改成你想要的大小)。另外,别忘了开启gzip压缩,gzip on;
。
使用nginx -t
命令可以测试nginx.conf的语法是否正确。
暂时就说这么多吧,有什么其他东西以后再慢慢添加。并非专业人士,有问题欢迎指出。
个人感觉Nginx的配置文件比Apache的简洁多了,写Nginx的配置文件就跟写作文一样,每一行的意思都很清楚,非常接近英文语句,可读性高。还记得我刚换Nginx时的各种不适应,感觉现在已经离不开了。Nginx的一些特性真的是让人不得不爱。
我的Nginx配置参考自这些页面,英语好的强烈建议打开看看: