wordpress是应用很广泛的CMS系统。无论是用作博客或者是安装自定义的主题来建站,用起来都是很简单,而且自定义主题的开发也容易上手。近期因工作需要开发一个wordpress的主题来建站,发现wordpress代码比较老,需要兼容的情况很多。API一致性很差,经常做同一个功能有多个相似的api,而且名字看起来差不多,但参数却差别很大。这些都还算好的,遇到一个比较大的问题是,wordpress里必须配置主站的域名(也就是在wp-admin需要配置的url),而且mysql的数据里充斥着hard code的url。这给数据迁移和反向代理带来了很大的不便。这次是由于安全的原因,我只能把wordpress假设在反代后面,就这么一个小小的改变,我发现wordpress死活水土不服。
下面记录下配置的要点,方便以后查看。我使用的服务器是nginx,反向代理的服务器也是nginx。
一般情况
一般情况我们架设wordpress 的结构是这样的:
HTTP请求 + | +--------------------------------------------+ | | | | +-----------------v----------------+ | | | | | | | Nginx | | | | | | | +-----------------+----------------+ | | | | | +-----------------v----------------+ | | | | | | | wordpress | | | | | | | | | | | | | | | | | | | +-----------------+----------------+ | | | | | +-----------------v----------------+ | | | mysql | | | | | | | +----------------------------------+ | | | | | +--------------------------------------------+
而配置域名方面也比较简单,主要是两处
- nginx 的配置 nginx.conf
server_name www.example.com
- wordpress wp-admin中的设置
其实这第二步就稍显多余,为什么wordpress不能都使用相对路径?如果大家多次修改后wp-admin进不去,可参见直接修改数据库。
反向代理的情况
这个时候wordpress的架构是这样:
HTTP请求
+
|
|
|
+--------------------------------------------+
| | |
| +-----------------+---------------+ |
| | Nginx Reverse Proxy | |
| | | |
| +-----------------+---------------+ |
| | |
+--------------------------------------------+
|
|
|
|
+--------------------------------------------+
| | |
| +-----------------v----------------+ |
| | | |
| | Nginx | |
| | | |
| +-----------------+----------------+ |
| | |
| +-----------------v----------------+ |
| | | |
| | wordpress | |
| | | |
| | | |
| | | |
| | | |
| +-----------------+----------------+ |
| | |
| +-----------------v----------------+ |
| | mysql | |
| | | |
| +----------------------------------+ |
| |
| |
+--------------------------------------------+
理论上我不就是在外面加了个反向代理,我就把两个nginx的配置改下应该就可以了吧?
- Nginx Reverse Proxy
server_name www.example.com location / { proxy_pass http://<Wordpress-Server-IP>:<Port> #Proxy Settings proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
- wordpress 服务器的Nginx 配置
listen <Port> server_name localhost
可惜只是理论上应该这样。只配置了这两个,wordpress 是仍然不能工作的。经过反复调试,不是反向代理服务器返回500错误,就是wordpress的redirect不正常。
经过多次搜索研究,还要配置下面两步
-
清理mysql的数据
把hard code的数据url 给改成过来,确保不存在域名不正确的url。比如: localhost:<Port>/xxx 这样的url在数据库, 都需要改成 www.example.com/xxx 。大家可以使用 Search-Replace-DB 这个工具,来替换数据库。
-
改PHP代码手动设置反向代理的HOST,因为 wordpress的核心开发者说:让wordpress支持反向代理不是他们的责任
核心思想就是要让 PHP代码知道反向代理转发的域名是什么,然后强制地在每个页面里动态设置。
第一步 Nginx Reverse Proxy 配置改为
server_name www.example.com location / { proxy_pass http://<Wordpress-Server-IP>:<Port> #Proxy Settings proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
加了 X-Forwarded-For 。
第二步 修改 wp-config.php 的代码,添加如下部分
if ( ! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] ) ) { $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; }
修改了以上的内容,wordpress 的反向代理才能真正工作起来。
总结
综上所述:让wordpress支持反向代理一共有五步
- 反向代理服务器需要配置域名,并且需要配置 X-Forwarded-For 。
server_name www.example.com location / { proxy_pass http://<Wordpress-Server-IP>:<Port> #Proxy Settings proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
- wordpress的服务器,配置server_name 为 localhost 和端口号。
listen <Port> server_name localhost
- wordpress 的wp-admin里要设置成域名,而不是localhost或者wordpress server的IP。
- 要在 wp-config.php 修改里 HTTP_HOST 。
if ( ! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] ) ) { $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST']; }
- 【可选的】用 Search-Replace-DB 来检查替换数据库,确保数据库里不存在域名不正确的url。
附录
在wp-admin进不去的情况下,操作 wp_options 数据库表, 来更新wordpress的域名
msyql -u xxx -p # 连接数据库。 > use wordpress; # 使用数据库 > update wp_options SET option_value='http://www.example.com' WHERE option_name='home'; > update wp_options SET option_value='http://www.example.com' WHERE option_name='siteurl'; > quit