# PanelAlpha Engine 实测：AI 管理 VPS，能替代 GitHub Self-hosted Runner 吗？

> Canonical: https://vxi.me/posts/panelalpha-engine-vps-hosting-control-plane/
> Locale: zh-cn
> Published: 2026-10-08
> Updated: 2026-10-08
> Markdown: https://vxi.me/posts/panelalpha-engine-vps-hosting-control-plane.md

我现在的生产发布链已经比较固定：代码进 GitHub，受保护的 workflow 决定什么时候发布，Self-hosted Runner 只负责在服务器上执行已经审查过的步骤。前段时间看到 [PanelAlpha Engine 的 Show HN](https://news.ycombinator.com/item?id=49991829)，我最想确认的不是“AI 能不能帮我部署”，而是另一个更实际的问题：如果把应用生命周期交给一个 MCP 控制面，它和现有 Runner 到底是什么关系？

我用一台独立的 Ubuntu 24.04.2 测试 VPS 跑了 PanelAlpha Engine v2.1.1。这个版本截至本次 QA 仍是项目的 [GitHub latest release](https://github.com/panelalpha/panelalpha-engine/releases/tag/v2.1.1)。结果没有跑到一个漂亮的“一键部署成功”：在 1 vCPU、1.9 GiB RAM、50 GB 磁盘的机器上，安装超过两小时仍停在 Engine 安装阶段，最后记录的进度是 70%，我主动终止了后续实验。

这并不能证明 PanelAlpha “装不上”。它真正给我的信息是：这不是一个轻量的 AI 命令执行器，而是一套会进入 Docker、网络、防火墙、项目隔离、备份和监控边界的 Hosting Control Plane。安装没跑完，反而足够让我重新判断它是否应该拿来替代现有的 Self-hosted Runner。

## 我没有把它装到生产机，先看一台干净 VPS 会发生什么

这次测试从一台干净 VPS 开始。实验前没有 Docker，`docker version` 返回 127；系统里也没有可用的 `iptables` 和 `nft` 命令，监听端口基本只有 SSH 与 chrony。这个基线很重要，因为后面看到的 Docker 和防火墙变化，至少可以明确归因到安装过程，而不是机器之前留下的配置。

PanelAlpha 自己的 [安装文档](https://github.com/panelalpha/panelalpha-engine/blob/1e19bbf22a49c638f9e886fde653e02bbdc4bea5/docs/02-getting-started/install.md) 也把边界写得很清楚：它更适合一台新的、专用的 Debian / Ubuntu VPS。源码里的安装器还包含 `systemd-resolved`、`/etc/resolv.conf`、Docker 网络和主机防火墙处理逻辑。这也是为什么我没有拿现有博客 Runner 或其他生产机器做实验。

实际执行前，我先把 bootstrap 下载为文件并计算 SHA-256，而不是直接 `curl | sh`：

```console
$ curl -fsSL https://get.panelalpha.com/engine -o panelalpha-installer.sh
$ sha256sum panelalpha-installer.sh
5d3c436269e09f8a813073691f61ad18329c0b87a818cb7fc3481344ac8e2496
```

测试版本随后固定到 v2.1.1：

```console
$ bash /root/panelalpha-installer.sh --engine-version v2.1.1 --no-tui
```

第一轮没有走远。安装器发现系统缺少 Git，尝试安装时遇到依赖不可用，实际日志是：

```text
git : Depends: liberror-perl but it is not installable
E: Unable to correct problems, you have held broken packages.
[ERROR] Failed to install git (required to fetch the installer).
```

这一轮退出码是 1。我没有把它写成“PanelAlpha 核心安装失败”，因为失败点还在宿主机依赖准备阶段。后续继续验证时，安装过程进入了大规模系统包升级；其中一次执行以 141 退出。再继续以后，Engine 安装才推进到后面的镜像、网络和防火墙阶段。

这里还有一个细节值得纠正我最初的预期。源码确实存在修改 `systemd-resolved` 和 `resolv.conf` 的路径，但这台 VPS 从一开始就没有 `systemd-resolved.service`，而且 `resolv.conf` 本来就是外部 DNS，所以本次运行前后 DNS 文件没有发生可观察变化。源码能力和这一次机器上真正发生的事，需要分开写。

## 安装停在 70%，但宿主机已经不是原来的状态

实验结束前，我重新采集了一次机器状态。那时 Docker Engine 已经安装完成，版本是 29.8.2；PanelAlpha 的进度文件仍显示：

```text
step: Installing PanelAlpha engine
progress: 70
```

`docker ps -a` 仍为空，也就是说不能把这次实验描述成“10 个后台容器已经运行”。能直接确认的是，机器上已经出现了 6 个 PanelAlpha 镜像，其中包括 composer、DNS proxy、Exim、metrics、Pure-FTPd 和 SFTP。最大的 composer 镜像由 Docker 报告为 795 MB disk usage。

更明显的变化发生在网络层。基线里 `iptables` / `nft` 工具不存在；安装推进后，主机已经有 UFW / Docker 规则，并出现了 `PA-BUILD-EGRESS`、`PA-PUBLISHED`、`PA-TENANT-INPUT`、`PA-TENANT-NET` 等 PanelAlpha 链。与此同时，监听端口快照仍只有 SSH 和 chrony——Engine 本身还没有准备好对外提供服务。

实验结束时，`eth1` 的累计 RX 计数是 1,508,426,817 bytes。这个数字我不会直接写成“PanelAlpha 下载了 1.5 GB”，因为基线文件没有记录接口 RX 计数，无法扣除系统升级、SSH 和其他流量。能确认的是：在一个持续数小时的干净 VPS 安装窗口里，网络、Docker 镜像和主机防火墙都已经发生了明显变化，而应用部署阶段还没有开始。

这和我平时使用 GitHub Runner + Docker Compose 的感受差别很大。Runner 更像一条受 GitHub workflow 驱动的执行通道；PanelAlpha 则在建立一整套应用托管控制面。后者需要更多底座并不奇怪，因为它还要处理项目隔离、域名、数据库、文件、备份、监控等生命周期。

所以我最终停止测试，不是为了下一个“PanelAlpha 不行”的结论，而是因为继续耗时间把它硬装完，已经不能回答我最初的选型问题。对这台 1C2G 机器来说，控制面本身的冷启动和宿主机改动已经是必须纳入成本的事实。至于项目能否成功部署、失败发布是否保持旧版本、备份能否恢复，我这次都没有跑到，不能拿官方说明替代自己的运行结果。

## `modify` 权限为什么仍然要谨慎

没有跑到 MCP 服务端，我仍然保留了之前的固定版本源码审计。PanelAlpha v2.1.1 的 [ToolPolicy](https://github.com/panelalpha/panelalpha-engine/blob/1e19bbf22a49c638f9e886fde653e02bbdc4bea5/core/app/Mcp/ToolPolicy.php) 把三个权限模式按 HTTP 方法做了一个上限：

| 权限模式 | 允许的方法 |
| --- | --- |
| `readonly` | GET |
| `modify` | GET、POST、PUT、PATCH |
| `full` | GET、POST、PUT、PATCH、DELETE |

乍看之下，`modify` 很像“能修改但不能做危险删除”。继续看生成出来的 MCP 工具就会发现，这个理解不够准确。

`project_delete` 是 DELETE，所以不会通过 `modify` 的动词上限；但 [`backup_restore`](https://github.com/panelalpha/panelalpha-engine/blob/1e19bbf22a49c638f9e886fde653e02bbdc4bea5/core/app/Mcp/Tools/Api/Backups/BackupRestoreTool.php) 和 [`project_push`](https://github.com/panelalpha/panelalpha-engine/blob/1e19bbf22a49c638f9e886fde653e02bbdc4bea5/core/app/Mcp/Tools/Api/Projects/ProjectPushTool.php) 都是 POST，而且都带有 `IsDestructive` 标记。按这层 verb ceiling，它们可以出现在 `modify` 范围内。

这不是一个“未授权漏洞”的结论。Engine 在注册工具前还会继续套用 toolset、denylist 以及 TokenAbilities 的令牌范围；备份恢复请求也要求 `confirm=true`。我没有完成真实 token 的动态拒绝测试，所以不会说这些保护可以或不可以被绕过。

它给我的工程提醒更简单：给 Coding Agent 设计基础设施权限时，“不允许 DELETE”并不等于“不会覆盖重要状态”。恢复备份、把 staging 推到 live、重建项目，都可能通过 POST 完成。真要把 Agent 接进去，我会从 `readonly` 起步，再显式收窄 toolset 和 denylist，而不是只看 `readonly / modify / full` 三个名字。

备份与遥测这次也只停留在源码 / 官方文档边界。官方 [Backups 文档](https://github.com/panelalpha/panelalpha-engine/blob/1e19bbf22a49c638f9e886fde653e02bbdc4bea5/docs/05-capabilities/backups.md) 明确说没有内置定时计划，需要外部 cron 等调度；恢复会覆盖当前项目状态。Telemetry 文档则区分了 `pae telemetry:disable` 和将 `PANELALPHA_MONITORING=` 留空：前者会停掉计划的六小时健康巡检，后者官方描述为保留本地巡检但不向监控端点发送报告。这些行为我没有动态执行，只能当作 v2.1.1 的文档事实。

## 我现在不会拿它替换 Self-hosted Runner

把这轮实验和我现有的 [ChatGPT Web + GitHub + Self-hosted Runner 工作流](/posts/chatgpt-web-github-self-hosted-runner/) 放在一起看，我反而觉得“谁替代谁”这个问题问窄了。

| | GitHub Self-hosted Runner | PanelAlpha Engine |
| --- | --- | --- |
| 主要职责 | 执行受 GitHub workflow 控制的 job | 管理应用与服务器托管生命周期 |
| 核心状态 | Git commit、workflow、release | Engine 内的项目 / 托管状态 |
| AI 接入方式 | Agent 改代码 / workflow，再由 GitHub 执行 | Agent 可经 MCP / API 直接操作控制面 |
| 宿主机介入 | 取决于 workflow 自己做什么 | 安装阶段就会建立 Docker、网络与防火墙底座 |
| 我这次验证到哪 | 现有生产链长期在用 | 只验证到安装 70% 和部分宿主机变化 |

对我的博客、小型服务和少量自部署项目来说，我现在仍会保留 GitHub + Self-hosted Runner + Docker Compose。这个选择不是因为我证明了 Runner “更安全”或“性能更好”，而是因为它和我现有的 source of truth、PR 审查、发布路径已经对齐，新增一个高权限 Hosting Control Plane 暂时没有抵消它带来的额外状态与底座成本。

反过来，如果要管理几十个应用、需要统一域名、数据库、文件、备份、项目隔离，并且确实希望 Coding Agent 通过一个受约束的接口管理这些资源，PanelAlpha 的定位就合理得多。它并不是一个更花哨的 `docker compose up`，而是在尝试把传统 hosting panel 变成 Agent 可以调用的基础设施 API。

这次实验最终停在安装阶段，我反而觉得足够了。它没有回答“PanelAlpha 完整跑起来以后好不好用”，但已经回答了我最初真正需要决定的事：如果目标只是把经过审查的代码可靠地发布到自己的几台服务器，我目前没有理由为了 AI 操作体验额外引入一整套 VPS 控制面。

如果以后再测，我会换成资源更充足的全新 VPS，第一件事也不会是部署真实项目，而是先完成 `readonly / modify / full` 的 MCP 拒绝矩阵，再测试失败发布、远端备份恢复和 telemetry 的实际行为。到那一步，才能讨论它是否适合作为长期的 AI 运维入口，而不只是讨论安装体验。
