云服务器搭建WordPress踩坑记录

很久之前就有建站的想法,但是一直在犹豫。这次终于下定决心,买了一个顶级域名,又用学生优惠在阿里云买了一台轻量应用服务器。虽说选择国内的主机会多出一些备案的步骤,但是毕竟有优惠的价格、更快的访问速度,加之我也不赶时间,所以还是选择了国内的机房。

起初,我照着教程手动编译安装了 LAMP,花了一晚上编译和安装,结果在配置 HTTPS 的时候不小心把 httpd 搞坏了,自己又没有能力修理,无奈只好重置了系统。第二次,我尝试了一下LNMP一键包,发现非常符合我的需求,既可以用一行命令完成各种配置,又没有附带一堆花哨的服务。下面我会罗列出几个我在配置过程中遇到的问题和对应的解决方案。

修改服务器主机名和SSH端口

默认的主机名是一串随机字符,看着不是很爽,遂修改之(将 [主机名] 替换为你想要的主机名):

hostnamectl set-hostname [主机名]

另外,为了安全起见,修改一下 SSH 的端口。运行以下命令编辑配置文件:

nano /etc/ssh/sshd_config

找到 #Port 22 字样,在下面添加一行 Port [SSH端口](将 [SSH端口] 替换为你想要的端口),如下:

#Port 22
Port [SSH端口]

保存,重启 SSH 服务即可生效:

systemctl restart sshd.service

如果无法访问,那可能是被阿里云的防火墙阻挡了,请前往控制面板打开相应端口。

切换到阿里云软件源

首先,运行以下命令备份原配置:

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

然后,下载阿里云的配置:

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

最后,重新生成缓存:

yum clean all
yum makecache

WordPress不能安装、不能下载主题和插件

这种情况的原因基本都是 WordPress 目录的权限设置不当——没有把属主和属组设置为 www(也有时候是 daemon),导致 WordPress 没有写入的权限。我们可以利用 chmodchown 命令解决这个问题。由于我的 WordPress 位于 /home/wwwroot/default,我使用的 Nginx 所使用的用户和用户组是 www:www,运行以下命令:

chmod -R 755 /home/wwwroot/default
chown -R www:www /home/wwwroot/default

另外值得一提的是,虽然当权限设置错误时,WordPress 会遇到问题,但 phpMyAdmin 依旧能正常运行。我猜测这是因为 phpMyAdmin 的功能是操作数据库,并不需要写入目录,所以不受影响。

卸载阿里云盾和云监控

卸载阿里云盾:

wget http://update.aegis.aliyun.com/download/uninstall.sh && chmod +x uninstall.sh && ./uninstall.sh
wget http://update.aegis.aliyun.com/download/quartz_uninstall.sh && chmod +x quartz_uninstall.sh && ./quartz_uninstall.sh
pkill aliyun-service
rm -rf /etc/init.d/agentwatch /usr/sbin/aliyun-service
rm -rf /usr/sbin/aliyun*
rm -rf /usr/local/aegis*
rm -rf /etc/systemd/system/aliyun.service
iptables -I INPUT -s 140.205.201.0/28 -j DROP
iptables -I INPUT -s 140.205.201.16/29 -j DROP
iptables -I INPUT -s 140.205.201.32/28 -j DROP
iptables -I INPUT -s 140.205.225.192/29 -j DROP
iptables -I INPUT -s 140.205.225.200/30 -j DROP
iptables -I INPUT -s 140.205.225.184/29 -j DROP
iptables -I INPUT -s 140.205.225.183/32 -j DROP
iptables -I INPUT -s 140.205.225.206/32 -j DROP
iptables -I INPUT -s 140.205.225.205/32 -j DROP
iptables -I INPUT -s 140.205.225.195/32 -j DROP
iptables -I INPUT -s 140.205.225.204/32 -j DROP

卸载云监控(不建议,卸载后将无法在管理面板查看内存和硬盘信息):

/usr/local/cloudmonitor/wrapper/bin/cloudmonitor.sh stop
/usr/local/cloudmonitor/wrapper/bin/cloudmonitor.sh remove && \
rm -rf /usr/local/cloudmonitor

exec()被禁用

如果在安装插件时,出现 exec() 函数被禁用的提示,只需要编辑 php.ini,找到 disable_functions,去掉 exec,重启 Nginx 即可。

更新失败。错误信息:此响应不是合法的JSON响应。

一切妥当,想要写一篇文章测试一下,却发现无法保存草稿,也无法提交。WordPress报错:

更新失败。错误信息:此响应不是合法的JSON响应。

根据这篇文章的解释,我需要配置 Nginx 的伪静态。LNMP 的脚本在添加”虚拟主机(vhost)“时就有一个”伪静态“的选项。由于备案还未完成,我的 WordPress 暂时使用了”默认主机“。所以稍微研究了一下 Nginx 的配置文件规则。

稍稍阅读了 Nginx 的配置文件,发现虚拟主机和默认主机的配置基本是一致的,都是 server {} 的格式。我的理解是,虚拟主机是除默认主机之外额外的服务器,可以配置不同的根目录、不同的 SSL 证书等;不同主机之间使用域名、端口来区别。因为都在同一个 Nginx 里面,是”虚拟“出来的主机,所以叫虚拟主机。

参考这篇文章,可以发现只要在默认主机的配置里面加一个 include 来引用 LNMP 自带的 WordPress 规则就可以实现默认主机的伪静态。我顺便看了一下 rewrite/wordpress.conf 这个规则,发现里面只有短短几行:

location / {
	try_files $uri $uri/ /index.php?$args;
}

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

所以我就干脆把这几行直接复制到了 Nginx 配置文件中,这样和 include 这个文件是等效的。重启 Nginx,发现 WordPress 不报错了。问题解决!

至于伪静态的定义,知乎上已经解释得很白话了,这里就不再赘述。

添加HTTPS支持、设置自动跳转

过了大概两个礼拜,网站终于通过了 ICP 备案,可以通过域名访问了。我开始配置 SSL 证书。SSL 证书的话,我选择的是 LNMP 支持自动签发、续签的 Let’s Encrypt 证书。进行这一步操作有一个前提,就是服务器的 80 端口能够通过域名访问(为了能够证明服务器和域名是你的)。因为备案通过前服务器不能用域名访问,所以部署 HTTPS 也得在备案后进行。

备案通过后,我就开始部署 HTTPS。首先利用 LNMP 脚本创建虚拟主机:

lnmp vhost add

在接下来的向导中,domain 一栏我写了 www.[域名]more domain name 一栏我写了 [域名](将 [域名] 替换为你的域名)。Nginx 能够通过 HTTP 头中的字段判断出请求的域名,并以此选择匹配的主机来响应。这样配置,www.[域名][域名] 的请求都可以访问 WordPress。接下来的几项参考截图填写即可:

这里的 rewrite rules 其实就是 include 了之前我们复制到主配置文件的 rewrite/wordpress.conf 中的规则。这次我们让 LNMP 自动配置即可,不需要我们自己去include 或者复制了。最后我们看到 LNMP 已经完成了配置,按下任意按键就会开始自动申请并部署 SSL 证书。

很快虚拟主机就可以使用了,我们这个时候需要把 /home/wwwroot/default 里的所有文件(注意,需要排除 .user.ini 这个文件)复制到 /home/wwwroot/www.[域名].conf 中。

另外,我还希望 HTTP 能够自动跳转到 HTTPS,请求域名不带 www 时能够自动加上 www。所以我对 Nginx 主配置文件(nginx.conf)和虚拟主机配置文件(vhost/www.[域名].conf)进行了如下修改——

在 Nginx 主配置文件(nginx.conf) 中找到唯一的 server {} 片段,在最后加上一句:

rewrite ^(.*)$ https://www.[域名]/$1 permanent;

如果一个请求不匹配任何虚拟主机的条件(比如用 IP 访问),它就会被默认主机处理。这个语句意思就是直接跳转到 https://www.[域名]/

再来到虚拟主机配置文件(vhost/www.[域名].conf),找到第一个 server {} 片段,从 listen 80 可以看出这是负责 HTTP 的虚拟主机,在最后加上一句:

rewrite ^(.*)$ https://www.[域名]/$1 permanent;

与上面的情况相似,这个语句能够把所有 HTTP 请求重定向到 HTTPS 上,也就是所谓的强制 HTTPS。

最后,找到第二个 server {} 片段,从 listen 443 ssl 可以看出这是 HTTPS 的虚拟主机。在最后加上一句:

if ($host != 'www.[域名]'){
    rewrite ^(.*)$ https://www.[域名]/$1 permanent;
}

这个语句检查请求的域名,如果不带 www,就会重定向到带有 www 的域名上来,也就是自动添加 www。

重启一下 Nginx。 最后一步,打开 WordPress->设置->常规,设置一下站点 URL 即可。

无法删除 .user.ini

在删除 .user.ini 文件时,会报错 rm: cannot remove '.user.ini': Operation not permitted。这是因为该文件具有不可更改(immutable)的属性,可以使用命令取消不可更改属性:

chattr -i .user.ini

现在就可以正常删除 .user.ini 文件了。