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 addgit commitgit 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
检查项工具检查什么
Dockerfilehadolint不要 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.pyCF Email 桥接脚本press-deploy 仓库恢复
/opt/cf-bridge-venv/Python 虚拟环境pip install aiosmtpd httpx
/opt/cf-bridge.envCF API Token去 CF 后台重新生成
/etc/systemd/system/cf-smtp-bridge.servicesystemd 服务从文档重新创建
/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-datapress-sitespress_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.comf1-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 仓库加 upstream remote,记录当前基于哪个 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 加固)交叉审查全项目文档发现遗漏