从 Release 到生产,原子秒级切换。
在终端交互选择 GitHub Releases 资产包,或一行命令直接部署最新版本。 支持断点续传与 SHA-256 完整性校验;离线环境下支持本地 bundle 文件。
查看部署指南 ↗# 交互选择 Release 资产
upy release
# 部署最新正式版
upy release latest
# 部署本地 bundle 文件
upy bundle ./bundle.zip
curl -fsSL https://raw.githubusercontent.com/AaronConlon/upy/main/install.sh | bash
默认安装至 /usr/local/bin,支持通过 INSTALL_DIR 指定安装路径。
核心功能
覆盖应用发布、磁盘空间维护、关键数据备份与多人移动端告警,构建单机运维闭环。
在终端交互选择 GitHub Releases 资产包,或一行命令直接部署最新版本。 支持断点续传与 SHA-256 完整性校验;离线环境下支持本地 bundle 文件。
查看部署指南 ↗# 交互选择 Release 资产
upy release
# 部署最新正式版
upy release latest
# 部署本地 bundle 文件
upy bundle ./bundle.zip
解压至独立版本目录,通过 current 软链原子切换。
自动将目录与文件规整为 0755/0644 权限,避免 Nginx / Caddy 出现 403 权限错误。
纳管 Go/Rust 等轻量常驻进程。 严格预检运行账号与权限,启动参数原样保真,端口身份严密防伪,失败秒级自动回滚。
新版本镜像与配置就绪后再停止旧容器并释放端口,避免端口冲突。 内置健康检查机制,启动异常时自动回滚至上一可用版本。
真实还原三大模式的完整流水线 —— 包含 CI 自动化打包脚本、服务器目录结构、真实终端执行日志与底层可靠性保障。
# 1. 构建前端产物
- name: Build frontend
run: npm ci && npm run build
# 2. 写入清单并打成 bundle.zip
- name: Package bundle
run: |
cat << 'EOF' > dist/upy.yaml
name: my-spa-app
version: ${{ github.ref_name }}
type: static
static:
directory: dist
EOF
cd dist && zip -r ../bundle.zip . upy.yaml
# 服务器端项目配置
name: my-spa-app
release:
provider: github
repository: owner/my-spa-app
asset: bundle.zip
# 压缩包与版本保留策略 (默认最多保留 3 个 bundle 压缩包,范围 0~100)
bundles:
keep: 3
releases:
keep: 1
# Nginx 配置指向软链: root /var/www/my-spa-app/current;
$ upy release latest 📦 项目: my-spa-app 📁 目录: /var/www/my-spa-app 🧩 类型: 静态站点 (static) 🏷 当前版本: 未部署 -> 正在获取 owner/my-spa-app 的 v1.0.0 版本... ✓ 已选择版本 v1.0.0 -> ⬇️ 正在下载资产 bundle.zip(1.4MB)... ✓ 已保存到 bundles/v1.0.0-bundle.zip -> 正在解压 bundle... ✓ bundle 解压完成 -> 正在校验静态 bundle 入口... ✓ 静态 bundle 校验通过 (dist/index.html 存在) -> 正在自适应修复目录与文件权限... ✓ 目录权限修正为 0755,文件权限修正为 0644 -> 正在原子切换 current 软链... ✓ current -> releases/1.0.0/dist ✓ 部署完成: my-spa-app 1.0.0 ⏱ 部署耗时: 0.8s
0755,静态文件权限为 0644。current -> releases/1.0.0/dist,发布过程零中断。# 1. 交叉编译 Linux 纯静态二进制
- name: Build Go binary
env:
CGO_ENABLED: '0'
GOOS: linux
GOARCH: amd64
run: go build -trimpath -ldflags "-s -w" -o bin/web ./cmd/web
# 2. 打包清单与可执行文件
- name: Package bundle
run: |
cat << 'EOF' > upy.yaml
name: my-api
version: ${{ github.ref_name }}
type: system
target: { os: linux, arch: amd64 }
system:
command: ["./bin/web", "--port", "8080"]
healthcheck:
url: http://127.0.0.1:8080/health
timeout: 15s
EOF
zip -r bundle-linux-amd64.zip upy.yaml bin/web
name: my-api
release:
provider: github
repository: owner/my-api
asset: bundle-linux-amd64.zip
service:
user: my-api # 独立无权限系统账号
group: my-api
unit: upy-my-api.service
# 业务持久化数据隔离在 /opt/my-api/shared/data/
# 环境变量与配置位于 /opt/my-api/shared/service.env
$ upy release latest 📦 项目: my-api 📁 目录: /opt/my-api 🧩 类型: 系统原生服务 (system) 🏷 当前版本: 1.0.0 -> 正在获取 owner/my-api 的 v1.1.0 版本... ✓ 已选择版本 v1.1.0 -> ⬇️ 正在下载资产 bundle-linux-amd64.zip(4.2MB)... ✓ 已保存到 bundles/v1.1.0-bundle-linux-amd64.zip -> 正在解压 bundle... ✓ bundle 解压完成 -> 正在校验系统服务配置与可执行文件... ✓ 系统服务配置校验通过 (user: my-api, arch: linux/amd64) -> 正在更新 systemd unit 并加载配置... ✓ 系统服务已启动 (upy-my-api.service) -> 正在健康检查 http://127.0.0.1:8080/health (超时 15s)... ✓ 健康检查通过 (PID: 28412, Port 8080 归属校验无误) -> 正在原子切换 current 软链... ✓ current -> releases/1.1.0 ✓ 部署完成: my-api 1.1.0 ⏱ 部署耗时: 3.2s
service.user 与用户组存在性,不存在时立即阻断,杜绝以 root 提权运行。/proc/<pid>/fd 与 socket 校验本地监听者归属,防止被假冒进程欺骗。clean 动态解析 live systemd unit 引用,严防清理误删正在运行的活跃二进制。# 打包 Compose 文件与应用制品
- name: Package Compose bundle
run: |
cat << 'EOF' > upy.yaml
name: my-compose-stack
version: ${{ github.ref_name }}
type: docker
docker:
mode: compose
composeFile: docker-compose.yml
healthcheck:
url: http://127.0.0.1:8080/health
timeout: 30s
EOF
zip -r bundle.zip upy.yaml docker-compose.yml Dockerfile src/
name: my-compose-stack
release:
provider: github
repository: owner/my-compose-stack
asset: bundle.zip
# 生产环境私密配置放于 shared/.env
# 数据库与持久化数据卷挂载至 shared/data/
$ upy release latest 📦 项目: my-compose-stack 📁 目录: /opt/my-compose-stack 🧩 类型: Docker Compose (docker) 🏷 当前版本: 1.0.0 -> 正在获取 owner/my-compose-stack 的 v1.1.0 版本... ✓ 已选择版本 v1.1.0 -> ⬇️ 正在下载资产 bundle.zip(1.8MB)... ✓ 已保存到 bundles/v1.1.0-bundle.zip -> 正在解压 bundle... ✓ bundle 解压完成 -> 正在执行 docker compose build (docker-compose.yml)... ✓ 镜像构建完成 -> 正在停止上一版本并释放宿主端口... ✓ 上一版本旧栈已平滑停止 -> 正在启动新版本 (docker compose up -d)... ✓ 容器集群已启动 -> 正在健康检查 http://127.0.0.1:8080/health (超时 30s)... ✓ 健康检查通过 (HTTP 200 OK) -> 正在原子切换 current 软链... ✓ current -> releases/1.1.0 ✓ 部署完成: my-compose-stack 1.1.0 ⏱ 部署耗时: 12.3s
shared/.env 生产密钥覆盖。
部署时依据 bundles.keep 自动保留最新压缩包(默认最多 3 个,支持 0~100 自由定制);
支持通过 upy clean 交互式清理或一键常规瘦身。
内置双重活跃版本保护,禁止删除 current 正在运行的版本;通过跨进程互斥锁避免并发冲突。
# 交互式清理菜单(支持空间分析)
upy clean
# 仅清理历史 bundle 压缩包缓存
upy clean --bundles
# 一键常规瘦身(清理缓存与旧版本)
upy clean --all -y
遵循约定优先原则,自动识别项目中的 backup.sh 脚本并注入环境变量。
执行期间自动施加跨进程排他互斥锁,严防并发写入产生脏数据;支持智能保留轮转策略与 Bark 移动端实时告警。
#!/usr/bin/env bash
# 环境变量由 upy 自动注入: UPY_BACKUP_DIR, UPY_PROJECT_NAME, UPY_TIMESTAMP
mkdir -p "${UPY_BACKUP_DIR}"
BACKUP_FILE="${UPY_BACKUP_DIR}/dump-${UPY_PROJECT_NAME}-${UPY_TIMESTAMP}.sql.gz"
# 在容器内安全执行 mysqldump 导出并压缩
docker compose exec -T db mysqldump -u root -p"${DB_PASSWORD}" "${DB_NAME}" | gzip > "${BACKUP_FILE}"
# 备份功能配置(可选)
backup:
script: backup.sh # 自定义脚本路径(缺省自动探测)
dir: backups # 备份产物归档目录(默认 backups/)
retention: 7 # 自动轮转保留的最大备份份数(默认 7)
timeout: 15m # 备份最大超时时间(默认 15m,支持 30s, 5m, 1h)
upy backup
$ upy backup -> 正在对项目 my-api-service 执行约定备份... ✓ 发现约定脚本: backup.sh (chmod 0755) ✓ 已获取项目排他锁 (.deploy.lock) -> 正在驱动执行备份脚本 (UPY_BACKUP_DIR=backups)... ------------------------------------------------------------ 正在导出数据库到: /opt/my-api-service/backups/dump-my-api-service-20261019-120000.sql.gz... 数据库导出成功! ------------------------------------------------------------ ✓ 项目 my-api-service 备份执行完成! 📦 归档产物: dump-my-api-service-20261019-120000.sql.gz (42.5 MB) 🛡️ 自动轮转: 保留最近 7 份(已清理 1 份历史旧备份) ⏱ 总耗时: 2.4s 🔔 已向 Bark 渠道推送备份完成通知
upy backup
交互式选择已登记项目执行备份
upy backup my-app --list
查看项目历史备份列表与占用体积
upy backup my-app --prune 5
手动触发轮转,保留最近 5 份备份
upy backup --all -y
一键批量备份所有已登记项目
action: 备份中),严格互斥正在进行的部署或磁盘清理,杜绝产生半更新脏数据。
全机纳管项目动态盘点,以占用空间最大的项目为 100% 基准绘制等宽横向柱状条形图;
顶栏置顶聚焦最近一次部署动态(项目、版本、部署类型、相对时间与健康状态)。严格杜绝软链双重计数,支持 --detail 深度展开与 --json 格式化导出。
# 算法:以占用最高的项目 maxBytes 为 100% 基准换算比例
1 my-compose-app docker 1.45 GB [████████████████████] 100.0%
2 my-api-service system 482 MB [███████░░░░░░░░░░░░░] 32.5%
3 portal-frontend static 86 MB [█░░░░░░░░░░░░░░░░░░░] 5.8%
# 甄选 state.json 中时间戳最新的项目置顶高亮
📦 项目: my-api-service (v1.2.0)
🧩 类型: Systemd 系统服务 (system) · upy-my-api-service.service
⏱ 时间: 22分钟前 (2026-10-19 19:40:02)
🟢 状态: 正常运行 (active)
$ upy analysis upy analysis — 客户端项目与磁盘分析 ━ 最近一次部署动态 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📦 项目: my-api-service (v1.2.0) 🧩 类型: Systemd 系统服务 (system) · upy-my-api-service.service ⏱ 时间: 22分钟前 (2026-10-19 19:40:02) 🟢 状态: 正常运行 (active) ━ 项目分析 (状态 · 空间基准对比 · 类型 · 版本号) ━━━━━━━━━━━ # 项目名称 状态 类型 当前版本 磁盘占用 基准对比 (Max) 1 my-compose-app 🟢 active docker v2.1.0 1.45 GB [████████████████████] 100.0% 2 my-api-service 🟢 active system v1.2.0 482.3 MB [███████░░░░░░░░░░░░░] 32.5% 3 portal-frontend 🟢 active static v0.9.4 86.1 MB [█░░░░░░░░░░░░░░░░░░░] 5.8% 4 demo-spa ⚪ undeployed static - 14.2 MB [▏░░░░░░░░░░░░░░░░░░░] 0.9% ━ 存储汇总统计 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 📊 纳管项目: 4 个 💾 累计占用: 2.03 GB (平均每个项目 519.6 MB) 👑 空间首位: my-compose-app (1.45 GB, 占全机 upy 空间的 71.4%) 💡 提示: 可使用 upy analysis --detail 查看各子目录详细空间分布
upy analysis
全机项目磁盘占用基准图与最近部署
upy analysis --detail
展开 releases/bundles/backups 子目录细分
upy analysis <name>
针对指定项目深入查看占用与目录树
upy analysis --json
以 JSON 结构化数据输出供监控解析
current 符号链接本身字节,不递归穿透目标版本目录,杜绝活跃版本重复计算。
部署与备份结果即时推送至 iOS 设备与团队业务系统。底层基于开源 Bark 移动端推送与项目级专属 Webhook。
无需第三方复杂配置,支持在 deploy.yaml 中项目级独立配置、全局配置兜底、团队多人广播、HMAC-SHA256 签名防伪与智能自动去重。
# 统一写法:通用属性(对所有成员生效) + 用户级列表(按 - name 区分多用户)
notify:
bark:
# 1. 通用属性 (全局/项目默认继承)
serverUrl: https://api.day.app # 通用服务端节点 (可填自建私有域名)
group: "payment-api" # 通用推送分组
sound: "chime" # 通用提示音 (如 bell, chime, glass 等)
level: "active" # 通用时效级别 (active / timeSensitive)
# 2. 用户级属性 (按 - name 区分多用户,字段优先级高于通用字段)
users:
- name: "前端负责人"
token: "DEVICE_KEY_ALICE"
sound: "glass" # 用户级覆盖通用 sound
- name: "值班运维"
token: "DEVICE_KEY_BOB"
serverUrl: https://bark.ops.internal # 覆盖通用 serverUrl
level: "timeSensitive"
- name: "测试工程师"
token: "DEVICE_KEY_CAROL" # 未指定独立属性,完全继承通用配置
# 单人极简直配:直接在 bark 下声明 token 即可,完全继承通用设置
notify:
bark:
serverUrl: https://api.day.app
group: "my-service"
sound: "bell"
token: "DEVICE_KEY_SINGLE_USER"
# 项目级独立 Webhook(不污染全局,支持单 URL、多端点与 HMAC 签名)
notify:
webhook:
- url: "https://ops.example.com/api/deploy-webhook"
secret: "SEC_KEY_FOR_HMAC_SHA256" # 附带 X-Upy-Signature 防伪签名
headers:
X-Environment: "production"
- url: "https://qyapi.weixin.qq.com/.../send" # 企微/飞书/钉钉群机器人
# Title 与 Body 无需手动拼写,upy 自动从运行时状态组装:
Title: upy 部署成功 · my-api-service
Body:
项目: my-api-service
版本: v1.2.0
类型: Systemd 系统服务
目录: /opt/my-api-service
耗时: 3.2s
# 若部署或备份异常,Body 自动附带「原因: <详细报错>」
upy release latest
$ upy release latest -> 正在发布项目 my-api-service v1.2.0... ✓ 系统服务配置校验通过 ✓ 已更新 systemd unit 并指向 releases/1.2.0 ✓ 系统服务已启动 (upy-my-api-service.service) ✓ 健康检查通过 (HTTP 200 OK) ✓ current -> releases/1.2.0 ⏱ 总耗时: 3.2s 🔔 已向 3 个 Bark 接收人与 1 个项目 Webhook 推送通知: ✓ Alice (https://api.day.app) [HTTP 200] ✓ Bob (https://api.day.app) [HTTP 200] ✓ 运维负责人 (https://bark.mycorp.internal) [HTTP 200] ✓ Webhook: https://ops.example.com/api/deploy-webhook [HTTP 200]
deploy.yaml 中生效,独立配置不污染全局;支持 HMAC-SHA256 防伪签名 (X-Upy-Signature) 与投递跟踪标识。- name 分多个用户,用户专属配置(如独立 sound 或私有 serverUrl)优先级高于外层通用字段,未指定字段自动回退继承通用配置。deploy.yaml)与机器全局兜底(~/.upy/config.yaml)协同运作,智能合并通知渠道。3.2s),超过 60s 换算为分钟(1m15s),超过 60m 自动以小时开头(1h2m),告别机械全秒输出。notify: { enabled: false } 可随时独立静音该项目。deploy.yaml 中通过 bundles.keep 控制保留 0~100 个历史压缩包(默认最多 3 个);upy update 升级时全自动同步 zsh、bash 与 fish 补全规则,新命令即刻生效。开源(MIT 协议)。
单二进制、零外部依赖、极低内存占用。