先说结论:

第一需要使用Alias指定文件夹,第二由于try_files的bug,需要手写rewrite

Nginx简直就是个智障。妈的花了我一个下午,翻了几十个stackoverflow和google才找到这么一个无人问津的小帖子。

需求:

主域名example.com下已经挂了静态站点,文件在/home/html/portal。现在要在example.com/blog目录下挂一个Wordpress博客,文件在/home/html/wordpress

过程:

这么简单的一个小问题,竟然让人大费周章了半天时间,Nginx大概是我见过的这方面最垃圾的东西。要不是看在你性能高的份上,谁™会屌你。

  • 坑1:root指定的文件夹会与location前缀进行组合。

于是不论你怎么改root,只要物理路径不和url进行匹配,只要wordpress不放在根目录,那么Nginx只会在/physical/path/+/virtual/dir/的组合路径下查找wordpress文件(妈的智障,我为什么非要把wordpress文件夹改成和url一样?)

  • 坑2:经过一番google,你发现了alias命令,结果alias的路径末尾如果没有斜线就会404。

是不是想起了proxy_pass时候的斜线和location里的斜线?

  • 坑3:之前google到的很多例子,包括官方例子都写给你:try_files uri uri/ /virtual/dir/index.php?$args; 结果怎么不能用啊?

又经过一番google,你发现因为一个远古bug导致alias和try_files共用时出错了。于是你还得自己重写url。

  • 坑4:配置文件已经写得乱成一团了,我想把Wordpress的配置放在一起行不行?于是写成了nested location,这父级和子location是怎么个匹配法啊?

不知道为什么,没什么人用nested location。官方也没做什么解释,google了一番之后获得了一个提示,location向下传递的时候不会变化,仍然是完整匹配。于是又给所有的子location加了前缀正则匹配。

总算搞定了。。感觉好厉害啊,完全不懂怎么做到的。。。

参考配置例子:

location /blog {
  return 301 $scheme://$host/blog/;
}

location @blog {
  rewrite ^/blog/(.*)$ /blog/index.php?$1;
}

location /blog/ {
  index index.php;
  alias /home/html/wordpress/;

  try_files $uri $uri/ @blog;

  # Add trailing slash to */wp-admin requests.
  rewrite /wp-admin$ $scheme://$host$uri/ permanent;

  # Directives to send expires headers and turn off 404 error logging.
  location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
    access_log off;
    log_not_found off;
    expires max;
  }

  location ~* ^/blog/(?:uploads|files)/.*\.php$ {
    deny all;
  }

  # Pass all .php files onto a php-fpm/php-fcgi server.
  location ~ ^/blog/(.+\.php)$ {
    alias /home/html/wordpress/$1;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_intercept_errors on;
    fastcgi_index index.php;
    fastcgi_pass php;
  }
}

参考链接

http://www.netz39.de/2014/installation-of-wordpress-in-a-subdirectory-with-nginx/