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

将 WordPress 后台迁移到独立 admin 子域名:绕过 EdgeOne,解决核心升级 524 超时

升级请求经过 EdgeOne,长时间运行的后台请求最终出现超时,数据库中还一度留下了 core_updater.lock

作者:

,

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 缓存问题排查

【图 14,最终回归验证:en 首页和文章页 Cloudflare HIT,lang 与 canonical 正确】

(15) 将 Polylang 英文子域名接入 Cloudflare:HTML 缓存、登录绕过与后台入口收敛

【图1:浏览器开发者工具中,旧 /en/ 首页返回 301,随后成功加载 en 子域名英文首页】

(16) WordPress 英文站从 /en/ 迁移到 en 子域名:兼容数千条 Nginx 旧规则并避免二次 301

升级请求经过 EdgeOne,长时间运行的后台请求最终出现超时,数据库中还一度留下了 core_updater.lock

(17) 将 WordPress 后台迁移到独立 admin 子域名:绕过 EdgeOne,解决核心升级 524 超时

【图 1,后台发布新文章后,中文首页仍未显示新文章】

(18) WordPress 多域名架构暂停复盘:en、admin、W3TC 与多 CDN 的可维护性重新评估

此前,我曾经排查过一次 WordPress 核心在线升级失败的问题。当时升级请求经过 EdgeOne,长时间运行的后台请求最终出现超时,数据库中还一度留下了 core_updater.lock

前文记录:

最近,我已经将英文站迁移到:

Plaintext
en.shuijingwanwq.com

并将上传目录中的图片和附件迁移到:

Plaintext
media.shuijingwanwq.com

这两个域名目前均使用 Cloudflare,中文主站继续通过 EdgeOne 提供服务。

原本以为完成这两次拆分以后,EdgeOne 的流量压力会明显降低。但从 2026 年 7 月 12 日的统计数据来看,www.shuijingwanwq.com 一天仍然产生了约:

Plaintext
L7 访问流量:2.9 GB
EdgeOne 响应流量:2.8 GB
客户端请求流量:102.66 MB
L7 访问请求数:13.8 万次
【图 1,EdgeOne 指标分析中显示单日 2.9 GB L7 访问流量】
【图 1,EdgeOne 指标分析中显示单日 2.9 GB L7 访问流量】

后台迁移并不能直接消除这 2.9 GB 前台流量,因为其中绝大部分仍然来自中文站页面、静态文件、搜索引擎和其他访客请求。

不过,这至少说明:已经没有必要再让 WordPress 后台操作继续通过 EdgeOne。

结合此前的核心升级超时问题,我最终决定将 WordPress 后台迁移到一个独立子域名:

Plaintext
admin.shuijingwanwq.com

本文完整记录这次迁移过程,包括 Nginx 虚拟主机、W3 Total Cache 兼容、WordPress URL 重写、多语言域名统一跳转、前台 AJAX 接口保护,以及最终用于生产环境的配置文件。


一、最终架构

迁移完成后的访问结构如下:

Plaintext
www.shuijingwanwq.com

     EdgeOne

WordPress 中文前台


en.shuijingwanwq.com

    Cloudflare

WordPress 英文前台


media.shuijingwanwq.com

    Cloudflare

wp-content/uploads


admin.shuijingwanwq.com

Cloudflare DNS Only
不经过 EdgeOne 或 Cloudflare 代理

独立 Nginx 虚拟主机

PHP-FPM / WordPress 后台

需要特别说明的是:

Plaintext
admin 使用独立 Nginx 虚拟主机
但不复制第二套 WordPress 程序

adminwwwen 最终仍然共用同一个 WordPress 目录:

Plaintext
/data/wwwroot/www.shuijingwanwq.com

这是因为后台运行仍然需要访问同一套:

Plaintext
wp-admin
wp-includes
wp-content
wp-login.php
wp-config.php

独立虚拟主机负责的是访问入口、证书、日志和安全策略,而不是复制应用程序。


二、为什么不直接修改 WordPress 的 siteurl

WordPress 数据库中的地址仍然保持不变:

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

siteurl:
https://www.shuijingwanwq.com

没有将 siteurl 修改成:

Plaintext
https://admin.shuijingwanwq.com

原因是直接修改 siteurl 可能同时影响:

  • 中文前台资源地址;
  • Polylang 多域名识别;
  • REST API;
  • 插件和主题资源;
  • W3 Total Cache 缓存键;
  • WP-Cron;
  • Yoast SEO;
  • 登录和退出跳转;
  • 英文站资源地址。

本次方案采用的是:

Plaintext
Nginx
负责前台域名下旧后台入口的统一跳转

WordPress MU 插件
负责 WordPress 自己生成的后台 URL 和资源地址

数据库 home/siteurl
保持原值不变

三、创建 admin DNS 记录

在 Cloudflare 中添加:

Plaintext
类型:A
名称:admin
IPv4 地址:源站公网 IP
代理状态:仅 DNS
TTL:自动

必须保持灰色云朵,也就是:

Plaintext
DNS Only

否则后台请求仍然会经过 Cloudflare 代理,无法达到直接访问源站的目的。

服务器端解析验证:

Bash
getent ahostsv4 admin.shuijingwanwq.com | awk 'NR==1{print $1}'

返回源站公网 IP 后,说明解析已经生效。


四、使用 OneinStack 创建独立虚拟主机

我使用 OneinStack 自带的 vhost.sh 创建虚拟主机:

Bash
/root/oneinstack/vhost.sh

主要选项如下:

Plaintext
SSL 类型:
Use Let's Encrypt to Create SSL Certificate and Key

域名:
admin.shuijingwanwq.com

网站目录:
/data/wwwroot/www.shuijingwanwq.com

添加更多域名:
n

HTTP 跳转 HTTPS:
y

证书类型:
ec-256

防盗链:
n

Rewrite:
y

Rewrite 类型:
wordpress

访问日志:
y

这里直接将网站目录设置为现有 WordPress 目录:

Plaintext
/data/wwwroot/www.shuijingwanwq.com

OneinStack 最终创建了:

Plaintext
Nginx 配置:
/usr/local/nginx/conf/vhost/admin.shuijingwanwq.com.conf

证书:
/usr/local/nginx/conf/ssl/admin.shuijingwanwq.com.crt

私钥:
/usr/local/nginx/conf/ssl/admin.shuijingwanwq.com.key

访问日志:
/data/wwwlogs/admin.shuijingwanwq.com_nginx.log
【图 2,OneinStack 成功创建 admin 虚拟主机和 ECC 证书】
【图 2,OneinStack 成功创建 admin 虚拟主机和 ECC 证书】

五、第一次测试:WordPress 自动跳回 www

虚拟主机建立完成后,我直接测试:

Bash
for u in \
"http://admin.shuijingwanwq.com/" \
"https://admin.shuijingwanwq.com/" \
"https://admin.shuijingwanwq.com/wp-login.php" \
"https://admin.shuijingwanwq.com/wp-admin/"
do
  echo
  echo "========== $u =========="

  curl -sS -o /dev/null -D - \
    --max-time 20 \
    --resolve admin.shuijingwanwq.com:80:127.0.0.1 \
    --resolve admin.shuijingwanwq.com:443:127.0.0.1 \
    "$u" \
  | grep -Ei \
    'HTTP/|location:|set-cookie:|x-redirect-by:|content-type:|server:'
done

结果是:

Plaintext
http://admin.../
→ 301 到 https://admin.../

https://admin.../
→ 301 到 https://www.shuijingwanwq.com/

https://admin.../wp-login.php
→ 301 到 https://www.shuijingwanwq.com/wp-login.php

https://admin.../wp-admin/
→ 301 到 https://www.shuijingwanwq.com/wp-admin/

响应中显示:

Plaintext
x-redirect-by: WordPress

但这并不是 WordPress 核心单独造成的。

此前英文站从 /en/ 迁移到独立域名时,也遇到过相同问题。最终确认是 W3 Total Cache Page Cache 的:

Plaintext
redirect_on_foreign_domain

将不在允许列表中的 Host 重新跳回主站域名。


六、让 W3 Total Cache 放行 admin 域名

此前已经存在一个 MU 插件:

Plaintext
wp-content/mu-plugins/w3tc-polylang-domain-fix.php

它会从 Polylang 配置中读取语言域名,并移除 W3TC 的跨域名跳转。

由于 admin.shuijingwanwq.com 不是 Polylang 语言域名,因此需要将它明确加入允许列表。

最终完整文件如下。

wp-content/mu-plugins/w3tc-polylang-domain-fix.php

PHP
<?php
/*
Plugin Name: W3TC Polylang Domain Fix
Description: Prevents W3 Total Cache Page Cache from redirecting valid Polylang language domains back to the main home_url.
*/

add_action('init', function () {
    $host = $_SERVER['HTTP_HOST'] ?? '';

    if ($host === '') {
        return;
    }

    $polylang = get_option('polylang');
    $domains  = $polylang['domains'] ?? array();

    $allowed_hosts = array(
        'admin.shuijingwanwq.com',
    );

    foreach ((array) $domains as $domain) {
        if (!empty($domain)) {
            $parsed = wp_parse_url($domain);

            if (!empty($parsed['host'])) {
                $allowed_hosts[] = strtolower($parsed['host']);
            }
        }
    }

    if (!in_array(strtolower($host), $allowed_hosts, true)) {
        return;
    }

    global $wp_filter;

    if (empty($wp_filter['init']) || empty($wp_filter['init']->callbacks)) {
        return;
    }

    foreach ($wp_filter['init']->callbacks as $priority => $callbacks) {
        foreach ($callbacks as $callback) {
            $function = $callback['function'] ?? null;

            if (
                is_array($function)
                && isset($function[0], $function[1])
                && is_object($function[0])
                && $function[1] === 'redirect_on_foreign_domain'
                && get_class($function[0]) === 'W3TC\PgCache_Plugin'
            ) {
                remove_action('init', $function, $priority);
            }
        }
    }
}, 0);

修改后再次测试:

Plaintext
https://admin.shuijingwanwq.com/
→ 200

https://admin.shuijingwanwq.com/wp-login.php
→ 200

W3TC 的跨域名跳转已经解除。


七、WordPress 生成的登录地址仍然指向 www

W3TC 问题解决后,登录页面虽然已经能通过 admin 打开,但登录表单仍然是:

HTML
<form
  name="loginform"
  id="loginform"
  action="https://www.shuijingwanwq.com/wp-login.php"
  method="post"
>

忘记密码链接也指向:

Plaintext
https://www.shuijingwanwq.com/wp-login.php?action=lostpassword

未登录访问:

Plaintext
https://admin.shuijingwanwq.com/wp-admin/

则会跳转到:

Plaintext
https://www.shuijingwanwq.com/wp-login.php

这部分需要通过 WordPress URL 过滤器解决。


八、创建后台域名兼容 MU 插件

我创建了:

Plaintext
wp-content/mu-plugins/swq-admin-domain.php

这个插件负责:

  • 将后台登录地址改为 admin
  • 将后台管理链接改为 admin
  • 将后台 CSS、JavaScript 和字体改为 admin
  • 将后台 REST API 改为 admin
  • 将后台插件和主题资源改为 admin
  • 从 Polylang 配置中动态读取未来新增的语言域名;
  • 保留前台自己的 admin-ajax.php
  • 保留前台自己的 admin-post.php
  • 保留密码保护文章的 postpass 提交地址;
  • 保持上传文件继续使用 media.shuijingwanwq.com

以下是最终整理后的完整版本。它与当前生产环境中已经通过测试的逻辑一致,仅对注释和排版进行了整理。

wp-content/mu-plugins/swq-admin-domain.php

PHP
<?php
/*
Plugin Name: SWQ Admin Domain
Description: Routes WordPress login, administration resources and backend APIs through admin.shuijingwanwq.com without changing the database home or siteurl options.
Version: 1.0.0
*/

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

if ( ! defined( 'SWQ_ADMIN_BASE_URL' ) ) {
    define( 'SWQ_ADMIN_BASE_URL', 'https://admin.shuijingwanwq.com' );
}

if ( ! defined( 'SWQ_ADMIN_HOST' ) ) {
    define( 'SWQ_ADMIN_HOST', 'admin.shuijingwanwq.com' );
}

/**
 * Normalize an HTTP host for comparison.
 */
function swq_admin_domain_normalize_host( $host ) {
    $host = strtolower( trim( (string) $host ) );
    $host = preg_replace( '/:\d+$/', '', $host );

    return rtrim( $host, '.' );
}

/**
 * Return all WordPress frontend and administration hosts.
 *
 * Future Polylang language domains are read automatically from the
 * Polylang option after they have been configured in WordPress.
 */
function swq_admin_domain_get_managed_hosts() {
    static $hosts = null;

    if ( $hosts !== null ) {
        return $hosts;
    }

    $hosts = array(
        'shuijingwanwq.com'     => true,
        'www.shuijingwanwq.com' => true,
        SWQ_ADMIN_HOST          => true,
    );

    foreach ( array( 'home', 'siteurl' ) as $option_name ) {
        $option_url = get_option( $option_name );

        if ( is_string( $option_url ) && $option_url !== '' ) {
            $option_host = wp_parse_url(
                $option_url,
                PHP_URL_HOST
            );

            $option_host = swq_admin_domain_normalize_host(
                $option_host
            );

            if ( $option_host !== '' ) {
                $hosts[ $option_host ] = true;
            }
        }
    }

    $polylang = get_option( 'polylang' );

    $domains = is_array( $polylang )
        ? ( $polylang['domains'] ?? array() )
        : array();

    foreach ( (array) $domains as $domain ) {
        if ( ! is_string( $domain ) || $domain === '' ) {
            continue;
        }

        $domain_host = wp_parse_url(
            $domain,
            PHP_URL_HOST
        );

        $domain_host = swq_admin_domain_normalize_host(
            $domain_host
        );

        if ( $domain_host !== '' ) {
            $hosts[ $domain_host ] = true;
        }
    }

    /*
     * The uploads hostname is intentionally independent and must not be
     * rewritten to the administration hostname.
     */
    unset( $hosts['media.shuijingwanwq.com'] );

    return $hosts;
}

/**
 * Determine whether a host belongs to the WordPress/Polylang installation.
 */
function swq_admin_domain_is_managed_host( $host ) {
    $host  = swq_admin_domain_normalize_host( $host );
    $hosts = swq_admin_domain_get_managed_hosts();

    return $host !== '' && isset( $hosts[ $host ] );
}

/**
 * Replace the origin of a managed WordPress URL while preserving its
 * path, query string and fragment.
 */
function swq_admin_domain_replace_origin( $url ) {
    if ( ! is_string( $url ) || $url === '' ) {
        return $url;
    }

    $parts = wp_parse_url( $url );

    if (
        ! is_array( $parts )
        || empty( $parts['host'] )
        || ! swq_admin_domain_is_managed_host( $parts['host'] )
    ) {
        return $url;
    }

    $port = isset( $parts['port'] )
        ? ':' . (int) $parts['port']
        : '';

    $pattern = '#^https?://'
        . preg_quote( $parts['host'], '#' )
        . preg_quote( $port, '#' )
        . '(?=/|$)#i';

    return preg_replace(
        $pattern,
        SWQ_ADMIN_BASE_URL,
        $url,
        1
    );
}

/**
 * Return the path portion of a relative WordPress URL.
 */
function swq_admin_domain_get_path_only( $path ) {
    $path     = ltrim( (string) $path, '/' );
    $position = strpos( $path, '?' );

    if ( $position !== false ) {
        $path = substr( $path, 0, $position );
    }

    return $path;
}

/**
 * Return the action query argument from a relative WordPress URL.
 */
function swq_admin_domain_get_url_action( $path ) {
    $path     = (string) $path;
    $position = strpos( $path, '?' );

    if ( $position === false ) {
        return '';
    }

    $query = array();

    parse_str(
        substr( $path, $position + 1 ),
        $query
    );

    return strtolower(
        (string) ( $query['action'] ?? '' )
    );
}

/**
 * Determine whether a backend-looking path is also a public frontend
 * endpoint and therefore must remain on the frontend hostname.
 */
function swq_admin_domain_is_public_frontend_endpoint( $path ) {
    $path_only = swq_admin_domain_get_path_only( $path );

    if (
        in_array(
            $path_only,
            array(
                'wp-admin/admin-ajax.php',
                'wp-admin/admin-post.php',
            ),
            true
        )
    ) {
        return true;
    }

    return (
        $path_only === 'wp-login.php'
        && swq_admin_domain_get_url_action( $path ) === 'postpass'
    );
}

/**
 * Determine whether a site URL belongs to login or administration.
 */
function swq_admin_domain_is_backend_url(
    $path,
    $scheme = null
) {
    if ( swq_admin_domain_is_public_frontend_endpoint( $path ) ) {
        return false;
    }

    $path_only = swq_admin_domain_get_path_only( $path );

    if (
        in_array(
            $scheme,
            array(
                'login',
                'login_post',
                'admin',
            ),
            true
        )
    ) {
        return true;
    }

    return (
        $path_only === 'wp-login.php'
        || $path_only === 'wp-admin'
        || strpos( $path_only, 'wp-admin/' ) === 0
    );
}

/**
 * Determine whether the current request uses the dedicated admin host.
 */
function swq_admin_domain_is_current_request() {
    $host = swq_admin_domain_normalize_host(
        $_SERVER['HTTP_HOST'] ?? ''
    );

    return $host === SWQ_ADMIN_HOST;
}

/**
 * Filter site_url().
 *
 * On the admin host, WordPress application URLs must use the admin host.
 * On frontend hosts, only true login and management URLs are rewritten.
 */
function swq_admin_domain_filter_site_url(
    $url,
    $path,
    $scheme,
    $blog_id
) {
    if (
        swq_admin_domain_is_current_request()
        || swq_admin_domain_is_backend_url(
            $path,
            $scheme
        )
    ) {
        return swq_admin_domain_replace_origin( $url );
    }

    return $url;
}

add_filter(
    'site_url',
    'swq_admin_domain_filter_site_url',
    999,
    4
);

/**
 * Filter network_site_url(), including lost-password URLs.
 */
function swq_admin_domain_filter_network_site_url(
    $url,
    $path,
    $scheme
) {
    if (
        swq_admin_domain_is_current_request()
        || swq_admin_domain_is_backend_url(
            $path,
            $scheme
        )
    ) {
        return swq_admin_domain_replace_origin( $url );
    }

    return $url;
}

add_filter(
    'network_site_url',
    'swq_admin_domain_filter_network_site_url',
    999,
    3
);

/**
 * Replace a generated URL origin with the current managed frontend host.
 */
function swq_admin_domain_replace_origin_with_current_host( $url ) {
    if ( ! is_string( $url ) || $url === '' ) {
        return $url;
    }

    $host = swq_admin_domain_normalize_host(
        $_SERVER['HTTP_HOST'] ?? ''
    );

    if (
        $host === ''
        || $host === SWQ_ADMIN_HOST
        || ! swq_admin_domain_is_managed_host( $host )
    ) {
        return $url;
    }

    $parts = wp_parse_url( $url );

    if (
        ! is_array( $parts )
        || empty( $parts['host'] )
    ) {
        return $url;
    }

    $port = isset( $parts['port'] )
        ? ':' . (int) $parts['port']
        : '';

    $pattern = '#^https?://'
        . preg_quote( $parts['host'], '#' )
        . preg_quote( $port, '#' )
        . '(?=/|$)#i';

    $origin = ( is_ssl() ? 'https' : 'http' )
        . '://'
        . $host;

    return preg_replace(
        $pattern,
        $origin,
        $url,
        1
    );
}

/**
 * Filter ordinary administration URLs.
 *
 * Public AJAX and form endpoints remain on the current frontend host.
 * Inside the dedicated admin host they use the admin hostname.
 */
function swq_admin_domain_filter_admin_url(
    $url,
    $path = '',
    $blog_id = null,
    $scheme = null
) {
    $path_only = swq_admin_domain_get_path_only( $path );

    if (
        ! swq_admin_domain_is_current_request()
        && in_array(
            $path_only,
            array(
                'admin-ajax.php',
                'admin-post.php',
            ),
            true
        )
    ) {
        return swq_admin_domain_replace_origin_with_current_host(
            $url
        );
    }

    return swq_admin_domain_replace_origin( $url );
}

add_filter(
    'admin_url',
    'swq_admin_domain_filter_admin_url',
    999,
    4
);

/**
 * Filter network administration URLs.
 */
function swq_admin_domain_filter_network_admin_url(
    $url,
    $path = '',
    $scheme = null
) {
    return swq_admin_domain_replace_origin( $url );
}

add_filter(
    'network_admin_url',
    'swq_admin_domain_filter_network_admin_url',
    999,
    3
);

/**
 * Authentication URLs.
 */
add_filter(
    'login_url',
    'swq_admin_domain_replace_origin',
    999
);

add_filter(
    'lostpassword_url',
    'swq_admin_domain_replace_origin',
    999
);

add_filter(
    'logout_url',
    'swq_admin_domain_replace_origin',
    999
);

add_filter(
    'register_url',
    'swq_admin_domain_replace_origin',
    999
);

/**
 * Rewrite final CSS and JavaScript URLs only while rendering admin.
 */
function swq_admin_domain_filter_asset_src(
    $src,
    $handle = ''
) {
    if ( ! swq_admin_domain_is_current_request() ) {
        return $src;
    }

    return swq_admin_domain_replace_origin( $src );
}

add_filter(
    'style_loader_src',
    'swq_admin_domain_filter_asset_src',
    999,
    2
);

add_filter(
    'script_loader_src',
    'swq_admin_domain_filter_asset_src',
    999,
    2
);

/**
 * Keep REST API requests generated inside wp-admin off the frontend CDN.
 */
function swq_admin_domain_filter_rest_url(
    $url,
    $path,
    $blog_id,
    $scheme
) {
    if ( ! swq_admin_domain_is_current_request() ) {
        return $url;
    }

    return swq_admin_domain_replace_origin( $url );
}

add_filter(
    'rest_url',
    'swq_admin_domain_filter_rest_url',
    999,
    4
);

/**
 * Rewrite WordPress-generated plugin, content, include and theme
 * resources while serving the dedicated administration hostname.
 */
function swq_admin_domain_filter_generated_resource_url( $url ) {
    if ( ! swq_admin_domain_is_current_request() ) {
        return $url;
    }

    return swq_admin_domain_replace_origin( $url );
}

add_filter(
    'plugins_url',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'content_url',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'includes_url',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'theme_root_uri',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'template_directory_uri',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'stylesheet_directory_uri',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'theme_file_uri',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

add_filter(
    'parent_theme_file_uri',
    'swq_admin_domain_filter_generated_resource_url',
    999
);

保存后执行语法检查:

Bash
php -l wp-content/mu-plugins/swq-admin-domain.php

返回:

Plaintext
No syntax errors detected in wp-content/mu-plugins/swq-admin-domain.php

服务器端最终写入和语法检查记录也已经保留。


九、后台资源最初仍然经过 www

登录进入 admin 后,页面地址虽然已经保持为:

Plaintext
https://admin.shuijingwanwq.com/wp-admin/

但浏览器开发者工具显示,许多后台资源仍然从:

Plaintext
www.shuijingwanwq.com

加载。

其中包括:

  • load-styles.php
  • 插件 CSS;
  • 插件 JavaScript;
  • 字体文件;
  • wp-content/plugins 资源;
  • 部分主题资源。
【图 3,admin 后台打开成功,但网络面板仍出现大量 www 资源请求】
【图 3,admin 后台打开成功,但网络面板仍出现大量 www 资源请求】

由于后台页面本身位于 admin 域名,这些跨域字体和脚本还触发了:

Plaintext
CORS Missing Allow Origin

正确的处理方式不是在 www 上开放 CORS,而是让后台资源本身也通过 admin 加载。

MU 插件最终补充了这些过滤器:

Plaintext
site_url
network_site_url
admin_url
network_admin_url
login_url
lostpassword_url
logout_url
register_url
style_loader_src
script_loader_src
rest_url
plugins_url
content_url
includes_url
theme_root_uri
template_directory_uri
stylesheet_directory_uri
theme_file_uri
parent_theme_file_uri

完成后,在开发者工具中筛选:

Plaintext
www.shuijingwanwq.com

和:

Plaintext
en.shuijingwanwq.com

均显示:

Plaintext
没有请求
【图 4,最终后台网络请求中筛选 www 和 en 均无结果】
【图 4,最终后台网络请求中筛选 www 和 en 均无结果】

十、统一所有前台域名的后台入口

仅仅让 admin 本身正常工作还不够。

原来的前台域名仍然可以访问:

Plaintext
https://www.shuijingwanwq.com/wp-login.php
https://www.shuijingwanwq.com/wp-admin/

https://en.shuijingwanwq.com/wp-login.php
https://en.shuijingwanwq.com/wp-admin/

此前 Nginx 中还存在一段旧规则:

Nginx
# Redirect non-www admin/login requests to the main www domain.

它会将 en 和裸域的后台请求先跳转到 www

既然后台已经统一迁移到 admin,这段逻辑就应该替换为:

Plaintext
所有前台语言域名的后台管理入口

admin.shuijingwanwq.com

同时必须保留三个前台接口:

Plaintext
/wp-admin/admin-ajax.php
/wp-admin/admin-post.php
/wp-login.php?action=postpass

原因是:

  • admin-ajax.php 可能被前台主题或插件调用;
  • admin-post.php 可能承担前台表单提交;
  • postpass 用于密码保护文章,Cookie 应保留在当前前台域名。

十一、后台跳转 map 配置

新建:

Plaintext
/usr/local/nginx/conf/include/shuijingwan_admin_redirect_map.conf

完整内容如下。

shuijingwan_admin_redirect_map.conf

Nginx
# 所有前台语言域名共用的 WordPress 后台入口判断。
#
# 以下前台接口保留在原域名:
# - /wp-admin/admin-ajax.php
# - /wp-admin/admin-post.php
# - /wp-login.php?action=postpass

map "$uri|$arg_action" $swq_frontend_admin_redirect {
    default 0;

    # 前台 AJAX 与表单接口。
    ~*^/wp-admin/admin-(?:ajax|post)\.php\| 0;

    # 密码保护文章提交接口。
    ~*^/wp-login\.php\|postpass$ 0;

    # 其他登录和后台管理入口。
    ~*^/wp-login\.php\| 1;
    ~*^/wp-admin(?:/.*)?\| 1;
}

这里使用 map,可以让路径判断保持清晰,也方便以后扩展新的例外接口。


十二、server 上下文跳转配置

新建:

Plaintext
/usr/local/nginx/conf/include/shuijingwan_admin_redirect_server.conf

完整内容如下。

shuijingwan_admin_redirect_server.conf

Nginx
# 将前台语言域名下的登录和后台管理入口统一转到独立后台域名。
# 307 可保留旧登录表单 POST 请求的方法与正文。

if ($swq_frontend_admin_redirect = 1) {
    return 307 https://admin.shuijingwanwq.com$request_uri;
}

这里使用的是:

Plaintext
307 Temporary Redirect

而不是 301 或普通 302

主要原因是,假如用户仍然从旧登录页面提交 POST 表单,307 可以保留原来的请求方法和正文,避免用户名、密码或其他表单内容在跳转过程中丢失。


十三、最终 www 虚拟主机配置

当前中文、英文和裸域仍然共用:

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

以下是最终完整内容。

其中原有的 3,900 多行标签映射仍然保存在独立的:

Plaintext
shuijingwan_nginx_redirect.conf

中,因此没有必要在本文重复展开这些与后台迁移无直接关系的站点专用规则。

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

Nginx
# 引入生成的 map 规则(位于 server 外部,属于 http 上下文)
include /usr/local/nginx/conf/include/shuijingwan_nginx_redirect.conf;

# 引入 en.shuijingwanwq.com 独立旧路径规则
include /usr/local/nginx/conf/include/shuijingwan_en_redirect.conf;

# 引入所有前台语言域名共用的后台入口判断
include /usr/local/nginx/conf/include/shuijingwan_admin_redirect_map.conf;

server {
  limit_req zone=site_limit burst=50 nodelay;
  limit_conn conn_limit 50;
  limit_req_status 429;

  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.crt;
  ssl_certificate_key /usr/local/nginx/conf/ssl/www.shuijingwanwq.com.key;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;

  ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;

  ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256;
  ssl_conf_command Options PrioritizeChaCha;

  ssl_prefer_server_ciphers on;
  ssl_session_timeout 10m;
  ssl_session_cache shared:SSL:10m;
  ssl_buffer_size 2k;

  add_header Strict-Transport-Security max-age=15768000;

  ssl_stapling on;
  ssl_stapling_verify on;

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

  access_log /data/wwwlogs/www.shuijingwanwq.com_nginx.log combined;

  index index.html index.htm index.php;
  root /data/wwwroot/www.shuijingwanwq.com;

  if ($ssl_protocol = "") {
    return 301 https://$host$request_uri;
  }

  # 所有前台语言域名共用的后台入口跳转
  include /usr/local/nginx/conf/include/shuijingwan_admin_redirect_server.conf;

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

  include /usr/local/nginx/conf/rewrite/wordpress.conf;

  #error_page 404 /404.html;
  #error_page 502 /502.html;

  location ~ .*\.(wma|wmv|asf|mp3|mmf|zip|rar|jpg|gif|png|swf|flv|mp4)$ {
    valid_referers
      none
      blocked
      *.shuijingwanwq.com
      www.shuijingwanwq.com
      shuijingwanwq.com;

    if ($invalid_referer) {
      return 403;
    }
  }

  # 批量重定向所有 /amp 后缀链接至原规范页面
  location ~* ^(.+)/amp/?$ {
    return 301 $1/;
  }

  # 旧标签、旧专题先映射,再一次跳转到最终中文或英文域名
  if ($www_final_redirect_uri != "") {
    return 301 $www_final_redirect_uri$is_args$args;
  }

  # 未命中旧规则的普通 /en/ 页面迁移到英文子域名
  if ($www_en_migration_uri != "") {
    return 301 $www_en_migration_uri$is_args$args;
  }

  # en 子域名自己的旧标签、旧专题路径跳转
  if ($en_final_redirect_uri != "") {
    return 301 $en_final_redirect_uri$is_args$args;
  }

  location ~ [^/]\.php(/|$) {
    #fastcgi_pass remote_php_ip:9000;
    fastcgi_pass unix:/dev/shm/php-cgi.sock;
    fastcgi_index index.php;
    fastcgi_read_timeout 150s;
    include fastcgi.conf;
  }

  location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
    expires 30d;
    access_log off;
  }

  location ~ .*\.(js|css)?$ {
    expires 7d;
    access_log off;
  }

  location ~ /(\.user\.ini|\.ht|\.git|\.svn|\.project|LICENSE|README\.md) {
    deny all;
  }

  location /.well-known {
    allow all;
  }
}

十四、最终 admin 虚拟主机配置

admin 使用独立证书、日志和虚拟主机,但与主站共用 WordPress 目录。

为了避免搜索引擎将 admin 域名下可能访问到的前台页面作为重复内容收录,我在 Nginx 中增加了:

Plaintext
X-Robots-Tag: noindex, nofollow, noarchive

/usr/local/nginx/conf/vhost/admin.shuijingwanwq.com.conf

Nginx
server {
  listen 80;
  listen [::]:80;
  listen 443 ssl http2;
  listen [::]:443 ssl http2;

  ssl_certificate /usr/local/nginx/conf/ssl/admin.shuijingwanwq.com.crt;
  ssl_certificate_key /usr/local/nginx/conf/ssl/admin.shuijingwanwq.com.key;

  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;

  ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256;

  ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256;
  ssl_conf_command Options PrioritizeChaCha;

  ssl_prefer_server_ciphers on;
  ssl_session_timeout 10m;
  ssl_session_cache shared:SSL:10m;
  ssl_buffer_size 2k;

  add_header Strict-Transport-Security max-age=15768000;

  ssl_stapling on;
  ssl_stapling_verify on;

  server_name admin.shuijingwanwq.com;

  add_header X-Robots-Tag "noindex, nofollow, noarchive" always;

  access_log /data/wwwlogs/admin.shuijingwanwq.com_nginx.log combined;

  index index.html index.htm index.php;
  root /data/wwwroot/www.shuijingwanwq.com;

  if ($ssl_protocol = "") {
    return 301 https://$host$request_uri;
  }

  include /usr/local/nginx/conf/rewrite/wordpress.conf;

  #error_page 404 /404.html;
  #error_page 502 /502.html;

  location ~ [^/]\.php(/|$) {
    #fastcgi_pass remote_php_ip:9000;
    fastcgi_pass unix:/dev/shm/php-cgi.sock;
    fastcgi_index index.php;
    include fastcgi.conf;
  }

  location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
    expires 30d;
    access_log off;
  }

  location ~ .*\.(js|css)?$ {
    expires 7d;
    access_log off;
  }

  location ~ /(\.user\.ini|\.ht|\.git|\.svn|\.project|LICENSE|README\.md) {
    deny all;
  }

  location /.well-known {
    allow all;
  }
}

配置检测和重载:

Bash
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

响应头验证:

Bash
curl -sS -o /dev/null -D - \
  --resolve admin.shuijingwanwq.com:443:127.0.0.1 \
  "https://admin.shuijingwanwq.com/" \
| grep -Ei \
  'HTTP/|x-robots-tag:|strict-transport-security:'

返回:

Plaintext
HTTP/2 200
strict-transport-security: max-age=15768000
x-robots-tag: noindex, nofollow, noarchive

十五、前台接口与后台入口验证

源站直连测试:

Bash
for host in \
"www.shuijingwanwq.com" \
"en.shuijingwanwq.com" \
"shuijingwanwq.com"
do
  for path in \
  "/wp-login.php" \
  "/wp-admin/" \
  "/wp-admin/update-core.php" \
  "/wp-admin/admin-ajax.php" \
  "/wp-admin/admin-post.php" \
  "/wp-login.php?action=postpass"
  do
    echo
    echo "========== https://$host$path =========="

    curl -sS -o /dev/null -D - \
      --max-time 20 \
      --resolve "$host:443:127.0.0.1" \
      "https://$host$path" \
    | grep -Ei \
      'HTTP/|location:|x-redirect-by:|set-cookie:'
  done
done

最终结果:

Plaintext
www / en / 裸域:

/wp-login.php
→ 307 到 admin

/wp-admin/
→ 307 到 admin

/wp-admin/update-core.php
→ 307 到 admin

/wp-admin/admin-ajax.php
→ 保留在当前前台域名

/wp-admin/admin-post.php
→ 保留在当前前台域名

/wp-login.php?action=postpass
→ 保留在当前前台域名

裸域的公共接口继续先规范化到 www,属于原有裸域跳转行为。


十六、EdgeOne 和 Cloudflare 公网验证

不使用 --resolve,直接测试公网 CDN 链路:

Bash
for u in \
"https://www.shuijingwanwq.com/wp-login.php" \
"https://www.shuijingwanwq.com/wp-admin/" \
"https://www.shuijingwanwq.com/wp-admin/admin-ajax.php" \
"https://en.shuijingwanwq.com/wp-login.php" \
"https://en.shuijingwanwq.com/wp-admin/" \
"https://en.shuijingwanwq.com/wp-admin/admin-ajax.php"
do
  echo
  echo "========== $u =========="

  curl -sS -o /dev/null -D - \
    --max-time 20 \
    "$u?swq_test=$(date +%s)" \
  | grep -Ei \
    'HTTP/|location:|server:|eo-cache-status:|cf-cache-status:'
done

EdgeOne 返回:

Plaintext
wp-login.php:
HTTP/2 307
location: https://admin.shuijingwanwq.com/wp-login.php
eo-cache-status: MISS

wp-admin/:
HTTP/2 307
location: https://admin.shuijingwanwq.com/wp-admin/
eo-cache-status: MISS

admin-ajax.php:
HTTP/2 400
eo-cache-status: MISS

Cloudflare 返回:

Plaintext
wp-login.php:
HTTP/2 307
location: https://admin.shuijingwanwq.com/wp-login.php
cf-cache-status: DYNAMIC

wp-admin/:
HTTP/2 307
location: https://admin.shuijingwanwq.com/wp-admin/
cf-cache-status: DYNAMIC

admin-ajax.php:
HTTP/2 400
cf-cache-status: DYNAMIC

admin-ajax.php 在没有携带 action 参数时返回 400,属于 WordPress 的正常响应。


十七、运行时 URL 验证

通过 PHP 分别模拟 wwwenadmin Host:

Bash
cd /data/wwwroot/www.shuijingwanwq.com

for host in \
"www.shuijingwanwq.com" \
"en.shuijingwanwq.com" \
"admin.shuijingwanwq.com"
do
  echo
  echo "========== $host =========="

  SWQ_TEST_HOST="$host" php -r '
  $host = getenv("SWQ_TEST_HOST");

  $_SERVER["HTTP_HOST"]   = $host;
  $_SERVER["SERVER_NAME"] = $host;
  $_SERVER["HTTPS"]       = "on";
  $_SERVER["SERVER_PORT"] = "443";
  $_SERVER["REQUEST_URI"] = "/";

  require "wp-load.php";

  echo "admin_url  : " . admin_url() . "\n";
  echo "admin-ajax : " . admin_url("admin-ajax.php") . "\n";
  echo "admin-post : " . admin_url("admin-post.php") . "\n";
  echo "login_url  : " . wp_login_url() . "\n";
  echo "rest_url   : " . rest_url() . "\n";
  '
done

最终输出为:

Plaintext
www.shuijingwanwq.com

admin_url:
https://admin.shuijingwanwq.com/wp-admin/

admin-ajax:
https://www.shuijingwanwq.com/wp-admin/admin-ajax.php

admin-post:
https://www.shuijingwanwq.com/wp-admin/admin-post.php

login_url:
https://admin.shuijingwanwq.com/wp-login.php

rest_url:
https://www.shuijingwanwq.com/wp-json/
Plaintext
en.shuijingwanwq.com

admin_url:
https://admin.shuijingwanwq.com/wp-admin/

admin-ajax:
https://en.shuijingwanwq.com/wp-admin/admin-ajax.php

admin-post:
https://en.shuijingwanwq.com/wp-admin/admin-post.php

login_url:
https://admin.shuijingwanwq.com/wp-login.php

rest_url:
https://en.shuijingwanwq.com/wp-json/
Plaintext
admin.shuijingwanwq.com

admin_url:
https://admin.shuijingwanwq.com/wp-admin/

admin-ajax:
https://admin.shuijingwanwq.com/wp-admin/admin-ajax.php

admin-post:
https://admin.shuijingwanwq.com/wp-admin/admin-post.php

login_url:
https://admin.shuijingwanwq.com/wp-login.php

rest_url:
https://admin.shuijingwanwq.com/wp-json/

这说明前台接口、语言域名 REST API 和后台管理地址已经正确分离。


十八、通过 admin 成功升级 WordPress

迁移完成后,我在:

Plaintext
https://admin.shuijingwanwq.com/wp-admin/

重新执行 WordPress 核心升级。

此次升级顺利完成,没有再次出现 EdgeOne 524,也没有卡在升级页面。

最终版本:

Plaintext
WordPress 7.0.1
【图 5,通过 admin 子域名成功完成 WordPress 7.0.1 核心升级】
【图 5,通过 admin 子域名成功完成 WordPress 7.0.1 核心升级】

服务器端检查:

Bash
cd /data/wwwroot/www.shuijingwanwq.com

php -r '
require "wp-includes/version.php";

echo "WordPress 版本:{$wp_version}\n";

echo "维护模式文件:";
echo file_exists(".maintenance")
    ? "存在\n"
    : "不存在\n";

$_SERVER["HTTP_HOST"] = "admin.shuijingwanwq.com";
$_SERVER["HTTPS"] = "on";

require "wp-load.php";

echo "core_updater.lock:";
echo get_option("core_updater.lock") === false
    ? "不存在\n"
    : "仍然存在\n";
'

输出:

Plaintext
WordPress 版本:7.0.1
维护模式文件:不存在
core_updater.lock:不存在

这次升级结果实际证明:此前的失败主要与后台请求经过 CDN 链路有关,而不是 WordPress 文件权限、核心文件或服务器环境本身损坏。


十九、CDN 缓存规则是否需要修改

这次迁移完成后,我没有继续修改 EdgeOne 或 Cloudflare 的缓存规则。

现有规则已经能够保证:

Plaintext
/wp-login.php
/wp-admin/*
/wp-admin/admin-ajax.php
/wp-admin/admin-post.php
/wp-json/*

不被页面缓存。

公网验证中也已经看到:

Plaintext
EdgeOne:
eo-cache-status: MISS

Cloudflare:
cf-cache-status: DYNAMIC

因此,没有必要再在 EdgeOne 和 Cloudflare 中分别建立后台跳转。

后台入口统一跳转继续由 Nginx 负责,优点是:

  • EdgeOne 和 Cloudflare 使用同一套源站逻辑;
  • 不会出现两套 CDN 规则不一致;
  • 可以精确保留 admin-ajax.php
  • 可以精确保留 admin-post.php
  • 可以精确保留 postpass
  • 未来新增语言域名后可以自动继承。

admin.shuijingwanwq.com 本身使用 DNS Only,不经过 CDN,因此也不需要单独配置缓存规则。


二十、未来新增语言域名时如何处理

当前 Nginx 后台跳转规则并没有写死 wwwen

只要未来新增的语言域名:

  1. 配置 DNS;
  2. 加入服务器证书;
  3. 加入当前前台虚拟主机的 server_name
  4. 在 Polylang 中配置为语言域名;

就可以自动继承:

Plaintext
/wp-login.php
/wp-admin/*

admin.shuijingwanwq.com

PHP MU 插件也会从:

PHP
get_option( 'polylang' )

动态读取 Polylang 的 domains 配置,因此不需要再手动添加:

Plaintext
fr.shuijingwanwq.com
de.shuijingwanwq.com
es.shuijingwanwq.com

这比在 PHP 中写死:

PHP
(?:www|en|admin)

更适合长期维护。


二十一、这次迁移解决了什么

最终已经确认:

  • admin 使用独立 Nginx 虚拟主机;
  • admin 使用独立 ECC HTTPS 证书;
  • admin 通过 DNS Only 直连源站;
  • 后台页面不再经过 EdgeOne;
  • 后台资源不再经过 EdgeOne;
  • 后台资源不再经过英文站 Cloudflare;
  • WordPress 登录、忘记密码和退出地址统一使用 admin
  • wwwen 和裸域后台入口统一跳到 admin
  • 前台 AJAX、表单和文章密码提交没有被误伤;
  • Polylang 未来新增语言域名可动态兼容;
  • W3 Total Cache 不再将 admin 跳回 www
  • admin 已添加 noindex, nofollow, noarchive
  • WordPress 7.0.1 核心升级成功;
  • .maintenance 不存在;
  • core_updater.lock 不存在;
  • 中文站、英文站和旧 /en/ 跳转均保持正常。

二十二、这次迁移没有解决什么

需要保持客观的是,这次后台迁移并不会直接消除 EdgeOne 每天约 2.9 GB 的流量。

后台访问通常只有管理员本人,产生的流量远小于前台访客、搜索引擎和静态资源请求。

因此,这次迁移的主要价值是:

Plaintext
提高后台稳定性
解决长请求超时
降低后台操作对 CDN 的依赖
减少一部分不必要的 EdgeOne 流量
建立清晰的前后台网络边界

后续如果要继续降低 EdgeOne 用量,仍然需要单独分析:

  • 中文前台 HTML 流量;
  • 非 uploads 静态文件;
  • 字体文件;
  • 爬虫请求;
  • 标签页和分页;
  • 缓存命中率;
  • 高频访问来源;
  • 是否还有资源可以迁移到其他静态域名。

二十三、总结

最开始,我只是希望解决一次 WordPress 核心升级失败的问题。

但真正排查后发现,后台迁移并不是简单添加一个 DNS 记录和 Nginx 虚拟主机就能完成。

完整链路还涉及:

Plaintext
DNS
HTTPS 证书
Nginx 虚拟主机
W3 Total Cache 跨域名跳转
WordPress site_url
WordPress admin_url
登录表单
后台静态资源
REST API
Polylang 多域名
前台 AJAX
前台表单
文章密码 Cookie
搜索引擎隔离
EdgeOne
Cloudflare

最终采用的职责划分是:

Plaintext
Nginx:
统一前台语言域名下的后台入口

MU 插件:
修正 WordPress 生成的后台 URL 和资源

W3TC 补丁:
放行合法的多域名 Host

CDN:
保持后台路径不缓存,不负责核心跳转

数据库:
home 和 siteurl 保持不变

完成这些调整后,WordPress 后台已经真正从前台 CDN 链路中独立出来。

而最有说服力的验证结果,并不是某一条配置检查通过,而是:

Plaintext
WordPress 7.0.1 已经通过
admin.shuijingwanwq.com
成功完成在线升级

此前经过 EdgeOne 时出现的 524 超时,没有再次发生。

WordPress 英文站从 /en/ 迁移到 en 子域名:兼容数千条 Nginx 旧规则并避免二次 301

Linux 服务器运维、部署与线上故障排查

如果你的网站或后端服务部署在 Linux 服务器上,遇到访问异常、Nginx 配置问题、MySQL / Redis 异常、Docker 服务不可用、磁盘占满、CPU / 内存过高等问题,可以联系我做一次远程排查。

适合以下场景:
✅ 网站打不开或访问不稳定
✅ Nginx / PHP-FPM 配置异常
✅ MySQL / Redis 性能或连接问题
✅ Docker 服务部署与维护
✅ 服务器迁移与环境配置
✅ CPU / 内存 / 磁盘异常排查

服务内容:
✅ Linux 环境检查
✅ 网站部署与迁移
✅ Nginx / PHP-FPM / MySQL / Redis 排查
✅ Docker 配置与维护
✅ 服务器性能分析
✅ 长期远程运维支持

如需咨询,请联系我,并注明:Linux 运维咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

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

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