最近由于原先博客主机极度不稳定,所以准备了很久,准备进行主机迁移。由于迁移前的环境和迁移后还是有较大的区别,整体架构也不太一样,所以在这里说说迁移过程中遇到的问题。
环境对比
原主机 | 新主机 | |
操作系统 | CentOS 6 | CentOS 7 |
Web 服务器 | Apache 2.2 | Openresty 1.9.7 + Apache 2.4 |
PHP 版本 | 5.5 | 5.6 |
其他 | SELinux |
SELinux
很多人为了省事,在拿到主机的第一时间就直接禁用了 SELinux。不过在学习了一段时间之后,我发现其实 SELinux 是一个很好的保护机器的手段。
这里简单列举几个需要注意的 SELinux 的配置:
httpd_can_network_connect_db boolean 类型,控制 Apache 是否可以连接 DB http_port_t port 类型,控制 Apache 可以监听的端口 mysqld_port_t port 类型,控制 mysql 可以监听的端口和 Apache 可以连接的 DB 端口
由于我是将 Apache 作为只解析后端 PHP 请求使用,所以需要修改 http_port_t 加入我需要的端口。添加方法类似于:
semanage port -a -t http_port_t -p tcp 8090
另外由于我没有在本机安装 Mysql 而是使用的远程 Mysql 实例,并且开放的端口并不是标准的 3306,所以需要将端口号添加到 mysqld_port_t 中。
Apache
这玩意是主要的坑所在。下面来一一列举。
配置格式变更
Apache 2.2 和 2.4 的配置文件区别还是比较大的,加了很多新的参数,同时修改了很多配置的方法。最明显的是:
Options -Indexes Allow from all Deny from all
这三条配置已经完全被改掉了。如果在配置中出现第一种,会直接起不来。后面的 Allow Deny 的写法虽然不会有问题,但是已经不是官方推荐的了,建议改掉。
配置无效
在配置 Apache 2.4 的 Log Format 的时候,我发现了一个很蛋疼的问题,就是 CentOS yum 安装的版本(2.4.6)有些配置是使用不了的。如:
http://httpd.apache.org/docs/2.4/mod/mod_log_config.html
这个文档中的:
%{UNIT}T The time taken to serve the request, in a time unit given by UNIT. Valid units are ms for milliseconds, us for microseconds, and s for seconds. Using s gives the same result as %T without any format; using us gives the same result as %D. Combining %T with a unit is available in 2.4.13 and later.
很多参数都有类似的标注(available in 2.4.13 and later),告诉你在旧版本中不能使用。如果不仔细看的话很容易忽略。所以配置之前一定要仔细阅读。
HTTPS
WordPress
由于我的博客是全站 HTTPS 的,因此在 WordPress 上我是有做一些强制 HTTPS 的措施。但是!由于 WordPress 默认的检测 HTTPS 的方法是这样的:
/** * Determine if SSL is used. * * @since 2.6.0 * * @return bool True if SSL, false if not used. */ function is_ssl() { if ( isset($_SERVER['HTTPS']) ) { if ( 'on' == strtolower($_SERVER['HTTPS']) ) return true; if ( '1' == $_SERVER['HTTPS'] ) return true; } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { return true; } return false; }
而我的 HTTPS 是在 Nginx 层做的,所以导致这两个条件均不满足,因此会遇到重定向循环(Redirect Loop)的问题。解决方法有两种:
修改 wp-config.php 文件:
if ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ( 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) { $_SERVER['HTTPS'] = 'on'; }
这里的修改需要配合修改 Nginx 的 Proxy 设置,增加下面这行:
proxy_set_header X-Request-Protocol $scheme; #http or https
修改 wp-includes/functions.php 文件(4025行左右):
找到上面说的那段代码,将其替换为:
/** * Determine if SSL is used. * * @since 2.6.0 * * @return bool True if SSL, false if not used. */ function is_ssl() { if ( isset($_SERVER['HTTPS']) ) { if ( 'on' == strtolower($_SERVER['HTTPS']) ) return true; if ( '1' == $_SERVER['HTTPS'] ) return true; } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) { return true; } elseif ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && ( 'https' == $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) { return true; } return false; }
同时这个修改方法也要配合修改 Nginx 的 Proxy 设置。
注意,虽然可以不做判断直接无脑 $_SERVER[‘HTTPS’] = ‘on’; 或者在那个 is_ssl() 方法中无脑返回 true,但是不建议这样修改。因为这样可能会导致安全上面的问题。
Apache .htaccess
由于我在某些目录中通过 .htaccess 的方式强制重定向了非 HTTPS 请求,因此在将 SSL 交给 Nginx 之后相关的跳转判断也要修改。原先的跳转逻辑是:
RewriteEngine on RewriteCond %{HTTPS} !=on RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [L,R]
由于 %{HTTPS} 这个变量判断的是 Apache 传进来的内部参数,我们无法控制,所以需要将这段修改为:
RewriteEngine on RewriteCond %{HTTP:X-Request-Protocol} ^http$ RewriteRule ^(.*) https://%{SERVER_NAME}/$1 [L,R]
这里判断的就是 Nginx 传进来的 X-Request-Protocol 头了。不过这种写法并不能在单独使用 Apache 作为 Web 服务器的时候使用,需要注意。
客户端证书
目前只针对某目录或文件的客户端证书配置还没有测试完成,将在后面更新。
使用 Nginx 反代 Apache 安装 WordPress by 桔子小窝 is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.