Press 部署方案维护计划
TL;DR
当前自建 Press 方案的 6 个已知问题,逐一给出标准解决方案:8 文件入 Git 仓库、GitHub Actions 自动检测、Agent/fc-ci 上游跟踪流程、单点 Press 备份异地同步、Python 版本在镜像内固化。
现状:🚧 方案已设计,待逐项执行。
🎯 背景
当前 Press 部署方案(自建 Dockerfile + docker-compose)已验证可用,但存在 6 个可改进的问题。本笔记逐一给出解决方案,目标是让方案达到生产可维护水平。
📦 问题 1:8 个部署文件版本管理
当前状态
文件在 VPS 的 ~/press/ 下,和 GitHub 没有关联。改了 VPS 的,本地 repo 没有同步。
解决方案
建独立 repo miao-Q777/press-deploy:
press-deploy/
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── .gitignore
├── resources/
│ ├── start.sh
│ ├── main-entrypoint.sh
│ ├── nginx-entrypoint.sh
│ ├── nginx-template.conf
│ └── security_headers.conf
└── README.md
初始化:
cd ~/press
git init
git add Dockerfile docker-compose.yml .env.example .gitignore resources/ README.md
git commit -m "初始版本"
git remote add origin https://github.com/miao-Q777/press-deploy.git
git push -u origin main
之后每次改文件: 改完 → git add → git commit → git push
在任何 VPS 上部署:
git clone https://github.com/miao-Q777/press-deploy.git ~/press
cp .env.example .env
docker compose up -d
🔍 问题 2:自动检测
当前状态
8 个文件没被自动检查过,可能有语法错误或安全隐患。
解决方案
不用下载软件、不用打开网站。GitHub 自带 GitHub Actions——在仓库里放一个配置文件,每次 git push 自动触发检查。
.github/workflows/check.yml:
name: 自动检查
on: [push, pull_request]
jobs:
dockerfile-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hadolint/hadolint-action@v3
with:
dockerfile: Dockerfile
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ludeeus/action-shellcheck@v2
with:
scandir: './resources'
nginx-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker run --rm -v $PWD/resources/nginx-template.conf:/tmp/nginx.conf:ro nginx:alpine nginx -t -c /tmp/nginx.conf| 检查项 | 工具 | 检查什么 |
|---|---|---|
| Dockerfile | hadolint | 不要 root 运行、不要泄露 secret、最佳实践 |
| Shell 脚本 | shellcheck | 语法错误、未定义变量、引号缺失 |
| nginx 配置 | nginx -t | 配置文件语法正确性 |
效果:git push 后 GitHub 自动跑。绿色勾 = 通过,红叉 = 有问题,点进去看哪行。
可选追加:trivy 镜像漏洞扫描。非必须,生产环境建议加。
🔄 问题 3:Agent 和 fc-ci 上游跟踪
Agent 维护
我怎么知道上游更新了?
去 https://github.com/frappe/agent → 右上角 “Watch” → “Custom” → 勾 “Releases”。有新版本 GitHub 发邮件通知。一个月检查一次也行——这是成熟项目,不天天变。
上游更新了我要做什么?
cd ~/agent-fork
git remote add upstream https://github.com/frappe/agent.git # 一次性设置
git fetch upstream # 拉取最新代码
git merge upstream/develop # 合并
git push origin develop # 推到自己 fork
合并结果和处理方式:
| 情况 | 概率 | 你要做什么 |
|---|---|---|
| 自动合并成功 | 80% | 什么都不做 |
| 有冲突,1-2 个文件 | 15% | Git 标出冲突位置,打开文件手动选保留哪边 |
| 上游大改,全面冲突 | 5% | 先不合并,等看懂变化再决定 |
为什么冲突概率低? 你的 6 个 fix 都是单文件小改动(几行代码),不是大段重写。只要上游没改同一个函数,自动合并就能过。
合并后一定要做什么? 在 Press 上走一遍验证:创建 demo 站点 → New Site → Add Site to Upstream → Active。确认自动化流程没被破坏。
fc-ci 维护
基本不用管。 balamurali27/frappe fc-ci 分支是 Press 团队内部测试用的,不是公开项目。它可能一年也不动几次。你的 Dockerfile 只用它来 pip install frappe——这个接口极其稳定,不会变。
什么时候才要管:你升级 Press 大版本时(比如从 v15 到 v16),去看看 fc-ci 分支有没有对应更新。
维护链全景
你的角色:维护者
│
┌───────────┼───────────┐
│ │ │
miao-Q777/ miao-Q777/ miao-Q777/
frappe agent press-deploy
(fc-ci) (develop) (main)
│ │ │
upstream: upstream: 无 upstream
balamurali/ frappe/ (自己维护)
27/frappe agent
| 仓库 | 检查频率 | 触发条件 | 验证方式 |
|---|---|---|---|
| press-deploy | 按需 | 改文件时 | hadolint + shellcheck + nginx -t |
| agent | 每月 | 上游 Release | 建 demo 站点全流程 |
| frappe (fc-ci) | 按需 | Press 大版本升级 | docker compose build 能否成功 |
💾 问题 4:单点 Press 的备份
当前状态
已有 cron 每日备份,在 Press VPS 本地:
0 3 * * * /usr/local/bin/backup-press-volumes.sh
30 3 * * * /usr/local/bin/backup-m1-mariadb.sh
每天凌晨 3 点自动备份,保留 7 天。
解决方案:加异地同步
当前备份在 Press VPS 自己磁盘上——如果 VPS 爆炸,备份也丢了。只需在备份脚本末尾加一行:
rsync -a /backups/ root@45.55.93.224:/backups-press/
或者同步到 R2:
rclone copy /backups/ r2:getgrowth-backups/
恢复流程(30 分钟)
1. 新建一台 VPS,安装 Docker
2. git clone https://github.com/miao-Q777/press-deploy.git ~/press
3. rsync 从异地拉回备份到 /backups/
4. 恢复卷:docker run + tar xzf
5. cd ~/press && docker compose up -d
远期方案
CLAUDE.md 里规划的 Multica Workspace deploy-press 就是把这个流程全自动化——按一个键,重新部署一套 Press。
🐍 问题 5:Python 版本管理
现状
- Press 控制面:Python 3.10(Dockerfile 写死 FROM python:3.10-slim)✅ 已解决
- bench v15:Python 3.10,镜像自带
- bench v16:Python 3.14,镜像自带
- Agent Fix 2:自动扫描 pyproject.toml,匹配正确 Python 版本 ✅ 已解决
原理
Python 版本差异来自 Frappe 自己的升级,不是配置错误。解决方式是把 Python 版本嵌入 Docker 镜像内部,不和宿主机绑定:
Press 控制面镜像: FROM python:3.10-slim ← 镜像自带 3.10
bench v15 镜像: FROM python:3.10-slim ← 镜像自带 3.10
bench v16 镜像: FROM python:3.14-slim ← 镜像自带 3.14
每个容器用自己镜像里的 Python,互相不干扰。Press 的 Build 流程(Deploy Candidate → Build → Docker 镜像)自动根据 app 的 pyproject.toml 选择正确的基础镜像。Agent Fix 2 让这个过程不再报错。
新建 f VPS 注意事项
宿主机预装可能用到的 Python 版本(3.10 + 3.14),Ansible playbook 自动处理。这不是为了跑 bench(bench 在容器里),而是 Agent 在宿主机上需要 Python 完成安装和配置任务。
🔧 问题 6:运维缺口补充
以下 6 个缺口来自对全项目文档的交叉审查,不在之前 5 个问题的覆盖范围内。
缺口 6.1:n1/f1 宿主机关键文件备份(严重程度:高)
当前状态:m1 数据库 + Press 卷有 cron 备份(在 104.236.24.124),但 45.55.93.224 宿主机上什么都没有。
如果 45.55.93.224 磁盘故障,以下全部丢失且无法恢复:
| 文件 | 用途 | 需重新生成 |
|---|---|---|
/opt/cf-smtp-bridge.py | CF Email 桥接脚本 | 从 press-deploy 仓库恢复 |
/opt/cf-bridge-venv/ | Python 虚拟环境 | pip install aiosmtpd httpx |
/opt/cf-bridge.env | CF API Token | 去 CF 后台重新生成 |
/etc/systemd/system/cf-smtp-bridge.service | systemd 服务 | 从文档重新创建 |
/etc/ufw/ | 防火墙规则 | 重新配置 |
/home/frappe/frappe-bench/sites/*/site_config.json | 站点配置 | 手动重建 |
影响:n1/f1 重建需要重新部署桥接 + 恢复站点配置,至少 1-2 小时。
方案:
# 在 45.55.93.224 上加 cron,每天打包关键文件
tar czf /tmp/n1-backup.tar.gz /opt/cf-* /etc/systemd/system/cf-* /etc/ufw
rsync -a /tmp/n1-backup.tar.gz root@104.236.24.124:/backups/n1-f1/
缺口 6.2:DO Container Registry 旧镜像清理(严重程度:中)
当前状态:DO Registry getgrowth-press (NYC3),Starter 500MB 限制。每次 Build 推送新镜像(约 2.6GB/个),旧的不自动删。超限后新 Build 会失败(镜像推送被拒)。
方案:
1. 查当前使用量:
curl -H "Authorization: Bearer $DO_TOKEN" \
"https://api.digitalocean.com/v2/registry/getgrowth-press/repositories"
2. 在 Press 的 cron 里加清理脚本,只保留最近 N 个 tag
3. 或 DO Registry Settings 里启用 tag 自动过期策略(如果 DO 支持)
缺口 6.3:CF Origin CA 证书到期跟踪(严重程度:中)
当前状态:CF Origin CA RSA 证书用于 *.getgrowth.app TLS。有效期 15 年但无提醒机制。证书过期 → nginx TLS 握手失败 → 所有站点不可访问。
方案:
# 查到期日
openssl x509 -in /path/to/cert.pem -noout -enddate
# 续签步骤:
CF Dashboard → SSL/TLS → Origin Server → 创建证书 → 替换 nginx 文件 → nginx -s reload
设日历提醒,到期前 30 天触发。
缺口 6.4:已知脆弱点清单
4a. docker compose down -v 会清空所有持久化数据
press-db-data、press-sites、press_ssh 三个卷是 Press 的全部家当。一条命令能全毁。
防护:在 docker-compose.yml 同级放 README 警告,或给卷打 external: true 标签。
4b. bench 容器 supervisor.conf 被 Press 覆盖
bench 重建/迁移时 Press 自动生成的 supervisor.conf 会覆盖手动追加的 [program:xxx] 段。
当前状态:桥接已移到宿主机 systemd,此风险已缓解。
4c. Agent Job Undelivered 堆积
某些 Agent Job Type 的 disabled_auto_retry=1,投递失败后永不重试。症状:Press UI 功能卡 loading(如 DB Analyzer、SQL Playground)。
监控命令:
bench execute "frappe.get_all('[[Job|Agent Job]]', \
filters={'status': 'Undelivered'}, fields=['job_type','site','creation'])"
4d. f1 Agent press_url 每次重建后需手动修正
Ansible playbook 未传 --press-url,默认写 https://frappecloud.com。f1-init.sh 仍未创建。
缺口 6.5:定期健康检查命令清单
建议每月或每次重大变更后跑一次:
# Agent 连通性
bench execute "frappe.get_doc('Server','f1.getgrowth.app').ping_agent()"
bench execute "frappe.get_doc('Proxy Server','n1.getgrowth.app').ping_agent()"
# 桥接状态
systemctl is-active cf-smtp-bridge
journalctl -u cf-smtp-bridge --since '1 hour ago' | grep -c '200 OK'
# [[Job|Agent Job]] 堆积
bench execute "frappe.db.count('[[Job|Agent Job]]', {'status': 'Undelivered'})"
# 备份完整性
ls -lh /backups/m1-mariadb/ | tail -3
ls -lh /backups/press-volumes/ | tail -3
缺口 6.6:m1 安全加固
6a. m1 (159.65.38.50) 上 nginx 监听 0.0.0.0:443
公网可访问 Frappe 页面。m1 只应暴露 MariaDB (内网) + SSH。
修复:DO 控制台防火墙关掉 m1 的 443 入站规则。
6b. force=True 删站残留(issues.md #19)
demo1-5 的 MariaDB 数据库和 bench 目录残留在 m1/f1 上。_e56fcf0604db8cdd 数据库可能已不需要。
修复:确认后 DROP DATABASE _e56fcf0604db8cdd。
📋 执行清单
基础维护(问题 1-5)
- 创建
miao-Q777/press-deploy仓库,把 8 个文件推上去 - 加
.gitignore(排除.env) - 加
.github/workflows/check.yml(hadolint + shellcheck) - Agent 仓库加
upstreamremote,记录当前基于哪个 commit - 备份脚本加异地同步(rsync 到 45.55.93.224)
- 在另一个 VPS 上完整跑一次恢复流程,验证备份可用
- fc-ci 仓库确认 fork 完整性(本地有完整副本)
运维缺口(问题 6)
- 缺口 6.1:n1/f1 宿主机备份 cron 脚本
- 缺口 6.2:查 Registry 当前使用量,设清理策略
- 缺口 6.3:CF Origin CA 证书到期日 + 日历提醒
- 缺口 6.4c:Agent Job Undelivered 监控
- 缺口 6.4d:创建 f1-init.sh
- 缺口 6.5:每月健康检查 checklist
- 缺口 6.6a:DO 控制台关 m1 的 443 端口
- 缺口 6.6b:确认并 DROP 残留数据库
📝 更新日志
| 日期 | 改动 | 原因 |
|---|---|---|
| 2026-07-08 | 首次创建,覆盖 5 个问题的解决方案 | 方案评审后整理 |
| 2026-07-08 | 新增问题 6:运维缺口 6 项(n1/f1 备份、Registry 清理、证书跟踪、脆弱点、健康检查、m1 加固) | 交叉审查全项目文档发现遗漏 |