使用 1Panel 和内网穿透部署 WordPress 实例要点备忘

今天为了测试一个程序,需要同时搭建两个 WordPress 实例,特别是依赖于部分非缺省的 PHP 扩展,1Panel 应用商店里的 WordPress 对应的 PHP 环境相对固化,难以满足个性化需求,因此最终选择了手动创建网站实例,然后通过容器化方式单独挂载运行 PHP 和 MySQL。这样做的最大好处是自由度较高,可自由选择 PHP 或 MySQL 版本,如对 PHP 扩展有特定要求,也方便安装维护。

我的服务器在内网,通过 FRP 内网穿透方式实现公网访问,且两个实例均使用了 Redis 缓存。

今天在部署过程中踩了不少坑,为方便后续查阅,避免反复通过 AI 寻求解决办法,因此把几个核心要点记录下来。

一、frp 内网穿透下的端口暴露与 Nginx 配置

因为使用了 frp 进行内网穿透,外部流量经过穿透到达本地的 Nginx (具体为:OpenResty)时,会发生端口号暴露。例如访问 domain.com/wp-admin (最后没有以 / 结尾)时,会默认跳转为 domain.com:8585/wp-admin/ (出现的端口号 8585 即本地搭建时网站实例的端口号),导致无法访问。

1、修改本地 1Panel 的 Nginx 配置

为解决这个问题,需修改本地网站的 Nginx 配置文件,关闭绝对重定向和端口重定向:

# 在 Nginx 站点的 server 块中添加或修改以下配置(找个位置靠前些的)
server {
    # ... 其他配置 ...
    
    # 避免 Nginx 在做目录重定向时带上非标准端口号
    absolute_redirect off; # 会让 Nginx 直接返回相对路径的重定向指令,比如让浏览器直接跳到 /wp-admin/,从而完美避开域名和端口的拼接错误。
    port_in_redirect off;
    
    # ... 其他配置 ...
}

2、检查反向代理的 Header 头(可选但推荐)

为了防止 WordPress 内部的其他链接也错误识别端口,需确保 frp 服务端在反向代理时,把真实情况传递给了内网。

检查外网服务器反向代理配置( location / { ... } 内部),确保包含以下 Header 参数:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-Host $host;

这一步的作用是强制要求内网的 1Panel :“外面的访客是用 443 端口访问的,生成任何链接时都别把 8585 露出来”。

二、解决混合资源(Mixed Content)与 403 报错

目前我采取的是通过 FRP 的 HTTP 协议实现域名访问内网服务,还需要在 FRP 服务器中通过 nginx 的反向代理,实现去端口化以及 SSL 协议。

但 frp 反向代理( 外网 HTTPS -> frp -> 内网 1Panel Nginx -> Docker PHP )的架构下,代理服务器传递的 HTTPS 协议头( X-Forwarded-Proto )容易丢失,导致以下两个问题:

  1. 后台无限重定向:WordPress 发现后台需要 HTTPS,试图重定向到 HTTPS,但重新请求进来又被识别为 HTTP,从而陷入死循环,提示重定向次数过多。
  2. 前台 Mixed Content 报错:网页加载的静态资源(SVG、CSS、JS)全部被强制输出为 http:// 开头的链接,被浏览器拦截,导致页面样式错乱及控制台报错。

解决方法很简单,即通过 WordPress 的配置文件 wp-config.php ,在 /* That's all, stop editing! Happy publishing. */ 这一行之前,强制开启 HTTPS 识别,并固定站点 URL:

// 强制开启 HTTPS,无视反向代理的头部丢失问题
$_SERVER['HTTPS'] = 'on';
define('FORCE_SSL_ADMIN', true);

// 强制定义主页和站点 URL,防止数据库中记录的 http 协议引发错误
define('WP_HOME', 'https://domain.com');
define('WP_SITEURL', 'https://domain.com');

此外,为了让 frp 后的应用更好地感知真实请求,建议在 frp 服务端的 Nginx 反向代理配置中,确保传递了正确的请求头。在 Nginx 的 location 块中添加(可选但推荐):

proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Ssl on;

三、解除 PHP 上传文件尺寸及等待时间限制

上传文件时,因文件大小超出默认 PHP 最大允许文件上传尺寸,造成上传失败,修改 php.ini 即可,通过 1Panel --> 网站 --> 运行环境 ,提供了可视化修改。

主要修改以下参数:

max_execution_time:默认通常是 30,改大一点,比如 300 或 600。

max_input_time:也改成 300 左右。

upload_max_filesizepost_max_size:确保这两个值大于导入文件的大小(比如改成 50M 或 100M)。

四、Redis 容器化部署与多实例隔离

因需要,两个 WordPress 实例均需开启 Redis 缓存,使用 Redis Object Cache 缓存插件来连接 Redis 服务。

我的 Redis 服务是通过 1Panel 应用商店直接安装,即容器化部署。总的来说,WordPress 所处的环境如下:

  • WordPress 本地主机中部署
  • PHP 容器化部署
  • Redis 容器化部署
  • Openresty 容器化部署

安装 Redis Object Cache 插件,启用时直接报错:Redis 无法访问: Connection refused [tcp://127.0.0.1:6379]

默认的 Redis 服务地址为 127.0.0.1 ,这在传统环境下没问题。但在 Docker 容器化部署中,如果 PHP 填写 127.0.0.1 ,实际上是在尝试连接 PHP 容器内部的地址,自然找不到外部的 Redis 容器!

把连接地址改为 Redis 的容器名,即可让 PHP 正常与 Redis 容器通信。详细操作如下,同时也顺带解决了多实例 WordPress 共用一个 Redis 容器的隔离问题。

1、修改 object-cache.php 配置文件

文件位置在:/wp-content/plugins/redis-cache/includes/object-cache.php

找到 build_parameters() 函数,默认配置如下:

protected function build_parameters() {
    $parameters = [
        'scheme' => 'tcp',
        'host' => '127.0.0.1',
        'port' => 6379,
        'database' => 0,
        'timeout' => 1,
        'read_timeout' => 1,
        'retry_interval' => null,
        'persistent' => false,
    ];

将其修改为:

protected function build_parameters() {
    $parameters = [
        'scheme' => 'tcp',
        'host' => '1Panel-redis-kpTr', // 将 127.0.0.1 修改为 Docker 的容器名
        'port' => 6379,
        'database' => 0, // 注意这里:多网站隔离时,第一个网站用 0,第二个网站改用 1
        'password' => 'password', // 改为 Redis 的密码
        'timeout' => 1,
        'read_timeout' => 1,
        'retry_interval' => null,
        'persistent' => false,
    ];

小提示:Redis 默认自带了 16 个逻辑数据库(编号从 0 到 15)。可以通过修改这里的 ‘database’ => 0 为其他数字,来区分不同网站的不同 Redis 数据库,完全不用重复创建 Redis 容器。

2、修改 wp-config.php 配置文件

在最下方添加如下代码:

/** Redis Object Cache */
define( 'WP_REDIS_HOST', '1Panel-redis-kpTr' ); // Redis 容器名
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_PASSWORD', 'password' ); // Redis设置了密码时填写

保存上述文件后,回到 WordPress 控制台的插件界面刷新,点击开启即可。

其他:如何清除 Redis 的指定数据库

1. 登录 Redis CLI:

在终端中输入以下命令进入 Redis 的交互模式,并使用密码进行身份验证:

redis-cli

按下回车后,接着输入授权命令:

AUTH password

如果密码正确,系统会返回 OK。

2. 切换到 0 号数据库:

Redis 默认登录后就是 0 号数据库,但为了绝对安全,手动指定一下:

SELECT 0

系统会返回 OK。

3. 清空当前数据库

在确认当前是 0 号数据库后,输入以下命令清空它:

FLUSHDB

系统会返回 OK,此时 0 号数据库的数据已经被彻底清空。

在这个界面下,绝对不要输入 FLUSHALL 命令。FLUSHDB 只清空当前所在的库,而 FLUSHALL 会把 015 号库全部干掉。

4. 验证并退出

输入以下命令查看当前数据库的键值数量,确认是否已经清零:

DBSIZE

如果返回 (integer) 0,说明清理成功。

最后,输入 exit 退出 Redis 交互模式,再关闭终端窗口即可。

评论