Recently, I started preparing to move the English version of my WordPress site from the path-based URL:
https://www.shuijingwanwq.com/en/
to a subdomain-based URL:
https://en.shuijingwanwq.com/
The direct reason for this migration was that, while reviewing recent EdgeOne traffic data, I noticed that traffic to the main site had grown far beyond my previous expectations.
I am currently using the EdgeOne Personal plan, which includes 50 GB of traffic. Once the usage exceeds that quota, it moves into pay-as-you-go billing. Since the monthly fee of the Basic plan is relatively high, I do not plan to upgrade the package directly for now. Instead, I prefer to control costs by splitting domains and distributing CDN traffic more carefully.

So I started considering whether to split the English site from the main domain path /en/ to:
https://en.shuijingwanwq.com/
This would allow me to plan the CDN, cache, and traffic strategy for the English site separately, instead of letting the Chinese site, English site, and static resources all continue consuming the EdgeOne traffic quota of the main domain.
However, before actually changing the language URL settings in Polylang, I first ran into a more basic question:
For an existing OneinStack Nginx virtual host, how can I add a new domain name and make the current SSL certificate cover that new domain as well?
Some solutions found online suggest deleting the existing virtual host and then adding the domains again. But for a WordPress main site that has been running for a long time and already contains quite a few manually customized Nginx rules, I did not want to take the “delete and recreate” route.
This article records how I added en.shuijingwanwq.com to the existing OneinStack Nginx virtual host and reissued an SSL certificate that covers multiple domain names.
Current Site Environment
The current main site is a WordPress site deployed with OneinStack. Its Nginx virtual host configuration file is located at:
/usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf
The main site root directory is:
/data/wwwroot/www.shuijingwanwq.com
The existing domains are:
www.shuijingwanwq.com
shuijingwanwq.com
Now I want to add:
en.shuijingwanwq.com
But this subdomain is not an independent site, nor is it a static asset domain. It still needs to enter the same WordPress application, and Polylang will identify the English language based on the subdomain.
In other words, the target structure is:
www.shuijingwanwq.com
↓
同一个 WordPress 根目录
/data/wwwroot/www.shuijingwanwq.com
en.shuijingwanwq.com
↓
同一个 WordPress 根目录
/data/wwwroot/www.shuijingwanwq.com
This is different from the earlier media.shuijingwanwq.com setup. media is a static asset domain, so it is suitable for a separate virtual host. But en is a language subdomain, so it is more appropriate for it to enter the same WordPress site.

Why I Did Not Delete and Recreate the vhost
The OneinStack vhost.sh script does support adding more domain names when creating a virtual host. The script includes an interactive prompt similar to this:
Do you want to add more domain name? [y/n]:

However, judging from the local script output, this logic mainly belongs to the “create virtual host” workflow. If the corresponding ${domain}.conf already exists, the script reports that the virtual host already exists and asks you to delete it before creating it again.
For a new site, that is usually fine.
But for my current main site, the situation is different.
If I deleted the vhost first and then recreated it with OneinStack, the website directory would not necessarily be deleted. But the process could still affect normal access to the live site. My main site already has relatively stable traffic, so I cannot accept a short period of downtime, certificate errors, redirect errors, or overwritten Nginx configuration caused by recreating the virtual host.
In addition, the Nginx configuration file for my main site is no longer a completely default template. It already includes custom includes, WordPress rewrite rules, AMP redirects, tag redirects, static file access restrictions, and other rules. If I deleted and recreated the virtual host, I would have to manually add those rules back afterward, which would increase both the workload and the risk.
So this time I did not delete the virtual host. Instead, I chose to:
保留现有 vhost
只修改 server_name
调整主域名跳转规则
重新签发包含 en 子域名的 SSL 证书
Step 1: Back Up the Existing Nginx Virtual Host Configuration
Before making any formal changes, I first backed up the current configuration file:
cp /usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf /usr/local/nginx/conf/vhost/www.shuijingwanwq.com.conf.bak-$(date +%F-%H%M)
This is a necessary step. Since the site is already live, any mistake in the Nginx configuration must be easy to roll back quickly.
Step 2: Add the en Subdomain to the Existing server_name
The original configuration looked like this:
server_name www.shuijingwanwq.com shuijingwanwq.com;
I changed it to:
server_name www.shuijingwanwq.com shuijingwanwq.com en.shuijingwanwq.com;
With this change, en.shuijingwanwq.com enters the same Nginx server block, which means it reaches the same WordPress root directory.

Step 3: Adjust the Root Domain Redirect Rule
The original configuration included this rule:
if ($host != www.shuijingwanwq.com) { return 301 $scheme://www.shuijingwanwq.com$request_uri; }
This rule was fine when the site only had www and the root domain. Its job was to redirect every request that was not www.shuijingwanwq.com back to www.
But now that en.shuijingwanwq.com needs to be added, this rule is no longer suitable.
If it were left unchanged, visiting:
https://en.shuijingwanwq.com/
would be redirected by Nginx with a 301 back to:
https://www.shuijingwanwq.com/
So I changed the rule to handle only the root domain:
if ($host = shuijingwanwq.com) { return 301 $scheme://www.shuijingwanwq.com$request_uri; }
This way:
shuijingwanwq.com → www.shuijingwanwq.com
But:
en.shuijingwanwq.com
will no longer be forcibly redirected back to www by Nginx.
Step 4: Check and Reload Nginx
After the changes were made, I checked the configuration syntax first:
nginx -t
The output was normal:
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

Then I reloaded Nginx:
nginx -s reload
At this point, Nginx was already able to recognize the en.shuijingwanwq.com Host.
However, the task was not complete yet, because the SSL certificate still needed to be reissued so that it would include www.shuijingwanwq.com, shuijingwanwq.com, and en.shuijingwanwq.com at the same time.
Step 5: Check the Existing Certificate Domain Records in acme.sh
Before reissuing the certificate, I first checked the current acme.sh record for the main site certificate in the OneinStack environment:
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
The output at that time was:
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_'
From this output, I could see that the main domain in the current certificate record was:
www.shuijingwanwq.com
The alternative domain was:
shuijingwanwq.com
It did not yet include:
en.shuijingwanwq.com
I could also confirm that the Webroot corresponding to the current certificate was:
/data/wwwroot/www.shuijingwanwq.com
This matched my target exactly: en.shuijingwanwq.com was not going to be a newly created independent site. It would continue pointing to the same WordPress root directory.

Therefore, the next step was to reissue a certificate that includes the following three domain names:
www.shuijingwanwq.com
shuijingwanwq.com
en.shuijingwanwq.com
Step 6: Add the DNS Record First
Before issuing the certificate, en.shuijingwanwq.com needed to resolve to the origin server.
So I first added a DNS record:
主机记录:en
记录类型:A
记录值:源站服务器公网 IP
代理状态:暂时不走 CDN / 代理
The main purpose of this step was to make sure ACME HTTP validation could reach the origin server.
On the server, I used the following command to check DNS resolution:
getent ahostsv4 en.shuijingwanwq.com | head -n 1
The result returned at that time looked like this:
121.40.248.29 STREAM en.shuijingwanwq.com
If the returned value is the public IP address of the origin server, DNS resolution on the server side is working properly.

Step 7: Reissue a Multi-Domain Certificate with acme.sh
acme.sh was already installed in the current OneinStack environment, and the original certificate record was also stored under:
/root/.acme.sh/www.shuijingwanwq.com/
To keep the certificate setup consistent, I did not introduce a new certificate tool. I continued using the existing acme.sh setup.
The reissue command was:
~/.acme.sh/acme.sh --force --issue -w /data/wwwroot/www.shuijingwanwq.com -d www.shuijingwanwq.com -d shuijingwanwq.com -d en.shuijingwanwq.com
During issuance, the multi-domain information was visible:
Multi domain='DNS:www.shuijingwanwq.com,DNS:shuijingwanwq.com,DNS:en.shuijingwanwq.com'
After all three domain names passed validation, the certificate was issued successfully.
The new certificate was generated under:
/root/.acme.sh/www.shuijingwanwq.com_ecc/
It includes:
/root/.acme.sh/www.shuijingwanwq.com_ecc/fullchain.cer
/root/.acme.sh/www.shuijingwanwq.com_ecc/www.shuijingwanwq.com.key

Step 8: Install the New Certificate to the Certificate Path Used by Nginx
After the certificate was issued successfully, I still needed to install it to the certificate path currently used by Nginx.
Before installation, I backed up the old certificate first:
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)
Then I installed the new certificate:
~/.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"
After the installation succeeded, the output was:
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

Step 9: Verify Whether the New Certificate Includes the en Subdomain
After installing the new certificate, I verified whether the certificate actually served for en.shuijingwanwq.com already included the en subdomain:
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"
The returned result already included:
X509v3 Subject Alternative Name:
DNS:www.shuijingwanwq.com, DNS:en.shuijingwanwq.com, DNS:shuijingwanwq.com
This confirmed that the HTTPS certificate for en.shuijingwanwq.com was working correctly.

Step 10: Current Status and Next Step
At this point, the server-side preparation was complete:
Nginx 已识别 en.shuijingwanwq.com
SSL 证书已包含 en.shuijingwanwq.com
en 子域名已指向同一个 WordPress 根目录
However, directly visiting:
curl -I https://en.shuijingwanwq.com/
still returned a WordPress 301 redirect:
HTTP/2 301
location: https://www.shuijingwanwq.com/
x-redirect-by: WordPress
This means Nginx and SSL are no longer the problem. The remaining issue is at the WordPress / Polylang layer.

curl -I https://en.shuijingwanwq.com/ returns a WordPress 301 redirectThe next step is to enter the WordPress admin dashboard:
语言 → 设置 → URL 修改
and change Polylang’s language URL mode from:
/en/my-post/
to:
https://en.shuijingwanwq.com/my-post/
In other words, Polylang will identify the language based on the subdomain.
I did not continue with this step yet, because it will affect the existing English site URLs. It should only be switched after the server, certificate, and cache strategy have all been confirmed.
Summary
The biggest takeaway from this operation was:
For an existing OneinStack Nginx virtual host, deleting and recreating it is not always necessary just to add another domain name and update the certificate.
If the existing vhost configuration already contains many custom rules, deleting and recreating it is not only inconvenient, but may also affect live access. For a WordPress main site with stable traffic, even a short period of downtime, certificate errors, or redirect errors would introduce unnecessary risk.
A safer approach is:
备份现有 vhost
修改 server_name
调整跳转规则
检查 Nginx 配置
添加 DNS
查看 acme.sh 现有证书记录
重新签发包含新域名的证书
安装证书到原有 Nginx 证书路径
验证 HTTPS
最后再修改 WordPress / Polylang 设置
For a normal independent site, the OneinStack vhost.sh creation workflow is usually enough. But for a WordPress site that has been running for a long time and whose configuration has been adjusted multiple times, keeping the existing vhost and making only minimal changes is often the safer choice.
需要长期技术维护或远程问题排查?
我是拥有 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


发表回复