内容
# AppCrane
**您 AI 构建和部署的应用的自主托管中心。**
[](https://github.com/gitayg/appCrane/stargazers)
[](LICENSE)

使用 Claude Code 或 Cursor 编写应用,然后让您的 AI 代理通过 MCP 将其部署到 **您拥有** 的服务器。AppCrane 是一个自主托管的、以代理为优先的部署平台,具有企业级的安全防护措施,这些是云 PaaS 服务所不具备的:每个应用的 Docker 隔离、SAML/OIDC/SCIM 单点登录、每个用户的审计日志,以及一个中间件防护墙,防止平台操作员读取您的应用密钥(您的模型 API 密钥仍然是您的)。一个自主托管的 Heroku、Vercel 和 AppDeploy 等托管代理部署服务的替代方案。
**以 MCP 为优先。** AI 代理通过 `claude mcp add ... /api/mcp` 连接一次,并通过 35 个 `appcrane_*` 工具操作平台。无需 curl,无需单独的脚本 — `appcrane_get_guide(topic="onboarding"|"operations")` 按需返回最新的操作指南。
## 为什么选择 AppCrane
| 功能 | AppCrane | Coolify | Dokploy |
|---|---|---|---|
| 以代理为优先 / MCP 原生 | ✅ | ❌ | ~ 插件 |
| 自主托管,您的基础设施 | ✅ | ✅ | ✅ |
| 企业级单点登录(SAML/OIDC/SCIM) | ✅ | ~ | ❌ |
| 密钥防护墙(操作员无法读取) | ✅ | ❌ | ❌ |
| 托管代码仓库(无需 GitHub 账户) | ✅ | ❌ | ❌ |
| 每个应用的 Docker 隔离 | ✅ | ✅ | ✅ |
| 双重沙盒/生产环境 | ✅ | ~ | ✅ |
| 零停机部署 | ✅ | ~ | ✅ |
| 开源 | ✅ AGPL-3.0 | ✅ Apache-2.0 | ✅ Apache-2.0 |
**完整矩阵** vs AWS Copilot / App Runner / Lightsail / CodeDeploy / Vercel / AppDeploy → **[glick.run/comparison.html](https://glick.run/comparison.html)**
## 功能
- **Docker 容器隔离** — 每个应用都在自己的容器中运行;没有共享依赖,没有失控进程
- **企业级单点登录** — SAML 2.0、OIDC 和 SCIM 配置;连接到 Okta、Azure AD、Google Workspace
- **身份转发到应用作为头部** — `X-AppCrane-User-Role`、`X-AppCrane-App-Role` 等由代理在 `forward_auth` 验证用户后注入;部署的应用直接从请求中读取身份,无需回调(oauth2-proxy / IAP 模式)
- **`/api/me` 端点** — 规范的“调用者是谁”用于代理应用;接受 `cc_token` cookie、Bearer 或 `X-API-Key`;返回全局角色 + 应用角色(`?app=<slug>` 或 `Referer` 推断)
- **无头应用类型** — 设置 `auth_mode: 'headless'` 以完全绕过应用的 `forward_auth`;适用于遥测数据收集、公共 webhook、状态页面和单一用途的无身份验证服务
- **AppStudio AI 流水线** — AI 按计划提出代码改进建议;您在任何更改生效前审查和批准
- **实时存在** — 查看每个应用上谁是活跃的、哪个环境以及他们上次部署的时间
- **双环境** 每个应用:生产 + 沙盒,始终在线,独立端口
- **自动 HTTPS** 通过 Caddy 反向代理与 Let's Encrypt
- **GitHub webhook 自动部署** 在推送时(HMAC 验证)
- **零停机部署** (启动新实例,健康检查,交换,排空旧实例)
- **秒级回滚** (基于符号链接,保持最近 5 个版本)
- **加密环境变量** (AES-256-GCM)— 管理员无法读取它们
- **健康检查** 与自动重启和电子邮件通知
- **审计日志** 每个操作
- **MCP 服务器** 在 `/api/mcp` 上公开 35 个 `appcrane_*` 工具 — 代理操作平台,无需触及 curl、gh 或 shell
## 快速入门
```bash
curl -fsSL https://raw.githubusercontent.com/gitayg/appCrane/main/install.sh | sudo bash
```
或手动:
```bash
# 1. 克隆并安装
git clone https://github.com/gitayg/appCrane.git
cd appCrane
npm install
npm link # 使 'crane' 命令在全局范围内可用
# 2. 通过 systemd 安装和启动
cp scripts/appcrane.service /etc/systemd/system/appcrane.service
systemctl daemon-reload
systemctl enable --now appcrane
# 2.5. (可选)为 AppStudio 设置 Anthropic API 密钥
# 添加到 systemd 单元,使其在重启后仍然有效:
systemctl edit appcrane --force
# 在 [Service] 下添加:Environment="ANTHROPIC_API_KEY=sk-ant-..."
# 然后:systemctl daemon-reload && systemctl restart appcrane
# 3. 初始化管理员(必须在服务器上运行)
crane init --name admin --email admin@example.com
# 4. 创建应用
crane app create \
--name "MyApp" \
--slug myapp \
--domain myapp.example.com \
--repo https://github.com/yourorg/myapp
# 5. 创建用户并分配到应用
crane user create --name sarah --email sarah@example.com
crane app assign myapp --email sarah@example.com
# 6. 部署
crane config --key dhk_user_the_key_from_step_5
crane deploy myapp --env sandbox
```
## CLI 参考
### 服务器
```bash
crane status # 服务器健康状况:CPU、RAM、磁盘、应用
crane config --show # 显示 CLI 配置
crane config --url http://localhost:5001 # 设置 API URL
crane config --key dhk_admin_xxx # 设置 API 密钥
```
### 应用(管理员)
```bash
crane app list
crane app create --name X --slug x --domain x.example.com --repo https://github.com/...
crane app info myapp
crane app delete myapp --confirm
crane app assign myapp --email user@example.com
```
### 部署(应用用户)
```bash
crane deploy myapp --env sandbox
crane deploy myapp --env production
crane deploy:history myapp --env prod
crane deploy:log myapp --id 5
crane rollback myapp --env production
crane promote myapp # 沙盒 → 生产,零停机
```
### 环境变量(应用用户 — 管理员无法访问)
```bash
crane env set myapp --env sandbox DATABASE_URL=postgres://... API_KEY=sk-test
crane env list myapp --env production
crane env list myapp --env sandbox --reveal
crane env delete myapp API_KEY --env sandbox
```
### 健康状况、Webhook、备份
```bash
crane health status myapp
crane health config myapp --env prod --endpoint /api/health --interval 30
crane webhook myapp --auto-sandbox on
crane backup create myapp --env prod
crane backup list myapp
crane logs myapp --env production
crane audit --app myapp
```
## MCP(用于 AI 代理)
AppCrane 以 MCP 为优先。一次 `claude mcp add` 操作后,代理即可获得 35 个 `appcrane_*` 工具 — 列出应用、部署、设置/获取密钥、读取日志、管理访问、旋转图标等。工具名称与 AWS 对齐(`stage`、`set_secret`/`get_secret`、`cp`)。
```bash
claude mcp add --transport http appcrane https://crane.example.com/api/mcp \
--header "X-API-Key: dhk_admin_or_user_xxxxxxxxxxxxx" \
--header "X-Github-Token: ghp_your_github_pat"
```
然后在任何 Claude Code 会话中:
> 通过调用 `appcrane_get_guide` 并传入 `topic="onboarding"` 来新建一个应用,获取操作指南。
代理从服务器拉取当前指南,因此无需重新部署工具即可传播编辑。`topic="operations"` 返回 onboarding 后的参考资料(部署生命周期、故障排查快速失败、访问管理等)。
## 架构
```
Ubuntu 服务器
├── Caddy(反向代理,自动 HTTPS)
│ ├── myapp.example.com → 生产环境应用
│ └── myapp-sandbox.example.com → 沙盒环境应用
├── Docker(容器隔离)
│ ├── myapp-production ← 每个环境隔离的容器
│ └── myapp-sandbox
├── AppCrane API (:5001)
│ ├── Express 5 + SQLite
│ ├── 健康检查器(cron)
│ ├── 单点登录(SAML / OIDC / SCIM)
│ ├── AppStudio AI 流水线
│ └── 存在(WebSocket)
└── /data/apps/myapp/
├── production/releases/ (基于符号链接,最后 5 个)
└── sandbox/releases/
```
## 安全
- **初始化锁定到本地主机** — 仅限服务器本身的管理员设置
- **API 密钥身份验证** — 所有请求都需要 `X-API-Key` 头部
- **管理员隔离** — 管理员无法读取环境变量或 `/data/`;在中间件级别强制执行
- **AES-256-GCM** 环境变量加密存储
- **Webhook HMAC** GitHub 验证
- **SCIM 取消配置** — 从您的 IdP 中删除用户会自动撤销 AppCrane 访问权限
- **所有操作都被审计** — 谁做了什么,何时
## 部署应用的身份契约
在 AppCrane 上部署的应用无需实现自己的身份验证。Caddy 代理在将请求转发到容器之前,会根据 `/api/identity/verify` 验证每个请求,结果通过三种互补方式传递给应用。应用应按此 **优先级顺序** 使用它们:
### 1. 请求头(零获取,推荐)
Caddy `copy_headers` 将验证的身份复制到上游代理请求。应用直接读取它们:
| 头部 | 值 | 备注 |
|---|---|---|
| `X-AppCrane-User` | 电子邮件 | 向后兼容的单一标识符。始终为已验证的请求设置。 |
| `X-AppCrane-User-Id` | 数值 ID(字符串) | 始终设置。 |
| `X-AppCrane-User-Email` | 电子邮件 | 精细。可能为空,如果用户没有电子邮件。 |
| `X-AppCrane-User-Name` | 显示名称,`encodeURIComponent` 编码 | 读取时 `decodeURIComponent`。可能为空。 |
| `X-AppCrane-User-Role` | `platform_admin` \| `admin` \| `user` | 原始令牌,下划线保持不变。始终设置。 |
| `X-AppCrane-App-Role` | `owner` \| `admin` \| `user` \| `viewer` | 每个应用的角色。平台管理员在所有应用上折叠为 `admin` — 如果您需要专门针对平台管理员,请分支到 `X-AppCrane-User-Role`。 |
**信任模型:** Caddy 生成器在每个应用处理程序的 `forward_auth` 块之前发出 `request_header -X-AppCrane-*` strip 指令。Caddy 首先将任何客户端设置的 `X-AppCrane-*` 头部置为零,然后 `copy_headers` 仅注入 `/verify` 返回的内容。头部走私是不可能的 — 应用接收的内容保证是平台颁发的。
**缺失语义:** 如果请求中没有 `X-AppCrane-User-Role`,则请求 **未** 验证(Caddy 在 `forward_auth` 处关闭,您不会收到它)。因此 **存在 = 受信任**。
```js
// Express 示例
app.use((req, res, next) => {
const role = req.get('X-AppCrane-User-Role') // 'platform_admin' | 'admin' | 'user'
const appRole = req.get('X-AppCrane-App-Role') // 'owner' | 'admin' | 'user' | 'viewer'
const email = req.get('X-AppCrane-User-Email') || req.get('X-AppCrane-User')
req.user = role ? { id: req.get('X-AppCrane-User-Id'), email, role, appRole } : null
next()
})
```
### 2. `GET /api/me` (当您需要更多基本信息时)
返回完整用户信息 — 名称、电子邮件、用户名、全局角色 — 以及调用者询问的应用的每个应用角色。 与应用相同的来源,因此浏览器自动发送 `cc_token`;无需 SDK 或令牌管道:
```js
const r = await fetch('/api/me') // ?app=<slug> 可选;否则推断 Referer
if (r.status === 401) { location.href = '/login?redirect=' + encodeURIComponent(location.href); return }
const { user, app_role } = await r.json()
```
`/api/me` 内部的身份验证优先级:
1. `cc_token` cookie(代理应用的默认值 — `httpOnly`,浏览器管理)。
2. `Authorization: Bearer <session>`(CLI / 编程)。
3. `X-API-Key: dhk_*`(管理员 / 代理密钥)。
应用 slug 解析:
1. 显式 `?app=<slug>` 查询。
2. `Referer` 推断(第一个路径段;尝试沙盒后缀)。
3. 如果两者都无法解析,则使用精简的全局有效载荷。
### 3. 无头应用 — 完全退出
对于 *整个应用* 都是无身份验证的服务 — 遥测数据收集、公共 webhook、状态页面、squash CLI 的 `ping`/`stats` — 将应用的 `auth_mode` 设置为 `headless`(启动器中的所有者专用切换,或通过 MCP 使用 `appcrane_set_app_meta slug=<…> auth_mode=headless`)。然后 Caddy 块跳过 `forward_auth`、复制头部和剥离。没有 `X-AppCrane-*` 头部,没有 `/api/me`,没有 `cc_token`。应用服务器负责其需要的任何有效载荷级身份验证(HMAC、安装 ID、IP 允许列表等)。
按形状选择:
- **整个应用都是无身份验证的收集** → 无头应用(干净的分离,更小的爆炸半径)。
- **大多数身份验证的应用具有几个公共端点** → 保持 `authenticated`,在应用自己的路由器上门控公共路径。
## 权限模型
| 操作 | 管理员 | 应用用户 |
|--------|-------|----------|
| 创建/删除应用 | 是 | 否 |
| 分配用户 | 是 | 否 |
| 服务器健康状况 | 是 | 否 |
| 部署 / 回滚 / 推广 | **否** | 是(自己的应用) |
| 查看/编辑环境变量 | **否** | 是(自己的应用) |
| 配置健康状况/Webhook | **否** | 是(自己的应用) |
| 备份 | **否** | 是(自己的应用) |
## 技术栈
Node.js 20、Express 5、SQLite、Docker、Caddy 2、SAML/OIDC/SCIM、AES-256-GCM、Commander.js、Ubuntu 22.04+
## 许可证
[GNU AGPL v3](LICENSE)。免费开源 — 使用、修改和自主托管。如果您运行修改后的版本作为网络服务,则必须在相同许可证下提供源代码。需要以商业产品运行私人修改或将 AppCrane 嵌入专有产品? 提供 [商业许可证](COMMERCIAL-LICENSE.md)。
## 反馈与贡献
打开问题:https://github.com/gitayg/appCrane/issues
欢迎拉取请求 — 请先阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。它包括保持 AppCrane 的双重许可(AGPL + 商业)可能的简短 CLA。