轻量级 Web 应用部署服务 —— 从 GitHub 拉取项目,构建静态产物,通过 Nginx 子域名直接托管。
- GitHub OAuth 登录,管理员权限控制
- 一键部署 GitHub 仓库中的前端项目
- 自动分配子域名,Nginx 静态托管
- 实时构建日志(SSE 推送)
- 全站 HTTPS,泛域名证书自动申请 & 续期
- Docker Compose 一键启动,零依赖部署
- Node.js 20+
- Docker & Docker Compose
- 一个 GitHub OAuth App(回调地址设为
https://your-domain.com/api/auth/github/callback)
- 克隆仓库并安装依赖:
git clone https://github.com/your-username/orbit.git
cd orbit
npm install- 在项目根目录创建
.env文件:
GITHUB_CLIENT_ID=你的GitHub OAuth App ID
GITHUB_CLIENT_SECRET=你的GitHub OAuth App Secret
JWT_SECRET=随机生成的密钥字符串
DOMAIN=localhost- 构建共享包并启动开发服务器:
# 先构建 shared 包(server 和 web 都依赖它)
npm run build:shared
# 终端 1:启动后端(端口 3000)
npm run dev:server
# 终端 2:启动前端(端口 5173,自动代理 /api 到后端)
npm run dev:web- 打开浏览器访问
http://localhost:5173
第一个通过 GitHub 登录的用户会自动成为管理员。
-
准备一台服务器(2C2G 即可),安装 Docker
-
将项目上传到服务器,创建
.env文件:
GITHUB_CLIENT_ID=你的GitHub OAuth App ID
GITHUB_CLIENT_SECRET=你的GitHub OAuth App Secret
JWT_SECRET=随机生成的密钥字符串
DOMAIN=lsyfighting.cn
DP_Id=你的DNSPod ID
DP_Key=你的DNSPod Key- 一键启动:
docker compose up -d这会启动三个容器:
| 容器 | 说明 | 端口 |
|---|---|---|
orbit |
前端 + 后端 + 构建引擎 | 3000 |
orbit-nginx |
反向代理 + HTTPS + 静态托管 | 80, 443 |
orbit-acme |
SSL 证书自动管理 | - |
- 首次手动签发 SSL 证书:
docker exec orbit-acme /entrypoint.sh issue之后证书 90 天有效,60 天时自动续期,无需人工介入。
- 配置域名 DNS:
deploy.your-domain.com→ 服务器 IP(管理界面)*.your-domain.com→ 服务器 IP(部署的应用)
访问管理界面首页,即可看到所有已部署应用的卡片列表,包括:
- 应用名称、状态(构建中 / 已部署 / 失败)
- GitHub 仓库地址
- 子域名链接(点击直达)
点击任意应用卡片可查看详情页,包含构建历史记录。
- 点击导航栏的 Deploy
- 填写部署表单:
| 字段 | 说明 | 默认值 |
|---|---|---|
| 应用名称 | 只允许小写字母、数字和连字符 | - |
| 仓库地址 | GitHub 仓库 URL | - |
| 分支 | 要部署的分支 | main |
| 构建命令 | 构建脚本 | npm run build |
| 输出目录 | 构建产物所在目录 | dist |
- 提交后自动开始构建,页面实时展示构建日志
- 构建成功后,应用即可通过
应用名.your-domain.com访问
在应用列表或详情页点击 Deploy 按钮,即可拉取最新代码并重新构建部署。
点击导航栏 Admin,可查看所有已登录用户,并切换其管理员权限。
用户提交部署 → 克隆/拉取仓库 → npm install → 构建 → 产物原子替换 → 生成 Nginx 配置 → 重载 Nginx → 上线
- 创建构建记录,状态设为
building - 克隆仓库(首次)或拉取最新代码(后续)
- 执行
npm install+ 构建命令 - 将产物原子性地部署到站点目录(先写
.tmp,再 rename,无停机) - 生成 Nginx 虚拟主机配置(HTTP→HTTPS 跳转 + SPA 路由支持)
- 重载 Nginx,站点上线
服务器
├── Docker
│ ├── Orbit 容器(前端 + 后端 + 构建引擎)
│ ├── Nginx 容器(反向代理 + HTTPS + 静态文件托管)
│ │ ├── app-a.domain.com → /data/sites/app-a/
│ │ ├── app-b.domain.com → /data/sites/app-b/
│ │ └── ...
│ └── acme.sh 容器(自动申请 & 续期 SSL 证书)
├── /data/sites/ 构建产物(共享卷)
├── /data/repos/ Git 仓库克隆
├── /data/nginx/ Nginx 动态配置
├── /data/ssl/ SSL 证书
└── /data/orbit.db SQLite 数据库
- 用户项目不起独立容器,构建产物直接输出到共享卷,由 Nginx 静态托管
- 全站 HTTPS,泛域名证书由 acme.sh 通过 DNSPod DNS API 自动管理
- 部署采用原子替换,零停机
orbit/
├── packages/
│ ├── server/ 后端(Hono + SQLite)
│ │ ├── src/
│ │ │ ├── routes/ API 路由(auth, apps, admin, github, sse)
│ │ │ ├── services/ 核心服务(deploy, builder, nginx, git)
│ │ │ ├── db/ 数据库 schema & 迁移
│ │ │ ├── middleware/ 认证 & 权限中间件
│ │ │ └── lib/ 工具(jwt, github oauth, env)
│ │ └── package.json
│ ├── web/ 前端(React + TanStack Query)
│ │ ├── src/
│ │ │ ├── pages/ 页面(Apps, AppDetail, Deploy, Admin)
│ │ │ ├── components/ UI 组件
│ │ │ ├── api/ API 客户端 & 请求 hooks
│ │ │ └── hooks/ useAuth, useSSE
│ │ └── package.json
│ └── shared/ 共享类型 & 常量
│ └── package.json
├── docker/ Docker 相关配置
│ ├── Dockerfile.orbit
│ ├── Dockerfile.nginx
│ ├── nginx/ Nginx 配置模板
│ └── acme/ SSL 证书脚本
├── docker-compose.yml
└── package.json Monorepo 根配置
# 开发
npm run dev:server # 启动后端开发服务器
npm run dev:web # 启动前端开发服务器
# 构建
npm run build # 构建全部包(shared → server → web)
npm run build:shared # 仅构建 shared
npm run build:server # 仅构建 server
npm run build:web # 仅构建 web
# 数据库
npm run db:generate # 生成 Drizzle 迁移文件
npm run db:migrate # 执行数据库迁移
# 类型检查
npm run typecheck # 全量类型检查
# Docker
docker compose up -d # 启动生产环境
docker compose down # 停止服务
docker compose logs -f # 查看日志
docker exec orbit-acme /entrypoint.sh issue # 手动签发证书
docker exec orbit-acme /entrypoint.sh renew # 手动续期证书| 层级 | 方案 | 备注 |
|---|---|---|
| 前端 | React 19 + TypeScript + Tailwind CSS 4 | SPA 管理界面 |
| 后端 | Node.js + Hono | 轻量、Web 标准 API |
| 数据库 | SQLite + Drizzle ORM | 轻量持久化,TypeScript 优先 |
| 反向代理 | Nginx | 子域名路由 + HTTPS + 静态托管 |
| 认证 | GitHub OAuth + JWT | 无密码管理 |
| SSL | acme.sh + Let's Encrypt | 泛域名证书自动管理 |
| 实时日志 | Server-Sent Events | 单向实时推送 |
| 构建工具 | Vite | 前端开发 & 构建 |
| 变量 | 必填 | 说明 |
|---|---|---|
GITHUB_CLIENT_ID |
是 | GitHub OAuth App ID |
GITHUB_CLIENT_SECRET |
是 | GitHub OAuth App Secret |
JWT_SECRET |
是 | JWT 签名密钥 |
DOMAIN |
是 | 域名(如 lsyfighting.cn) |
DATA_DIR |
否 | 数据目录,默认 ./data |
PORT |
否 | 服务端口,默认 3000 |
DP_Id |
生产 | DNSPod API ID(acme.sh 证书申请) |
DP_Key |
生产 | DNSPod API Key(acme.sh 证书申请) |