网络服务配置笔记:WordPress w/ SSL on Ubuntu w/ Nginx, PHP and MySQL

这次重新开站,暂时以这个博客打头阵(实际上好像也只有这个),方便自己乱丢一些文字在上面。以前的备份是2013年初的,这次的开站除了配置几个网络服务之外,也涉及到从旧WordPress的数据备份恢复并升级到最新版,这个过程也是很有趣的,一并写在这篇日志里。

注意:这篇内容,是为我方便所记录,有很多地方不涉及严格的考究和选择,代码部分亦可能存在纰漏,酌情参考,小心使用!

一套网络服务的配置,涉及服务器系统、网络服务器端软件、系统相应账户的配置和网络服务的配置。一个搜索可以找到很多XXX VPS提供商网站就有提供相应的教学,我主要翻看了Digital OceanLinode这两家的。这样来看,如果删掉这些啰嗦的、随意的文字,这篇日志也可以起名叫做“Use Your Old WordPress Backup to Build a New Site”,“Install or Upgrade WordPress on Ubuntu 16.04”,“Setup an LEMP environment with HTTPS support on XXX”等等了。后面内容的目录如下:

这篇日志里涉及到的软件版本在书写时如下:

Version
Ubuntu16.04 LTS
Nginx1.16
PHP7
MySQLServer/Client5.7
CertBot0.31

说起来,版本这个东西,一般都在功能配置和解决一些问题时候显得有用,在这篇日志里。在书写时,除Nginx和CertBot采用的是其官方的包系统,其他软件都依赖系统发行版的官方软件包提供,所以版本都不是软件官方最新的。虽然如此,使用起来基本上没什么大问题(Ubuntu LTS的意义也就在此了)。

启用一台Internet可访问的服务器

现在启用一台可以被Internet访问的服务器的方式多了很多,除了经久不息的共享虚拟主机(shared virtual host)和独立服务器(dedicated server)之外 ,还有虚拟专用服务器(virtual private server,VPS)等等。近几年,VPS放在“云”上,也就有了云服务器(cloud server)。 我用过的服务商不是很多,结合我的使用体验和网上看到的一些评测,简单总结一下VPS服务,局限和出错是在所难免的。 还有,可以参考在VPSBenchmarks提供的一些主流的VPS提供商的评测

业内比较大的云服务商,国际如Amazon Web Services(AWS)、Google Could Platform(GCP)和Microsoft Azure等,国内如阿里云腾讯云美团云等都有提供VPS服务,共享虚拟的和独立专用的都有。在各自的协议和规则下,各家也有一些免费的实例可以使用。除了几家著名大公司的服务之外,第二梯队也有一些名声很好的公司提供云计算服务,如Digital Ocean等。除了云VPS之外,这些服务商还提供建立云的多种相关服务,比如自建内网、存储等。总的来说,这些专业的服务商所提供的云服务,确实也都是适合于去建立专业的云的:多节点,复杂的内、外网划分,将不同的服务(web、数据库、负载均衡、日志、存储等)部署在不同的节点上,具有详细的访问权限控制等。

所以,还是那些操控相对简单的小一些的服务商更适合我这次的需求。也就是说,只需要完成“注册—加购—付款”,就可以即时启动一台服务器。这一类的服务商中,名声大一些、相对好一些的有老牌的LinodeVultrBandwagonOVHRamnode等。和那些超专业的大型服务商不一样,他们采用的技术相对简单一些,也容易上手,基本都是可以满足“只需要完成‘注册—加购—付款’就可以即时启动一台服务器”我这个需求的。

谈到“虚拟专用服务器”中的“虚拟”,应当对几种虚拟技术的优劣进行对比后再进行选择。既然我不是“专业”去做什么,也不必要那么要求严格,而大概的准确就差不多可以了。

一般用来提供VPS服务的虚拟技术,可以分为硬件虚拟化技术操作系统层面的虚拟化技术。一般这些小型服务商基于硬件虚拟化技术来提供服务的技术有KVM、Xen等,所虚拟的操作系统运行在自己的内核上,使用者可以有完整的控制;通过操作系统层面的虚拟化技术的有OpenVZ、LXC等,所虚拟的操作系统运行在虚拟平台的内核之上,使用者没有完整的控制,部分内核参数无法直接更改。

在知道了几家公司采用的虚拟化技术之后,则需要根据自己的需求来确定VPS规格,再结合价格来做选择。上面所列几家公司给的配置和价格都差不多,考虑到之前一直选了Ramnode家的服务,在加上有IPv6的需求,就继续选择了Ramnode。关于OpenVZ还是KVM以及硬件配置的选择,我是根据下面这几点做决定的:

  • Web服务,而且是我自己“娱乐”或者说“兴趣”的,也只是为我自己服务,不会有访问量的压力,硬件配置不需要很高,但需要安装并运行MySQL服务,则内存512MB起步。
  • 传说KVM比OpenVZ隔离性更好,但我没有很需要这个隔离性,况且是“传说”(大概因为我没仔细找到来源);不过KVM更稳定一些应该是真的,但稳定不稳定都是在服务提供商那边来说的,只要那边响应够快,处理够及时,应该不是大问题。Google一下一大堆
  • 因为KVM虚拟的系统具有完整的内核,内核也是运行在所选择的硬件配置之上的,所以与之相比,同配置的OpenVZ虚拟的系统获得的可使用的资源更多,因为OpenVZ所虚拟的系统的内核运行在OpenVZ主服务器上。

因此,我选择了一款内存1GB+4核CPU的OpenVZ产品。选地点也是有点意思的事,主要用MTR和下载大文件的速度来“考核”,从教育网、联通、移动这3种连接(手头没有电信连接),分别在一天的不同时候测试几个不同地点的服务“质量”。

选好了规格,“注册—加购—付款”很快完成,这台VPS就已经在运行了。通过Ramnode的控制面板可以做重装系统、设置root密码、配置IPv6地址等操作。最终,得到了一台IP地址是a.b.c.d/[a:b:c:d::1]root账户密码是***、运行Ubuntu 16.04 LTS的VPS。

配置域名解析服务(涉及部分SSL证书讨论)

好多年没有用过别家的域名解析服务了,一直在用DNSPod.cn的服务。因为服务器已经不在国内,也就没有需求要解决四大运营商带来的网络隔阂了(现在是不是已经没有了隔阂?)。也就是说,其实不需要再用DNSPod.cn的服务了。一直也想着把还有个域名转出来,到GoDaddy或者Google那里。再加上DNSPod现在属于腾讯了,总有点不太放心的感觉。虽然有这么多不太满意的地方,但国内的DNS解析商还应该算是第一选择吧,因为在国内解析起来快很多。(但是服务器在国外,还是会慢,还不如把DNS也放到外面,速度也不会有很明显的变慢。)

域名解析一般都很好设置。如果是在域名注册商那里管理的域名,直接在注册商提供的管理平台,为域名和子域名添加A记录指向a.b.c.d,添加AAAA记录指向[a:b:c:d::1]就可以了。如果是在第三方的域名解析商那里管理的域名,要先在域名注册商提供的管理后台处,确认已经将域名的域名解析服务器(name server,ns)指向了域名解析商所提供的地址,之后就可以在域名解析商那里操作了,添加相应的A记录和AAAA记录。

至此,我遇到两个问题,一个是多个IP地址和多个(子)域名的解析管理问题,一个是是否要换用Cloudflare的解析服务。

针对第一个问题:实际情况是我手头有几台VPS,每台有多个IP地址(IPv4和IPv6地址)。现在如果考虑这几个情况:服务商更换IP地址、根据情况我自己切换IP地址(一般是IPv6地址,因为手上的VPS每台都有/64的地址块)和Web服务切换服务器(也就涉及到切换IP地址)。那么也就是说,第一个问题实际上是:指向提供Web服务的域名的解析,使用A/AAAA解析,和使用CNAME解析,哪种更好一些。比较两者孰优孰劣,可以通过比较两种解析方式的速度和管理便捷度来看:

  • 解析速度:由于A/AAAA记录指向的是IP地址、CNAME记录指向的是域名,那么,在解析一个CNAME记录的时候,DNS服务器要比解析A/AAAA记录至少多一次查询。从一些使用经验得知,这增加的一次查询一般不会产生很大的延迟感。因此,针对解析速度而言,使用A/AAAA记录和CNAME记录相差不大,采用CNAME记录带来的性能降低可以忽略。
  • 管理便捷度:上面提到,实际情况是几台VPS有很多IP地址。假设有一个提供多个Web服务的VPS的IP地址发生变动,如果使用了A/AAAA记录方式的解析,那就需要把涉及到这个被改动的IP地址的域名记录全部更改;但如果使用了CNAME记录方式的解析,只需要更改CNAME记录所指向域名的A/AAAA记录就可以了。这也是一些拥有大型集群的公司所采用的域名管理方式之一,比如Google(好像应该有个“来源请求”一类的东西?)。

针对第二个问题:是否使用Cloudflare的解析服务,可以换由解答以下2个问题来解决:

  • 是否单纯需要使用Cloudflare的解析服务:对于我来说,实际是不需要的,因为前面说道我一直在用DNSPod.cn;其次,是否用Cloudflare的解析可以通过考虑其解析功能设置能力(应该是不错的)和解析速度(应该算相当快的),再考虑到它还提供了1.1.1.1的公共DNS解析服务器,使用他家的域名解析服务应该是不错的选择。
  • 是否需要使用Cloudflare的其他服务:这里的其他服务主要是指CDN和SSL证书。如果使用这些服务,要求将域名解析迁移至Cloudflare。CDN服务我没仔细读,但我这个小站点,我觉得没必要用CDN。SSL服务则涉及到Cloudflare多种多样的HTTPS模式,在“HTTPS设置和网站证书申请”会详细讨论SSL服务的选择;而我初步认为我一个小站点也不用大费周章,用一些免费的SSL证书就可以了(虽然Cloudflare的“半”SSL也是免费的)。

综上,我选择继续在DNSPod.cn上做域名解析,同时域名分为两组:第一组域名解析为A/AAAA记录,对应指向各个VPS/IP地址;第二组域名是供访问Web服务的域名,解析为CNAME记录,根据需要指向第一组中对应的域名:

  • A记录:web1.servers.com => a.b.c.d
  • AAAA记录:web1.servers.com => [a:b:c:d::1]
  • A记录:web2.servers.com => a.b.c.d
  • CNAME记录:site.com => web2.servers.com
  • CNAME记录:blog.site.com => web1.servers.com
  • CNAME记录:a.hosting.cn => web1.servers.com
  • CNAME记录:b.hosting.cn => web1.servers.com
  • CNAME记录:c.hosting.cn => web2.servers.com

服务器端操作系统安装和配置

由于是OpenVZ的虚拟方式,服务器操作系统安装就很简单了。只需要在服务商提供的面板里选择好Linux发行版,点一下等几分钟就可以安装好。之后在面板里为root更改一个临时的密码,然后SSH连接到VPS就可以接着在上面配置。为VPS加固安全的设置,放在以后来写,先做一些简单的配置。

SSH登录root之后,更新系统和软件包:

apt-get update
apt-get upgrade

为VPS做一些简单的测试,比如查看配置、硬盘I/O性能、网络连接性能等。有很多现成的脚本,可以直接拿来用。最简单的是在bench.sh上提供的测试脚本:

wget -qO- bench.sh | bash

除此以外,也可以在VPS上试试Speedtest by Ookla提供的测速服务。Speedtest官方没有提供适合VPS使用的Apps,但有一款开源的Python脚本可以实现,也提供了很多参数用于调整速度测试。可以在GitHub上查找到speedtest-cli,项目页面也提供了参数的使用介绍。假设已经有Python解释器:

# 下载最新脚本
wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
# 设置权限
chmod +x speedtest-cli
# 执行测速
./speedtest-cli

我这里操作系统默认安装并开启了Apache HTTP Server。因为我要用Nginx,所以要关掉(并卸载?)Apache。另外还有一个Postfix也是启用状态,是一个邮件服务器,对我没有用,就一并禁用:

# 停止并禁用Apache
service apache2 stop
systemctl disable apache2
# 停止并禁用Postfix
service postfix stop
systemctl disable postfix
# 检查服务状态
systemctl is-enabled apache2
systemctl is-enabled postfix

确认hostname的设置(应该不是必须要做的), 设置有问题就需要改一下,可以参考日志开头提到的一些VPS服务商提供的教程[Linode1Linode2]:

# 查询短域名
hostname
# 查询长域名(FQDN)
hostname -f

接下来设置操作系统时区。据说新版Ubuntu有一些更新的包设置时区很方便(来源暂时找不到了),但据说还是用下面的方法更好些:

dpkg-reconfigure tzdata

需要注意的是,如果选用GMT时区,用“+/-”标志时区的符号是与其由UTC时间算起的时间差符号是相反的,原因是需要与POSIX标准统一。具体可以咨询有关的Wikipedia页面[tz数据库-时区列表]和一个关于Ubuntu设置时区的讨论。也就是说UTC+8区对应的是Etc/GMT-8,有趣吧~

系统用户账户配置

这部分跟后面几节内容是紧密相关的,用户账户是对服务器进行有效和安全的管理的前提。因为大多数VPS系统安装好之后,默认存在的是root这个“超级用户”,既不安全,也不适合多用户使用。这一节的的内容,根据这篇针对Apache/Web服务器文件/文件夹权限的讨论,做了更改和适配。

对于不同的用户使用场景,对服务器用户和文件/文件夹权限的配置是应有所不同的。但是,在不安装附加软件的前提下,满足既安全、又方便管理的配置方法却似乎是不可能的。因此,除了使用文件/文件夹的所有权和权限控制访问之外,也会再使用ACL加以辅助,而实际上ACL应当是相对来说比较有效的管理工具。

因为我是个懒人,设置和维护起来越简单越好,那么就不考虑ACL了;同时考虑到需要经常更新系统和软件包,也不考虑更改系统服务的配置文件(系统/软件的更新有可能会覆写服务配置)。这样,就没法使下面的配置是最好、最合适我的。退而求其次,在保证能用的基础上,做到尽量安全,这是这一节的目标。接下来从具体的需求出发,经分析之后,得到用户组和文件/文件夹权限设置规则。首先是需求,可由以下几点表述:

  • Web服务专用用户/用户组:默认安装的Nginx会创建用户nginx和用户组nginx;Nginx主进程(main process)由root创建,之后根据配置和Web服务器运行状况创建多个工作进程(worker process),而worker进程以根据配置文件所设置的用户/用户组创建,一般以nginx用户创建worker进程。
  • PHP/PHP-FPM:安装PHP/PHP-FPM不会创建其他的用户和用户组,一般FPM以Web服务的用户和用户组运行。如果FPM使用Unix路径接口进行监听,则接口监听用户和用户组需要设置,一般也为创建Web服务进程的用户和用户组。
  • MySQL Server提供访问接口,而用户和权限则由MySQL设置,因此不属于这部分的考虑内容。
  • 这台VPS上预计放置多个以顶级域名(top-level domain,TLD)结尾的域名及其子域名的Web站点,即有*.site.com*.hosting.cn
  • 预计每个TLD域名的Web站点都各自可能有多人管理,即userSiteComAuserSiteComB管理site.com,而userHostingCnAuserHostingCnB管理hosting.cn
  • 管理Web站点的用户不需要具有管理员权限(root)。
  • 管理同一个TLD的站点的用户需要读写该TLD下所有站点文件/文件夹,不能读写别的TLD下站点的文件/文件夹。最好也不能读写除所管理TLD的站点文件夹之外的其他文件和文件夹。(这篇日志里暂时做不到这点。)

根据上面的需求,可以得到一种较为理想的配置(很有争议、可根据具体情况酌情调整的条目前加了*):

  • 根据VPS管理的人数,建立至少一个具有root权限的管理员用户。这里建立一个管理员用户admin,取代root而作为日常管理使用。
  • 为每一个TLD的所有站点建立一个根文件夹,并在根文件夹建立两个子文件夹:“htdocs”用于放置Web页面/脚本/资源,“logs”用于放置各种相关的日志文件。子域名对应站点的Web文件,则在“htdocs”内建立对应的子文件夹。
  • 对应每个TLD建立用户组:grpSiteComgrpHostingCn
  • 根据实际进行站点管理的个人,建立用户:用户主目录(home)指向其管理的TLD的根文件夹,用户组则指定为刚才建立的用户组。
  • *每个TLD的站点的根文件夹的所有者(owner)指定为“我”即adminroot
  • 每个TLD的站点的根文件夹的用户组所有者指定为该TLD对应的用户组,即grpSiteComgrpHostingCn之一。
  • 每个TLD的站点的根目录下的所有文件、各级子目录和各级子目录下的文件:
    • 为根目录和各级子目录设置setgid权限。
    • 为管理该TLD的用户设置umask=007。由于默认新文件权限666,新文件夹权限777:那么这些用户建立的文件的用户所有者为文件建立者、文件的组所有者为该TLD对应的用户组,权限为660(即u=rwg=rw);这些用户建立的文件夹的用户所有者为文件建立者、文件夹的组所有者为该TLD对应的用户组,权限为770u=rwxg=rwx)。
    • *对于已有文件/文件夹,可以设置用户所有者为“我”即admin或者root,或其中一位组员,如果其所有者不是该TLD对应用户组之中的用户。
  • 为使“我”可以访问和管理这些文件,需要将“我”即admin加入对应的用户组中。
  • 为使Web服务器Nginx可以读取资源以及写入log,需要将用户nginx加入对应的用户组中。

这里所说的“较为理想”的配置,只是对于我的需要而言是理想的。对于不同的场景,会有不同的配置方案,可以参考上面提到在ServerFault的链接。接下来就来操作吧:

# 建立用户admin,并设置为sudoer
adduser admin
adduser admin sudo

# 建立blog.site.com和a.hosting.cn的Web文档目录,
# 并为各自的TLD建立存放log的文件夹
mkdir -p /var/www/site_com/htdocs/blog_site_com
mkdir -p /var/www/site_com/logs
mkdir -p /var/www/hosting_cn/htdocs/a_hosting_cn
mkdir -p /var/www/hosting_cn/logs

# 设置TLD对应根目录的setgid权限
chmod g+s /var/www/site_com
chmod g+s /var/www/hosting_cn

# 设置所有子目录的setgid权限
find /var/www/site_com -type d -exec chmod g+s {} \;
find /var/www/hosting_cn -type d -exec chmod g+s {} \;

之后是建立各个用户和用户组,为他们配置权限:

# 建立两个用户组,对应两个TLD
addgroup grpSiteCom
addgroup grpHostingCn

# 创建各个用户,这里省省事就各创建一个吧
adduser --home /var/www/site_com --ingroup grpSiteCom userSiteComA
adduser --home /var/www/hosting_cn --ingroup grpHostingCn userHostingCnB

接下来配置Web资源文件和文件夹的所有者和权限:

# 设置“我”,即admin,为每个TLD站点内所有文件/文件夹的用户所有者,
# 并设置对应的用户组为所有文件/文件夹的用户组所有者
chown -R admin:grpSiteCom /var/www/size_com
chown -R admin:grpHostingCn /var/www/hosting_cn

# 将Web资源文件权限设为660,文件夹权限设为770
find /var/www/site_com -type d -exec chmod 770 {} \;
find /var/www/site_com -type f -exec chmod 660 {} \;
find /var/www/hosting_cn -type d -exec chmod 770 {} \;
find /var/www/hosting_cn -type f -exec chmod 660 {} \;

最后,需要设置Web服务器Nginx的运行时用户的权限,以及“我”这个管理员:

# 将Nginx安装时默认添加的用户nginx加入用户组grpSiteCom和grpHostingCn中
# 由于可以将PHP-FPM以用户nginx的身份运行,则不必对它做其他的权限配置,
# 只需要注意写好PHP和PHP-FPM的配置文件就好了
adduser nginx grpSiteCom
adduser nginx grpHostingCn

# 将“我”也加入用户组中,这样“我”才可以不以root身份运行时管理这两个文件夹里的内容
adduser admin grpSiteCom
adduser admin grpHostingCn

这样,除了umask=007的配置,其他项目基本就按照前面所提到的需求配置好了,这样作用的好处有:

  • 可以保证某组的文件不被其他用户组的成员访问,也可以不被其他无关用户访问,在服务器端防止了数据泄露,当然这没法防止通过Web服务器层面的访问
  • 可以保证“我”这个超级管理员的无限访问
  • 可以保证Web服务器以及PHP/PHP-FPM的正常读取Web资源并实现服务

既有好处,当然那也会有缺点:

  • 对于某些PHP脚本不够“友好”,或因为权限过于严格,或因为它们过于谨慎:
    • 如WordPress,虽然它对文件的权限一般要求是644,但若需要它的在线升级、安装模板和扩展程序则需要“该WordPress实例的文件所有者,是运行该实例的用户”,“运行该实例的用户”实际也就是运行PHP/PHP-FPM的用户(还是Nginx?)。当然,有一些其他的解法,比如通过修改WordPress配置文件等,原理解释解法都可以参考官方的文档。
    • (不确定)Drupal,我记得它需要数据库配置文件是644的,如果不是,就会一直提示还是什么来着。

大概对用户帐户的配置就是这样。如果还有更多,就是关于怎么更安全地使用帐户了,这个的话,有必要再单开一个小节来写,主要是SSH和SFTP的配置。此外,这里没有提到的是用户通过PHP脚本生成或者由Web界面上传这一行为,这样生成在服务器中的文件的文件夹所有者是对应TLD的用户组,但用户所有者却是Web服务器的用户nginx;其文件权限,对于Nginx来说,需要更改系统服务配置文件来实现,不够portable(如果系统程序包配置更改了,那又会带来麻烦),对于PHP/PHP-FPM来说,我还没找到怎么配置,或许也只有靠Nginx了?所以,在这小节就略过了这些吧,连同还没写的对用户umask=007的配置。

从后面几节开始,就正式开始用“我”,即admin,这个管理员了。root一般情况不会再使用。

网络服务器端软件安装和配置

这一节聚焦于VPS服务器软件的安装和配置。我的目的是把旧的WordPress备份数据恢复并运行起来,因此至少需要Web服务器、PHP、以及MySQL/MariaDB服务器。Web服务器可选Apache HTTP Server,Nginx,Lighttpd等。PHP根据需要如果Web服务器使用了Apache,那么一般安装PHP的软件包和libapache2-mod-php包;如果选用了Nginx,则安装PHP的软件包和php-fpm包。MySQL和MariaDB选择一个就好,两个基本相同(通)的。如果觉得不够开源或者害怕受到Oracle的控制,那么就选MariaDB好啦,我想一定有人读过类似《选择XX的??条原因》之类的文章了。这里我选了Nginx和MySQL,那么下面的安装过程基本就是固定的了。

PHP/PHP-FPM

这几个软件包的安装顺序不是固定的,本身也没有相互依赖。而且常常会根据包的安装和配置情况,多次更改其他包的配置文件。因此,这篇日志里我先安装并配置了PHP和PHP-FPM,之后的Nginx就可以一路做下去了。

PHP除了从源码编译的安装方式,也可以从系统更新源安装PHP、PHP-FPM和常用模块。此外,Ubuntu LTS版本在过了功能更新期之后,这个版本的官方更新源里的软件包也就不会有较大版本(major version及minor version)的更新了。因此,也就会有一些个人/团体维护的PPA(personal package archives)会将最新版的PHP制成预编译安装包,供不再提供功能更新的LTS等版本使用。在添加PPA之后,安装预编译软件包方法和使用系统更新源的软件包安装方法是一样的,如可以参考众多PPA中的一个可用的Ubuntu PHP PPA

虽然Ubuntu软件包在过了功能更新期之后,就没有软件大版本的更新,但官方依然会提供各类bugfix,直到发行版的EOL(end of life)之前都是有保障的。因此我考虑用Ubuntu官方的软件包系统。Ubuntu的软件包大概可以分两种:一种是具体的软件包(包名里带版本号);另一种叫做meta package,是根据具体软件包的更新情况,一般指向最新的软件包或软件包的集合。看过一些讨论[12]之后,我决定直接安装具体的软件包。实际上安装哪种软件包呢,影响大不大呢,好像也不大。安装PHP,系统会把依赖也都一起装了:

sudo apt install php7.0-bcmath php7.0-bz2 php7.0-cli php7.0-common php7.0-curl php7.0-fpm php7.0-gd php7.0-imap php7.0-intl php7.0-json php7.0-mbstring php7.0-mcrypt php7.0-mysql php7.0-soap php7.0-xml php7.0-xmlrpc php7.0-zip

安装好之后,看一下PHP的配置文件:

/etc/php/7.0/
          |- cli/                # 命令行有关的,不操心
          |- fpm/                # 与Nginx配合的fcgi运行模式的FPM的配置
          |   |- conf.d/         # 与mod有关的配置文件,不操心
          |   |- php-fpm.conf    # FPM的配置文件
          |   |- php.ini         # PHP的配置文件
          |   |- pool.d/         # FPM运行环境池,可根增加新的FPM运行配置
          |   |      |- www.conf # 默认的为Web环境的FPM配置
          |- mods-available/     # mod有关的目录,不操心

一般来说,“php.ini”文件的修改会影响所有FPM实例的PHP运行参数。因此,若非有必要,我觉得不需要直接修改“php.ini”文件,在FPM的实例配置文件中覆写需要的参数。但一般来说(也是Nginx官方调优的推荐),应当在“php.ini”文件中修改一个参数:

cgi.fix_pathinfo=0

这样做的好处是,把PHP脚本文件路径传递给PHP解释器之后,解释器先检查路径是否存在。如果不存在,则不会根据路径去执行别的文件。

php-fpm.conf”应当是FPM的主配置文件,一般来说里面的参数也不需要修改。参照运行环境配置池里的“www.conf”,为site.com站点增加一个新的FPM配置环境:

sudo cp /etc/php/7.0/fpm/pool.d/www.conf /etc/php/7.0/fpm/pool.d/site_com.conf

修改这个FPM环境的配置文件“site_com.conf”:

# 查找“[www]”修改为:
[site_com]

# 设置创建FPM环境进程的用户和用户组
user = nginx
group = grpSiteCom

# 设置Unix path socket的监听地址
listen = /run/php/php7.0-fpm-site_com.sock

# 设置Unix socket的访问权限
listen.owner = nginx
listen.group = grpSiteCom

在文件末尾增加需要覆写的PHP参数设置(也可在“php.ini”中进行全局设置):

# 指定error_log位置
php_admin_value[error_log] = /var/www/site_com/logs/blog_site_com.fpm-php.log

# 上传大小设置
php_admin_value[upload_max_filesize] = 32M
php_admin_value[post_max_size] = 48M

这样,PHP和PHP-FPM就基本设置好了。其中重要的是创建FPM进程的用户和用户组,一般跟随Web服务器的设置(如PHP-FPM配置中,默认是Apache的运行时用户设置,即www-data)。其次,一般都要增大PHP中关于上传大小的设置,使得一些PHP程序如WordPress的上传功能、phpMyAdmin的数据导入功能等可以正常使用。

Nginx

Nginx可以选择从操作系统带的官方软件包系统安装,也可以选择从Nginx官方提供的包系统安装,或者直接从源码编译。如果从操作系统的包系统安装,那么就涉及到包维护者的决定,就很可能会在之后更新中,在包的配置方式、文件存放位置等方面发生改变,而且如果是时间较早的LTS发行版,软件包在过了那个功能更新期之后就不再有大版本的更新了,只是安全维护。而从源码直接编译又是很麻烦的事情,因而我选了从Nginx官方提供的包系统安装。在Nginx官网有详细的安装介绍,以及mainlinestable两种发行版的区别和选择。下面的安装命令就是复制和粘贴了:

# 安装软件包系统的依赖
sudo apt install curl gnupg2 ca-certificates lsb-release
# 增加Nginx软件包系统(stable发行版)
echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list
# 导入Nginx官方签名密钥
curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add -
# 验证签名密钥
sudo apt-key fingerprint ABF5BD827BD9BF62
# 可能的预期输出(一定包含“573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62”)
pub   2048R/7BD9BF62 2011-08-19 [expires: 2024-06-14]
      Key fingerprint = 573B FD6B 3D8F BC64 1079  A6AB ABF5 BD82 7BD9 BF62
uid                  nginx signing key <signing-key@nginx.com>

# 更新包系统并安装Nginx
sudo apt update
sudo apt install nginx

这时候在浏览器中输入http://a.b.c.d./http://[a:b:c:d::1]/应该就可以访问到Nginx的默认页面了。或者在SSH中通过curl访问localhost127.0.0.0.1也可以。下面的命令可以打印当前安装Nginx的版本和编译信息:

nginx -V

如果输出信息中含有“TLS SNI support enabled”的字样,那么很好,就可以在单一IP上配置多个HTTPS站点了。

Nginx的配置文件所在目录的内容大概是这样子的:

/etc/nginx/
       |- conf.d/                # http server configurations, 
       |                           all *.conf files are included 
       |                           in http block in "nginx.conf"
       |      |- default.conf    # default http server for localhost
       |- fastcgi_params         # fastcgi parameters
       |- mime.types
       |- nginx.conf             # Nginx main configuration file, 
       |                           i.e., the main section
       |- ...

Nginx默认的配置已经是一个“It works!”的配置了,但适配和调优是可以一直做下去的,目的是使Nginx的运行行为满足以当前服务器配置的情况下,适合不同的Web服务场景。详细和具体的调整,应当在准确理解官方文档所提供的模块配置“指令”和“变量”的解释下,参考一些调优“指南”[1234,……]来完成。

考虑到我这是一个没什么访问量压力的小VPS,况且硬件也不是很出色,因此对Nginx的调配就到一个just-so-so的程度就可以。这一节剩下的部分就分为两个配置,一是Nginx主配置文件(nginx.conf)的调整,二是对应某个TLD的HTTP站点配置。

首先是主配置文件(nginx.conf),其内容在官方文档和其他讨论中称为“main section”,以花括号“{}”包含的部分成为一个“block”,block中可以嵌套block。在main section中为Nginx多进程运行的参数提供定义,并包含events blockhttp block

# /etc/nginx/nginx.conf 一种配置

# Nginx的worker进程以nginx用户和nginx用户组的权限运行,
# 应回顾上一节对用户权限的讨论进行调整
user nginx nginx;

# 自动调整worker进程的数量和与CPU的关联
worker_processes  auto;
worker_cpu_affinity auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    # 一个worker进程可以处理的连接数
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    keepalive_timeout  10;

    # gzip与breach attack有关,一说不建议打开
    #gzip on;

    # 把Nginx一些默认页面和HEADER中的版本号去掉
    server_tokens off;

    include /etc/nginx/conf.d/*.conf;
}

之后为TLD建立配置文件:

sudo touch /etc/nginx/conf.d/site_com.conf
sudo touch /etc/nginx/conf.d/hosting_cn.conf

可以参考default.conf来书写这些TLD站点的配置文件。结合PHP-FPM的配置,site.com站点目前只包含一个待处理的WordPress站点,配置文件如下:

server {
    # 在所有IP和IPv6地址监听80端口
    # http2需要SSL才可以启用
    listen 80;
    listen [::]:80;

    # name-based 站点识别
    server_name blog.site.com;
    index index.html index.htm index.php;
    
    # Web根目录,参考用户权限配置一节的讨论
    root /var/www/site_com/htdocs/blog_site_com;

    # logging设置
    access_log /var/www/site_com/logs/blog_site_com.access.log main;
    error_log /var/www/site_com/logs/blog_site_com.error.log error;

    # 首先检查文件和路径是否存在,如果路径存在,则会以
    # 根据WordPress的适配路径,然后再以.php结尾的请求,
    # 等待其他 location 来捕捉请求
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # PHP配置,选择为site.com专门设置的Unix path接口
    location ~* \.php$ {
        fastcgi_pass  unix:/run/php/php7.0-fpm-site_com.sock;
        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME     $fastcgi_script_name;
    }

    # 对静态Web资源的优化
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        access_log off;
        log_not_found off;
    }
}

写好配置文件,经过Nginx的代码检查和重新加载配置文件之后,就可以在浏览器通过http://blog.site.com/访问站点了,预期得到的应该是一个404页面。

# 检查配置文件
nginx -t

# 重新加载配置文件
sudo nginx -s reload
# 或
sudo service nginx reload

关于HTTPS站点的配置,在下一节讨论过证书之后就很容易来做了。之后可以选择手动修改配置文件。

MySQL

MySQL提供了很多种安装方式,除从源码编译之外,还可以从官方下载各类deb预编译包进行安装、直接安装Ubuntu发行版的MySQL软件包、或在系统中添加MySQL官方软件包系统进行安装。考虑到Ubuntu发行版自带的软件包与系统亲和力最好,而且安装维护也最方便,我就不选择其他的安装方式了。

从Ubuntu发行版的包系统安装MySQL很方便:

sudo apt install mysql-server

这样,也将同时安装mysql-client等。安装过程中会提示设置MySQL数据库root帐户的密码。完成之后做一下简单的安全加固, 根据提示操作就可以了 :

sudo mysql_secure_installation

由于同时也安装了mysql-client,就可以在控制台上访问MySQL服务器了:

mysql -u root -p

按照提示输入之前为root帐户设置的密码就进入MySQL提示符界面了,之后就可以使用SQL语句进行各种查询、维护和管理操作了。不过我比较懒,倾向在桌面端图形化操作,可选一些GUI工具比如HeidiSQL。但为了安全,VPS上的MySQL服务器root帐户默认仅在localhost127.0.0.1)有访问权限,不是很适合远程操作(虽然可以更改为任何网络,但就变得不安全)。因此考虑在服务器端安装一个phpMyAdmin,就可以以本地连接的方式访问MySQL服务器了,具体在后面的小节中简单说说。

到这里MySQL就可以使用了,根据使用情况创建新数据库、创建新的用户并赋予权限。不过有几个有趣的小问题,可以“随便”说说。

第一个是有关InnoDB的问题。不知道几年前什么时候开始,MySQL数据库的默认数据库引擎就已经改成InnoDB,不再是MyISAM了。而且,从MySQL 5.6.7开始,针对InnoDB存储的数据库存储空间,也从默认的系统表空间(system tablespace)转到了分文件表空间(file-per-table tablespace)。当初我错手删掉了一个30g+的数据库(存着实验室爬到的一大批微博数据),本想着数据库不是MyISAM而是InnoDB,存在恢复的可能,却因为当时MySQL默认将InnoDB引擎的数据存储在系统表空间中,只得从一两百个Gigabytes的ibdata文件中一点点恢复。被学妹催着恢复数据,结果是恢复了一部分好像也不是很全……学妹为了正常毕业,用了别的数据……

第二个是有关collationcharset的问题。上至各种操作系统,下至各种需要处理自然语言的类库,Unicode编码一直一个十分重要、需要处理的因素。自然语言多种多样,Unicode就是解决针对它们的存储与表示而生的技术,或者说标准。至今,大多数主流的操作系统和软件一般都会以支持Unicode和相关技术而支持多语言。

在Web领域,使用较多的是以UTF-8为标准的Unicode表示和存储技术。PHP 6曾因长期无法以Unicode重构,最终夭折;而最新的7.x版本也没有完全解决。反观MySQL,在MySQL 5.5.3版本之前,UTF-8编码的单个字符是以2个字节存储的,而这是没法覆盖所有Unicode平面(Unicode plane),或者说没法覆盖所有的Unicode代码页(Unicode code point)。当时,除了一些安全问题之外,对多数英语(即使是汉语)用户,所碰到的问题是没法正确存储和表示一些emoji。而从5.5.3版本的MySQL开始,新增了utf8mb4的字符集,意为UTF-8的字符是以4字节来存储的,同时也加入了对应的collation方式。

安装较新版本的MySQL Server后,默认的数据库引擎是InnoDB,默认的字符集是utf8mb4,默认的collationutf8mb4_general_ci。这些对于后面恢复旧的WordPress备份是很有用的信息。

HTTPS设置和网站SSL证书申请

从不知道几年前开始,由Google Chrome带头,针对在与服务器端交互的inputpassword等HTML元素,如果客户端与服务器端的连接使用的是HTTP连接,则会给予用户不安全的提示,如果使用的是HTTPS连接,则与以往一样没有多余的提示。这也是为了让互联网变得更安全的一种推进,如驱使Web服务采用HTTPS连接

HTTPS逐渐作为WWW的一个标配,新建立的Web站点一般都会采用HTTPS,而老站点也逐渐由HTTP迁移到HTTPS。启用HTTPS一般不需要在客户端做什么操作,传统的方法是对Web服务器进行有关的配置,并提供SSL证书给Web服务器。因此,获得SSL证书是启用HTTPS的传统方法的必经之路。由CDN起家(是吧?)的Cloudflare则为网站启用HTTPS服务提供了另一种思路。

对于我这种个人用户来说,则很有必要对比对比这些不同的方法,尤其因为涉及到要花钱=_=。在阅读了一些对获取SSL证书和启用HTTPS服务的对比之后[12],下面做一点总结。之后选择了一种适合我的方法对服务器进行配置。

  • 由传统的证书颁发机构处购买:
    • 价格高一些(可能分为基本SSL证书与各种附加扩展,如扩展验证证书);
    • 可能手续繁琐(我没买过);
    • 可能等待时间较长(需要有一定的时间做验证处理);
    • 每次更新部署证书可能需要手动完成;
    • 可以提供扩展验证(extended validation,EV)、机构验证(organization validation,OV)。
  • 由提供免费证书的证书颁发机构处获取:
    • 免费(限制域名数量,免费时长通常30天、60天、90天或1~2年);
    • 操作方式与购买正常的证书相差不大;
    • 可以提供EV或OV,但可能需额外花费、或转为需正常购买的证书。
  • 由支持ACME的证书颁发服务处免费获取:
  • 使用Cloudflare的“Crypto”服务:
    • 免费(1个账号限制一个域名及其子域名,永久免费);
    • 对站点启用HTTPS的方法采用了类似“代理服务器”的形式,提供多种实现方式;
    • 在Cloudflare的面板完成大部分设置,根据实现方式的不同,Crypto服务可以为:
      • Off:不提供通讯加密,基本可以不用在服务器端进行操作;
      • Flexible:提供用户与Cloudflare服务器的通讯加密,基本可以不用在服务器端进行操作;
      • Full、Full (Strict):提供完全的端对端的通讯加密,需要在服务器端部署对应的SSL证书;
    • 不提供EV或OV;
    • 需要将域名DNS的NS记录指向Cloudflare(在域名解析这部分提到过);
    • 可同时启用Cloudflare提供的“CDN”、“Caching”服务,并利用“Page Rules”设置从HTTP请求到HTTPS请求的转向(无需再在服务器端做设置)。

写了这么一大堆,我的选择结果就是采用“Let’s Encrypt”的服务,除了在域名解析那部分讲提到的暂时不想换域名解析服务商之外,剩下的原因就是这几个字:简单、免费、可控。

接下来就是证书申请和Web服务器的HTTPS配置。我用了支持ACME的EFF官方客户端Certbot。Certbot的安装和使用方法在其官网首页有简单的介绍,只要是支持的Web服务器和操作系统,在首页选择服务器和操作系统,就可以查找到对应的Certbot安装和获取证书的命令。通过官方提供的命令,按照提示操作就可以完成证书的申请、在Web服务器配置文件中HTTPS服务的修改;如果是已有的证书,则会有提示是否进行续期。除此以外,这个工具还有很多功能和有趣的使用方法,比如手动模式、修改订阅者信息、选择challenge方法等,可以参考官方文档

以自动模式运行Certbot,在申请证书完成后,会自动在选择的域名的配置“块”中去掉了原有的在80端口监听的部分,并添加相应的HTTPS代码(“http2”属性是我自己添加的):

    listen [::]:443 ssl http2 ipv6only=on; # managed by Certbot
    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/blog.site.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/blog.site.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

此外,也会根据在运行Certbot的选择,是否添加由HTTP请求到HTTPS请求的转向:

server {
    if ($host = blog.site.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    listen       80;
    listen       [::]:80;
    server_name  blog.site.com;
    return 404; # managed by Certbot
}

在检查Nginx配置并重载配置或重启服务之后,就可以在浏览器中通过https://blog.site.com/访问到站点了,预期依然是404页面,但应该可以在浏览器中看到如绿色小锁的标志了。

简易的监控服务配置

监控VPS有很多种方式,大多需要在系统中安装必要的程序或软件包。NodeQuery提供了一种简单方便的监控方式,只需要在系统中下载一个脚本并设置cron自动按时运行,就可以向NodeQuery反馈常用的信息。可以从网站访问到这些信息,包括简易的系统信息、内存使用量、硬盘使用量、网络接口状态及流量信息、Internet网络延迟(ping)、系统CPU和I/O负载、进程列表和资源用量等。

phpMyAdmin的简易安装和加固

管理MySQL数据库的话,可以SSH到VPS后利用MySQL Client客户端以SQL与之交互操作。此外,phpMyAdmin则是可以在浏览器访问的图形化的MySQL管理器,使用起来是方便的很,但需要注意的是安全的使用。

安装phpMyAdmin有几种方式,可以直接安装操作系统发行版软件源里的软件包,也可以选择自建Web站点,然后进行简单快速安装

  1. 分配一个域名server.site.com到这台VPS,用于访问phpMyAdmin;
  2. 在Nginx配置中新增一个服务器server.site.com,配置好PHP/PHP-FPM;
  3. 用Certbot为server.site.com申请SSL证书,检查Nginx中该服务器的HTTPS设置;
  4. 下载最新的phpMyAdmin分发包,解压至服务器server.site.com的根目录;
  5. 以根目录下文件“config.sample.inc.php”的内容建立文件“config.ini.php”。

这样就可以通过https://server.site.com/访问到phpMyAdmin了。根据配置文件向导配置参考文档审查根目录的配置文件“config.ini.php”:

// 设置至少32字符长的内容,登录密码以此加密存储在cookie中
$cfg['blowfish_secret'] = '以至少32字符替换内容';

// 设置phpMyAdmin基于cookie验证登录
$cfg['Servers'][$i]['auth_type'] = 'cookie';
// MySQL服务器参数,只连接localhost本地服务器,不允许空密码
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['AllowNoPassword'] = false;

剩下的内容保持默认,不在这个配置文件中保存任何MySQL的用户名和密码。此外,根据官方的安全提示,可以为phpMyAdmin的目录增加HTTP验证。为Nginx中的某服务器增加HTTP验证,可以参考Nginx官方文档以及一个操作向导

由于Nginx并未提供额外的密码生成工具,需要使用Apache软件包“apache2-utils”中的工具为HTTP验证功能生成密码。如果没有安装,则:

sudo apt install apache2-utils

然后为用户生成HTTP验证密码,用户名为“serverHosting”和“admin”,存储在site.com这个TLD的文件夹下:

# 带“-c”的参数用于创建密码文件
sudo htpasswd -c /var/www/site_com/.htpasswd serverHosting
sudo htpasswd /var/www/site_com/.htpasswd admin

之后修改Nginx服务器的site.com配置文件中对应的部分(已有内容参考Nginx安装配置部分):

server {
    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/server.site.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/server.site.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    server_name  server.site.com;
    root   /var/www/site_com/htdocs/server_site_com;
    index  index.php;

    location / {
        auth_basic           "Authentication.";
        auth_basic_user_file /var/www/site_com/.htpasswd;
    }

    location ~* \.php$ {
        fastcgi_pass  unix:/run/php/php7.0-fpm.sock;
        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME     $fastcgi_script_name;
    }
}

从旧WordPress的数据备份恢复并更新至最新版

做完上面那么一堆工作,就是为了把这个WordPress恢复使用起来。前面多多少少提到所面临的问题,这里再详细讲一下:

  • 数据备份于2013年初,当时的情况是:
    • 软件版本:WordPress 3.5.1
    • 软件版本:PHP 5.x
    • 软件版本:MySQL Server 5.0.90
    • 当时使用的域名现在已经不属于我了
    • 站点以HTTP访问
    • MySQL的数据库引擎是MyISAM
    • MySQL的数据库字符集(charset)为“utf8
  • 现在的情况是:
    • 软件版本:WordPress 5.x
    • 软件版本:PHP 7.x
    • 软件版本:MySQL Server 5.7
    • 使用了新的域名
    • 站点改用HTTPS访问
    • PHP 7.x用于连接MySQL的方式变动
    • MySQL的数据库引擎优先使用InnoDB
    • MySQL的数据库字符集优先使用“utf8mb4

经过对比,除正常的WordPress升级之外,还涉及到几个必须要完成的操作和几个可选的操作:

必须完成的操作

  • 在本地搭建过渡环境,将WordPress升级到中间的一个版本作为过渡
  • 更改站点地址
    • Site Address (URL)
    • WordPress Address (URL)
    • 数据库中有关地址

可选的操作

  • 将恢复后的MySQL数据字符集改为“utf8mb4
  • 将恢复后的MySQL数据库引擎改为InnoDB

升级WordPress本是很简单的事情,尤其是从版本2.7起可以在WordPress界面在线升级,从版本3.7起可以在后台一键升级到最新版。而涉及到上面的问题,增加了恢复WordPress并升级的难度。考虑到由于PHP 7.x改变了连接MySQL的方式,无法直接在VPS线上完成数据恢复和WordPress升级,必须在本地搭建环境进行。

更改站点地址可以在WordPress后台完成,也可以使用一些技巧来实现,如果实际不允许的话。数据库中存储的站点地址,如帖子中的图片/文件附件地址,则需要特殊的工具来修改。更改MySQL字符集有2种方式:第一种是WordPress 4.2的升级脚本以官方的方式提供了将数据库字符集更改为“utf8mb4,要求MySQL Server版本在5.5.3以上,对MySQL Client库和mysqlnd版本亦有要求;由于官方以可运行脚本的升级数据库字符集的方式只存在于4.2版本中(至5.1.1依然是这样,后面的版本没考察),虽然之后的版本不再在数据库升级过程中更改字符集,但提供了maybe_convert_table_to_utf8mb4()函数,因此第二种是可以考虑使用第三方脚本update_db_utf8mb4.phputf8-to-utf8mb4.php。至于更换MySQL数据库引擎,可以自己运行SQL操作,或使用WordPress的插件来完成,如Vevida Optimizer

由于必须在本地搭建环境,而我使用Windows平台,XAMPP等提供Web服务器/PHP/MySQL/MariaDB的整合服务栈,更方便我用来搭建多个版本的Web环境。我选择了XAMPP 1.7.3作为本地环境。“感觉”从WordPress 3.5.1在后台一键升级到5.x最新版不是很安全,因此选择手动将其升级到3.7版本之后再使用一键升级。考虑到既然要手动升级,不妨在升级版本3.7之后,先升级到版本4.2同时升级脚本会自动将数据库字符集转换为“utf8mb4”,之后再用一键升级到最新版。

因此,整个的升级步骤记录下来:

  1. 本地系统配置hosts,添加原有WordPress所使用的olddomain.name域名指向127.0.0.1
  2. 本地搭建XAMPP 1.7.3环境,在Apache中配置好指向olddomain.namevhost
  3. 本地phpMyAdmin建立数据库,导入备份数据
  4. 本地将备份数据解压到vhost中配置的站点根目录
  5. 本地访问http://olddomain.name/,查看站点是否一切正常(后台/页面访问/永久链接等)
  6. 本地WordPress系统中禁用所有插件
  7. WordPress下载存档页面下载以下版本的WordPress存档到本地:
    • 3.7(与备份版本和之后版本相差2个主要版本号,原因来自官方文档
    • 3.9
    • 4.1
  8. 按照官方文档指明的跨版本手动升级方法,从当前3.5.1版,依次由3.7、3.9升级到4.1版
  9. 在WordPress后台设置中,修改站点地址和WordPress地址为“https://blog.site.com
  10. 完成上一步之后,浏览器应该看到的是一个什么错误的页面(404吧)
  11. 本地phpMyAdmin备份WordPress 4.1版本的数据
  12. 本地站点根目录打包备份所有文件
  13. 上传本地打包的所有文件到VPS上站点对应的根目录,解压,设置文件所有者、组所有者和读写权限
  14. 服务器phpMyAdmin建立数据库和用户,为用户赋予该数据库的必要权限
  15. 服务器phpMyAdmin导入WordPress 4.1版本的数据
  16. 修改WordPress目录下“wp-config.php”文件中的MySQL数据库连接用户名、密码、数据库名等
  17. 浏览器访问https://blog.site.com,检查各类页面和功能是否正常
  18. WordPress下载存档页面下载4.2版本的WordPress存档到服务器,按照手动升级方法,更换4.1版本的文件为4.2版本(官方升级脚本支持将数据库字符集转为“utf8mb4”)
  19. 浏览器访问https://blog.site.com/wp-admin/,页面会提示数据库升级,按照提示完成之后,数据库字符集则更换为“utf8mb4
  20. 在WordPress后来中使用一键升级,升级到最新的5.x版
  21. 官方针对更换站点地址的文档中提到的替换数据库中站点地址的方法中选择一种,如使用插件Better Search Replace,替换数据库中(主要是帖子中)图片、文件等附件的URL
  22. 使用插件Vevida Optimizer将WordPress各数据表的引擎更换为InnoDB

经过上面的步骤,这个WordPress站点基本上就从一个几年前的旧备份数据恢复并升级过来了。这篇日志的基本目的也就达到了。除了上面的这些内容,还有很多杂七杂八的内容,比如对各级软件的安全加固和优化、定期数据备份、本地备份和异地备份、无人值守的操作系统自动升级、以及SSL证书定期自动更新等,有时间再写吧。

这篇日志有点长,要不要分开几个部分呢……

检查了一遍,看起来好像没什么问题了,也不分页或者分篇了,一键发布。看自己写的这一篇文字,就知道自己是什么水平了——“XXX专业的非专业人员”,哦吼吼~

PS,其实最早给这篇起名叫做《这次一套网络服务配置的笔记》……

One thought on “网络服务配置笔记:WordPress w/ SSL on Ubuntu w/ Nginx, PHP and MySQL”

Leave a Reply

Your email address will not be published. Required fields are marked *