运维 | VPS 架构的自我进化:从宝塔到 Traefik + FrankenPHP
VPS 架构的自我进化:从宝塔到 Traefik + FrankenPHP
有些服务器,不折腾,却安稳。
有些重构,不惊天动地,却润物无声。
几年前买下这台 VPS 时,第一件事就是装宝塔面板。那时候觉得,管理网站就该有个可视化界面,点一点鼠标就能部署环境、创建站点、申请证书,多省心。
事实证明,宝塔确实省心——直到你开始需要「不省心」的东西。
写在前面
这篇文章记录的是我这台 VPS 从宝塔面板 + Nginx + MySQL 的传统架构,逐步迁移到 Docker + Traefik + FrankenPHP 的全过程。
所有操作均由 Hermes Agent(一个 AI 编程助手)通过 SSH 自动完成,我只负责描述需求,Agent 负责执行。某种意义上,这篇文章也是 AI 辅助运维的一份实践记录。
一、曾经的架构
最初的环境很标准:
宝塔面板(BT Panel) → 管理界面
Nginx → Web 服务器
MySQL 5.7 → 数据库
PHP 7.x → PHP 运行时站点通过宝塔的「添加站点」功能创建,证书用宝塔的「SSL」面板申请,伪静态规则在宝塔里配置。
这个架构的好处是所见即所得,对于只有一个博客的轻量需求完全够用。但问题也逐渐显现:
- 宝塔面板本身占用资源(约 200MB 常驻内存)
- MySQL 对于 Typecho(SQLite 就够用)来说太重了
- 多站点管理依赖宝塔的 Nginx 配置,修改起来不够灵活
- 证书续期偶尔出问题,需要手动干预
- 每次系统更新都要进面板操作,无法脚本化
二、为什么迁移
2.1 资源优化
VPS 只有 1GB 内存,宝塔 + MySQL + Nginx + PHP-FPM 跑下来,可用内存捉襟见肘。换成 Docker 后,每个服务各司其职,不需要的组件一个都不装。
2.2 配置即代码
宝塔的配置存在面板数据库里,导出迁移很麻烦。Docker Compose + Traefik 的配置全是文本文件,可以 Git 管理、可以 AI 修改、可以一键重建。
2.3 自动化运维
既然有了 Hermes Agent 这样的 AI 助手,架构就应该设计成「AI 可运维」的——所有操作通过 SSH 命令行完成,不需要任何图形界面。Traefik 的动态配置、Docker 的容器编排,天然适合这种模式。
三、迁移过程
3.1 第一步:Traefik 就位
Traefik 作为反向代理网关,接管所有 HTTP/HTTPS 流量。
# traefik/docker-compose.yml
services:
traefik:
image: traefik:v3.1
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
networks:
- traefik-net
environment:
- CF_DNS_API_TOKEN_FILE=/cloudflare.token
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml
- ./config:/config
- ./certs:/certs核心配置亮点:
# 证书:Cloudflare DNS-01 挑战,通配符证书
certificatesResolvers:
letsencrypt:
acme:
dnsChallenge:
provider: cloudflare这意味着 *.seekdoor.me 的泛域名证书自动续期,新增子域名无需手动申请证书。
3.2 第二步:博客搬进容器
Typecho 博客迁移到 FrankenPHP 容器。FrankenPHP 是一个基于 Caddy 的现代 PHP 应用服务器,内置 PHP 8.x,性能优于传统 Nginx + PHP-FPM。
# typecho/docker-compose.yml
services:
app:
image: typecho-franken:v1.3.0
container_name: typecho-app
expose:
- "80"
volumes:
- ./app:/app
- ./data/typecho:/data
networks:
- traefik-net
labels:
- "traefik.enable=true"
- "traefik.http.routers.typecho.rule=Host(`blog.seekdoor.me`)"
- "traefik.http.routers.typecho.entrypoints=websecure"
- "traefik.http.routers.typecho.tls=true"
- "traefik.http.routers.typecho.tls.certresolver=letsencrypt"数据库从 MySQL 迁移到 SQLite——Typecho 原生支持,减少一个服务依赖,备份也变成了拷一个文件的事。
3.3 第三步:周边服务迁移
Tiny Tiny RSS(RSS 阅读器)和 Cockpit(服务器管理面板)也接入 Traefik:
# ttrss 路由配置
http:
routers:
ttrss-secure:
rule: "Host(`ttrss.seekdoor.me`)"
service: ttrss-service
tls:
certResolver: letsencrypt
services:
ttrss-service:
loadBalancer:
servers:
- url: "http://ttrss:80"Cockpit 不走 Docker,直接通过 Traefik 代理到宿主机端口:
services:
cockpit-service:
loadBalancer:
servers:
- url: "http://172.25.0.1:9090"3.4 第四步:域名与流量接入 Cloudflare
所有域名通过 Cloudflare 托管,DNS 解析指向 VPS IP。Traefik 的 Cloudflare DNS-01 挑战自动为每个域名签发 Let's Encrypt 证书。
流量路径:
用户 → Cloudflare CDN → VPS:443 (Traefik) → 容器:80 (FrankenPHP/Nginx)四、当前架构全景
┌─────────────────────────────────────────┐
│ Cloudflare │
│ (DNS + CDN + DDoS 防护) │
└────────────────┬────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Traefik v3.1 │
│ 反向代理 / SSL 终结 / 自动证书 │
│ 端口: 80→443, 443→各自容器 │
│ 证书: Let's Encrypt (DNS-01) │
└──────┬──────────┬──────────┬────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Typecho │ │ ttrss │ │ Cockpit │
│ Franken │ │ PHP │ │ (宿主机) │
│ SQLite │ │PostgreSQL│ │ 9090 │
│ blog │ │ RSS │ │ 管理面板 │
└──────────┘ └──────────┘ └──────────┘
│
▼
┌──────────┐
│ Initial-M│
│ 主题 v3.2│
│ +自定义 │
└──────────┘五、AI 运维的实践
这次架构迁移的整个过程——从分析现状、规划方案、编写配置、部署验证——全部由 Hermes Agent 通过 SSH 自动完成。
几个有意思的细节:
5.1 路径陷阱
第一次部署主题时,Agent 把文件放到了 Nginx 的网站根目录,但博客实际跑在 Docker 容器里,数据卷挂载在另一个路径。首页能正常访问(因为 Traefik 代理到了容器),但后台「外观」页面找不到新主题。
排查过程:
- 查看 Nginx 配置发现
root /www/server/stop——非典型路径,怀疑是反向代理 - 检查 Docker 运行状态,确认博客在容器中
- 查看 docker-compose.yml 找到数据卷映射关系
- 重新部署到正确的数据卷路径 → 问题解决
这就是 AI 运维的优势:Agent 不会"觉得丢脸",它会一步步排查,直到找到根因。
5.2 主题定制的迁移
博客原本使用 Initial 主题并做了 7 项个性化定制(Pangu.js 自动间距、波浪动画页脚、归档下拉菜单、Bangumi 挂件等)。升级到 Initial-M 时,Agent 逐项分析了每个定制在新主题中的对应关系,保留了 Initial-M 的新功能,叠加了用户的个性化改动。
5.3 故障恢复
所有配置都有备份:
- 旧主题备份在
themes/initial-backup-YYYYMMDD/ - 旧 Nginx 配置保留在宝塔备份中
- 数据库每日自动备份
- 即使重建整个 Docker 环境,
docker-compose up -d就能恢复所有服务
六、迁移收益
| 指标 | 迁移前 | 迁移后 |
|---|---|---|
| 常驻内存 | ~400MB(宝塔+Nginx+MySQL+PHP) | ~150MB(Traefik+FrankenPHP+ttrss) |
| 证书管理 | 手动续期/宝塔自动 | 全自动(Traefik + DNS-01) |
| 新增站点 | 宝塔界面操作 | 添加一行 docker-compose labels |
| 备份策略 | 宝塔整站备份 | SQLite 文件 + 配置文件 Git 管理 |
| 运维方式 | 图形界面 | SSH + AI Agent |
七、写在最后
这次迁移最大的收获不是技术指标的提升,而是一种运维模式的改变。
当架构变成「配置即代码」,当 AI 助手可以 SSH 进服务器执行任务,运维就不再是「登录面板 → 找按钮 → 点鼠标」的流程,而是「描述需求 → AI 执行 → 验证结果」的对话。
这大概就是未来运维的样子——不需要记住每个配置项的位置,只需要知道自己想要什么。
致谢
- Traefik — 优秀的反向代理和证书管理器
- FrankenPHP — 现代化的 PHP 应用服务器
- Initial-M — Typecho 主题的现代化 fork
- Hermes Agent — 帮我完成所有操作的 AI 助手
最后,一台 VPS 的生命力,不在于装了多新的软件,而在于你是否愿意持续维护它。而有了 AI 助手的帮忙,维护这件事,变得前所未有的轻松。
最后更新于 2026-07-04 「部分内容存在时效性,如有失效请留言反馈」
除注明外为 袅残烟的冥想盆 原创文章,转载请注明出处。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。