没有不值得去解决的问题,也没有不值得去学习的技术!

OneinStack 现有 Nginx 虚拟主机追加域名并重签 SSL 证书的一次实操记录

【图 10:新证书 SAN 信息截图,显示已经包含 en.shuijingwanwq.com】

作者:

WordPress CDN 与全球加速实战

图16:浏览器访问正常,网站全球访问成功

(1) 从阿里云 DNS 到 Cloudflare 全球加速的完整迁移实战记录

这一套规则遵循 Cloudflare + WordPress 标准 CDN 架构:

(2) Cloudflare SSL/TLS 与 Cache Rules 配置实战

图12:评论实时生效

(3) WordPress + Cloudflare 推荐配置与 Cache Rules 实战优化(SSL / API / 缓存闭环完整记录)

CDN上线后的boce数据

(4) CDN 上线前后性能对比实测:WordPress 缓存误判修正与真实加速效果验证

【图9:boce 测试 cn-test,灰云直连阿里云 ECS,平均响应 0.478s】

(5) Cloudflare 免费版适合中国大陆 WordPress 主站吗?从缓存 HIT 到灰云直连阿里云 ECS 的实测复盘

【图1:腾讯云 EdgeOne 产品页,选择“立即使用”】

(6) 从 Cloudflare Free 迁移到腾讯云 EdgeOne:一次 WordPress 主站国内外加速实战

【图2:EdgeOne 上线后 boce 第二次测试,平均响应 0.354s,不可访问 2 个】

(7) Cloudflare Free 迁移到 EdgeOne 后到底快了多少?WordPress CDN 三阶段 boce 与 WebPageTest 实测对比

[图2,EdgeOne 昨日 L7 访问流量,显示 6.56 GB]

(8) EdgeOne 流量成本排查:将 WordPress uploads 静态资源迁移到 Cloudflare media 子域名

【图3,EdgeOne 301 请求的 URL Path 排行,集中在 /wp-content/uploads/ 图片路径】

(9) WordPress 图片迁移到 media 子域名后,EdgeOne 仍然出现大量 301 的排查与处理记录

图4:Cloudflare Edge TTL 配置、Cloudflare Browser TTL 配置

(10) WordPress Media CDN 迁移后的 Cloudflare Cache Rules 调整记录

[图4:EdgeOne 按 URL path 开始于 /en/ 筛选后的流量截图]

(11) EdgeOne 流量成本控制决策:是否将英文站从 /en/ 迁移到 en.shuijingwanwq.com

[图3:执行核心升级时返回 524 No Reason Phrase]

(12) WordPress 核心升级反复 524 与“另一更新正在进行”的排查记录

【图 10:新证书 SAN 信息截图,显示已经包含 en.shuijingwanwq.com】

(13) OneinStack 现有 Nginx 虚拟主机追加域名并重签 SSL 证书的一次实操记录

【图 8,curl 验证 www 与 en 的 html lang、canonical 均正确】

(14) WordPress Polylang 英文站从 /en/ 迁移到 en 子域名:W3TC 与 Redis 缓存问题排查

最近我准备把 WordPress 英文站从路径形式:

Plaintext
https://www.shuijingwanwq.com/en/

迁移到子域名形式:

Plaintext
https://en.shuijingwanwq.com/

这次迁移的直接原因,是我最近观察 EdgeOne 流量数据时发现,主站流量增长已经明显超出之前的预期。

我当前购买的是 EdgeOne 个人版,套餐内包含 50 GB 流量。如果后续超过这个额度,就会进入按量计费。考虑到基础版月费较高,目前我不打算直接升级套餐,因此更倾向于通过域名拆分和 CDN 分流来控制成本。

【图 1:EdgeOne 最近 6 小时流量统计截图,显示当前流量增长趋势】
【图 1:EdgeOne 最近 6 小时流量统计截图,显示当前流量增长趋势】

因此,我开始考虑把英文站从主域名路径 /en/ 拆分到:

Plaintext
https://en.shuijingwanwq.com/

这样后续可以单独规划英文站的 CDN、缓存和流量策略,而不是让中文站、英文站、静态资源都继续集中消耗主域名的 EdgeOne 流量。

不过,在真正修改 Polylang 的语言 URL 设置之前,我先遇到了一个更基础的问题:

OneinStack 已有的 Nginx 虚拟主机,如何追加一个新域名,并让现有 SSL 证书同时覆盖这个新域名?

网上能搜到的一些做法,通常是先删除虚拟主机,再重新添加域名。但对于一个已经运行很久、并且手工改过不少 Nginx 规则的 WordPress 主站来说,我并不想走“删除再重建”的路线。

这篇文章记录的,就是这次在现有 OneinStack Nginx 虚拟主机中追加 en.shuijingwanwq.com,并重新签发包含多个域名的 SSL 证书的过程。

当前站点环境

当前主站是一个 OneinStack 部署的 WordPress 站点,Nginx 虚拟主机配置文件位于:

Plaintext
/usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf

主站根目录是:

Plaintext
/data/wwwroot/www.shuijingwanwq.com

已有域名包括:

Plaintext
www.shuijingwanwq.com
shuijingwanwq.com

现在希望追加:

Plaintext
en.shuijingwanwq.com

但这个子域名并不是一个独立站点,也不是一个静态资源域名。它仍然要进入同一个 WordPress 程序,由 Polylang 根据子域名识别英文语言。

也就是说,目标结构是:

Plaintext
www.shuijingwanwq.com

同一个 WordPress 根目录
/data/wwwroot/www.shuijingwanwq.com

en.shuijingwanwq.com

同一个 WordPress 根目录
/data/wwwroot/www.shuijingwanwq.com

这一点和之前的 media.shuijingwanwq.com 不一样。media 是静态资源域名,适合单独虚拟主机;而 en 是语言子域名,更适合进入同一个 WordPress 站点。

【图 2:Polylang URL 设置页面截图,展示“根据固定链接中的子域名称设置语言”的选项】
【图 2:Polylang URL 设置页面截图,展示“根据固定链接中的子域名称设置语言”的选项】

为什么没有使用删除再重建 vhost 的方式

OneinStack 的 vhost.sh 脚本确实支持在创建虚拟主机时添加更多域名。脚本里有类似这样的交互提示:

Plaintext
Do you want to add more domain name? [y/n]:
【图 3:OneinStack vhost.sh 菜单或脚本提示截图,显示添加更多域名的相关选项】
【图 3:OneinStack vhost.sh 菜单或脚本提示截图,显示添加更多域名的相关选项】

但从本机脚本输出看,这个逻辑主要发生在“创建虚拟主机”流程中。如果对应的 ${domain}.conf 已经存在,脚本会提示该虚拟主机已经存在,需要删除后再重新创建。

对于一个新站,这样做问题不大。

但对我现在这个主站来说,情况不一样。

如果先删除 vhost,再用 OneinStack 重建,理论上网站目录不会被删除,但这个过程仍然会影响线上站点的正常访问。现在我的主站已经有比较稳定的访问量,不能接受因为重建虚拟主机导致网站短时间不可访问、证书异常、跳转异常,或者 Nginx 配置被覆盖。

另外,我的主站配置文件已经不是完全默认模板,里面包含一些自定义 include、WordPress rewrite、AMP 跳转、tag 跳转、静态文件访问限制等规则。如果删除后再重建,后续还需要重新补回这些规则,操作成本和风险都会更高。

所以这次我没有删除虚拟主机,而是选择:

Plaintext
保留现有 vhost
只修改 server_name
调整主域名跳转规则
重新签发包含 en 子域名的 SSL 证书

第一步:备份现有 Nginx 虚拟主机配置

正式修改前,先备份当前配置文件:

Bash
cp /usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf /usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf.bak-$(date +%F-%H%M)

这是必要步骤。因为现有站点已经上线,任何 Nginx 配置改错,都需要能快速回滚。

第二步:在现有 server_name 中追加 en 子域名

原来的配置类似:

Nginx
server_name www.shuijingwanwq.com shuijingwanwq.com;

修改为:

Nginx
server_name www.shuijingwanwq.com shuijingwanwq.com en.shuijingwanwq.com;

这样,en.shuijingwanwq.com 就会进入同一个 Nginx server block,也就是同一个 WordPress 根目录。

【图 4:修改后的 Nginx server_name 配置截图】
【图 4:修改后的 Nginx server_name 配置截图】

第三步:调整裸域名跳转规则

原来配置中有一条规则:

Nginx
if ($host != www.shuijingwanwq.com) {  return 301 $scheme://www.shuijingwanwq.com$request_uri;  }

这条规则在只有 www 和裸域名时没问题。它的作用是把非 www.shuijingwanwq.com 的请求都跳转到 www

但现在要增加 en.shuijingwanwq.com,这条规则就不合适了。

如果不修改,访问:

Plaintext
https://en.shuijingwanwq.com/

会被 Nginx 直接 301 回:

Plaintext
https://www.shuijingwanwq.com/

因此,我把它改成只处理裸域名:

Nginx
if ($host = shuijingwanwq.com) {  return 301 $scheme://www.shuijingwanwq.com$request_uri;  }

这样:

Plaintext
shuijingwanwq.com → www.shuijingwanwq.com

但:

Plaintext
en.shuijingwanwq.com

不会再被 Nginx 强制跳回 www

第四步:检查并重载 Nginx

修改完成后,先检查配置语法:

Bash
nginx -t

输出正常:

Plaintext
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
【图 5:nginx -t 检查通过截图】
【图 5:nginx -t 检查通过截图】

然后重载 Nginx:

Bash
nginx -s reload

到这一步,Nginx 已经能够识别 en.shuijingwanwq.com 这个 Host。

不过这时还不能算完成,因为 SSL 证书还需要重新签发,让它同时包含 www.shuijingwanwq.comshuijingwanwq.comen.shuijingwanwq.com

第五步:查看 acme.sh 中现有证书的域名记录

在重新签发证书前,我先查看了 OneinStack 当前环境中 acme.sh 对主站证书的记录:

Bash
grep -E "Le_Domain|Le_Alt|Le_Webroot|Le_RealCertPath|Le_RealCACertPath|Le_RealKeyPath|Le_ReloadCmd" /root/.acme.sh/www.shuijingwanwq.com/www.shuijingwanwq.com.conf

当时输出如下:

Plaintext
Le_Domain='www.shuijingwanwq.com'
Le_Alt='shuijingwanwq.com'
Le_Webroot='/data/wwwroot/www.shuijingwanwq.com'
Le_RealCertPath=''
Le_RealCACertPath=''
Le_RealKeyPath='/usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key'
Le_ReloadCmd='__ACME_BASE64__START_L2Jpbi9zeXN0ZW1jdGwgcmVzdGFydCBuZ2lueA==__ACME_BASE64__END_'

从这里可以看到,当前主站证书记录中的主域名是:

Plaintext
www.shuijingwanwq.com

备用域名是:

Plaintext
shuijingwanwq.com

还没有包含:

Plaintext
en.shuijingwanwq.com

同时也能确认,当前证书对应的 Webroot 是:

Plaintext
/data/wwwroot/www.shuijingwanwq.com

这也正好符合我的目标:en.shuijingwanwq.com 不是新建独立站点,而是继续指向同一个 WordPress 根目录。

【图 6:查看 acme.sh 主站证书配置记录的终端截图】
【图 6:查看 acme.sh 主站证书配置记录的终端截图】

因此,下一步需要重新签发一个同时包含以下三个域名的证书:

Plaintext
www.shuijingwanwq.com
shuijingwanwq.com
en.shuijingwanwq.com

第六步:先添加 DNS 解析

签发证书前,需要先让 en.shuijingwanwq.com 解析到源站服务器。

这里我先添加了一条 DNS 记录:

Plaintext
主机记录:en
记录类型:A
记录值:源站服务器公网 IP
代理状态:暂时不走 CDN / 代理

这一步主要是为了让 ACME HTTP 验证能访问到源站。

服务器上可以用下面命令检查解析:

Bash
getent ahostsv4 en.shuijingwanwq.com | head -n 1

当时返回结果类似:

Plaintext
121.40.248.29   STREAM en.shuijingwanwq.com

如果返回的是源站公网 IP,说明服务器侧解析已经正常。

【图 7:DNS 解析检查结果截图】
【图 7:DNS 解析检查结果截图】

第七步:使用 acme.sh 重新签发多域名证书

OneinStack 当前环境中已经安装了 acme.sh,并且原有证书记录也在:

Plaintext
/root/.acme.sh/www.shuijingwanwq.com/

为了保持证书体系一致,我没有引入新的证书工具,而是继续使用已有的 acme.sh

重新签发命令如下:

Bash
~/.acme.sh/acme.sh --force --issue -w /data/wwwroot/www.shuijingwanwq.com -d www.shuijingwanwq.com -d shuijingwanwq.com -d en.shuijingwanwq.com

签发过程中可以看到多域名信息:

Plaintext
Multi domain='DNS:www.shuijingwanwq.com,DNS:shuijingwanwq.com,DNS:en.shuijingwanwq.com'

三个域名都验证成功后,证书签发完成。

新证书生成在:

Plaintext
/root/.acme.sh/www.shuijingwanwq.com_ecc/

其中包括:

Plaintext
/root/.acme.sh/www.shuijingwanwq.com_ecc/fullchain.cer
/root/.acme.sh/www.shuijingwanwq.com_ecc/www.shuijingwanwq.com.key
【图 8:acme.sh 多域名证书签发成功截图】
【图 8:acme.sh 多域名证书签发成功截图】

第八步:安装新证书到 Nginx 使用的证书路径

签发成功后,还需要把新证书安装到 Nginx 当前使用的证书路径。

安装前,先备份旧证书:

Bash
cp /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.crt /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.crt.bak-$(date +%F-%H%M)
cp /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key.bak-$(date +%F-%H%M)

然后安装新证书:

Bash
~/.acme.sh/acme.sh --install-cert --ecc -d www.shuijingwanwq.com \
--fullchain-file /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.crt \
--key-file /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key \
--reloadcmd "nginx -s reload"

安装成功后,输出如下:

Plaintext
Installing key to: /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key
Installing full chain to: /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.crt
Run reload cmd: nginx -s reload
Reload success
【图 9:证书安装并 reload success 的截图】
【图 9:证书安装并 reload success 的截图】

第九步:验证新证书是否已经包含 en 子域名

安装新证书后,再验证 en.shuijingwanwq.com 实际拿到的证书是否已经包含 en 子域名:

Bash
openssl s_client -connect en.shuijingwanwq.com:443 -servername en.shuijingwanwq.com </dev/null 2>/dev/null | openssl x509 -noout -text | grep -A2 "Subject Alternative Name"

返回结果中已经包含:

Plaintext
X509v3 Subject Alternative Name:
    DNS:www.shuijingwanwq.com, DNS:en.shuijingwanwq.com, DNS:shuijingwanwq.com

这说明 en.shuijingwanwq.com 的 HTTPS 证书已经正常。

【图 10:新证书 SAN 信息截图,显示已经包含 en.shuijingwanwq.com】
【图 10:新证书 SAN 信息截图,显示已经包含 en.shuijingwanwq.com】

第十步:当前状态与下一步

到这里,服务器层面的准备已经完成:

Plaintext
Nginx 已识别 en.shuijingwanwq.com
SSL 证书已包含 en.shuijingwanwq.com
en 子域名已指向同一个 WordPress 根目录

不过,此时直接访问:

Bash
curl -I https://en.shuijingwanwq.com/

仍然会得到 WordPress 发出的 301 跳转:

Plaintext
HTTP/2 301
location: https://www.shuijingwanwq.com/
x-redirect-by: WordPress

这说明 Nginx 和 SSL 已经不是问题了,剩下的问题在 WordPress / Polylang 层。

【图 11:curl -I https://en.shuijingwanwq.com/ 返回 WordPress 301 的截图】
【图 11:curl -I https://en.shuijingwanwq.com/ 返回 WordPress 301 的截图】

下一步需要进入 WordPress 后台:

Plaintext
语言 → 设置 → URL 修改

把 Polylang 的语言 URL 模式从:

Plaintext
/en/my-post/

切换为:

Plaintext
https://en.shuijingwanwq.com/my-post/

也就是让 Polylang 根据子域名识别语言。

这一步我还没有继续操作,因为它会影响现有英文站 URL,需要在确认服务器、证书和缓存策略都准备好之后再切换。

小结

这次操作最大的收获是:

对于已经存在的 OneinStack Nginx 虚拟主机,不一定要删除再重建,才能追加域名和证书。

如果现有 vhost 配置已经有很多自定义规则,删除再重建不只是麻烦,还可能影响线上访问。对于一个已经有稳定流量的 WordPress 主站来说,短时间不可访问、证书异常、跳转异常,都会带来不必要的风险。

更稳妥的做法是:

Plaintext
备份现有 vhost
修改 server_name
调整跳转规则
检查 Nginx 配置
添加 DNS
查看 acme.sh 现有证书记录
重新签发包含新域名的证书
安装证书到原有 Nginx 证书路径
验证 HTTPS
最后再修改 WordPress / Polylang 设置

对于普通独立站点,OneinStack 的 vhost.sh 创建流程已经足够。但对于一个已经长期运行、并且配置经过多次调整的 WordPress 站点,保留现有 vhost,只做最小变更,通常更安全。

WordPress 核心升级反复 524 与“另一更新正在进行”的排查记录 WordPress Polylang 英文站从 /en/ 迁移到 en 子域名:W3TC 与 Redis 缓存问题排查

需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理