本文档带你从克隆仓库到本地完整运行整套服务。

前置条件

  • Bun >= 1.3.5
  • Rust — 最新 stable 版
  • PostgreSQL 15+(本地或远程均可)
  • Docker & Docker Compose(可选,用于一键启动)

1. 克隆并安装依赖

git clone https://github.com/your-org/openproxy.git
cd openproxy
bun install

2. 生成 RSA 密钥对

供应商 API Key 以 RSA 加密形式存入数据库,需提前生成密钥对:

bun scripts/generateRSAKey.ts

保存输出结果,下一步会用到。

3. 配置环境变量

apps/server

cp apps/server/.env.example apps/server/.env

编辑 apps/server/.env,至少填写:

DATABASE_URL=postgres://user:password@localhost:5432/openproxy
BETTER_AUTH_SECRET=<随机 32 字节 base64 字符串>
BETTER_AUTH_URL=http://localhost:3888/api
BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:5173
RSA_PRIVATE_KEY=<第 2 步生成的私钥>
RSA_PUBLIC_KEY=<第 2 步生成的公钥>

# 邮件(任选其一)
RESEND_API_KEY=         # Resend
# 或 SMTP_HOST / SMTP_USER / SMTP_PASS / SMTP_FROM

# OAuth(可选)
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

apps/api

新建 apps/api/.env

DATABASE_URL=postgres://user:password@localhost:5432/openproxy
RSA_PRIVATE_KEY=<与 server 相同的私钥>
PORT=5060

4. 执行数据库迁移

cd apps/server
bun run migrate

该命令将 apps/server/drizzle/ 中的 SQL 应用到 PostgreSQL 实例。

5. 启动所有服务

# 根目录一键启动(Turborepo 并行拉起所有服务)
bun run dev

也可以单独启动各服务:

cd apps/api    && cargo run                # Rust 代理,端口 :5060
cd apps/server && bun run dev             # Bun 后端,端口 :3888
cd apps/web    && bun run dev:tenant      # 租户页,端口 :5173
cd apps/web    && bun run dev:admin       # 管理页,端口 :5173

6. 验证服务正常

# 代理健康检查
curl http://localhost:5060/health

# 后端健康检查
curl http://localhost:3888/api/health

之后在浏览器打开 http://localhost:5173 即可访问 Web 界面。

默认端口

服务地址
Rust 代理http://localhost:5060
Bun 后端http://localhost:3888
租户前端http://localhost:5173
管理后台http://localhost:5173

常见问题

数据库连接失败

确认 DATABASE_URL 正确,PostgreSQL 已启动,且该账号拥有 CREATE 权限(迁移阶段需要)。

鉴权回调异常

BETTER_AUTH_URL 必须指向 apps/server 实际可访问的地址;BETTER_AUTH_TRUSTED_ORIGINS 必须与前端 Web 的 origin 一致。

API Key 解密失败 / RSA 报错

确保 apps/api/.env 中的 RSA_PRIVATE_KEYapps/server/.env 中的同一套密钥对,且值完整、无换行截断或多余空格。务必使用同一次 bun scripts/generateRSAKey.ts 的输出。

端口被占用

检查 :5060:3888 是否已有进程占用,在对应 .env 文件中用 PORT=xxxx 覆盖。