阿里云 OSS 存储(适合中国大陆业务)
将 EasyStarter 的存储 Provider 切换到阿里云对象存储 OSS,复用 RAM AccessKey
阿里云 OSS 存储
EasyStarter 内置了阿里云 对象存储 OSS 作为存储服务商,可以与默认的 Cloudflare R2 自由切换。服务端通过 OSS REST API V4 签名直接调用,不依赖任何 Node.js SDK,可以在 Cloudflare Workers Runtime 下直接运行。
如果你的服务主要面向中国大陆用户,使用阿里云 OSS 通常能获得更稳定的访问速度和更低的出口流量成本;与上一节的 阿里云手机号登录 共用同一对 RAM AccessKey,运维上也更简单。
| 项目 | 当前配置 |
|---|---|
| 上传/下载/列举/删除 | OSS REST API V4 + OSS4-HMAC-SHA256 签名 |
| 服务端 Provider | apps/server/src/storage/providers/aliyun-oss.ts |
| Provider 注册位置 | apps/server/src/storage/index.ts |
| 配置开关 | packages/app-config/src/app-config.ts 中的 common.storage.provider |
| 文件访问路径 | ${SERVER_URL}/api/storage/aliyun-oss/<key>(通过服务端代理,OSS Bucket 无需公开) |
EasyStarter 现有的 avatar 与 attachment 上传类型、文件大小和 MIME 类型限制对所有 Provider 通用,切换到 OSS 后业务代码无需修改。
所需环境变量
# 与阿里云手机号登录共用同一对 RAM AccessKey
ALIBABA_CLOUD_ACCESS_KEY_ID=
ALIBABA_CLOUD_ACCESS_KEY_SECRET=
# OSS 专属
ALIYUN_OSS_BUCKET=
ALIYUN_OSS_REGION=
ALIYUN_OSS_ENDPOINT=变量说明:
| 变量 | 含义 | 示例 |
|---|---|---|
ALIBABA_CLOUD_ACCESS_KEY_ID | RAM 用户 AccessKey ID,服务端调用 OSS 的长期凭证 | LTAI5tXXXXXXXXXXXXXXXXX |
ALIBABA_CLOUD_ACCESS_KEY_SECRET | RAM 用户 AccessKey Secret,仅创建时显示一次 | XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX |
ALIYUN_OSS_BUCKET | OSS Bucket 名称,不含域名 | your-app-bucket |
ALIYUN_OSS_REGION | Bucket 所在地域 ID,签名时作为 region scope | cn-hangzhou |
ALIYUN_OSS_ENDPOINT | OSS 访问域名,不要带 Bucket 前缀和协议头 | oss-cn-hangzhou.aliyuncs.com |
ALIYUN_OSS_ENDPOINT 必须填外网访问域名,例如 oss-cn-hangzhou.aliyuncs.com。如果你写成 your-app-bucket.oss-cn-hangzhou.aliyuncs.com,Provider 内部会再次拼接一次 Bucket,导致请求路径错误。
如果你已经按照 阿里云手机号登录 配置过 ALIBABA_CLOUD_ACCESS_KEY_ID / ALIBABA_CLOUD_ACCESS_KEY_SECRET,可以直接复用同一对密钥,只需要为同一个 RAM 用户追加 OSS 权限。
创建 OSS Bucket
官方文档:创建存储空间
- 登录 OSS 控制台
- 点击 Bucket 列表 → 创建 Bucket
- 填写 Bucket 名称,例如
your-app-bucket(全局唯一,3-63 字符,仅小写字母、数字、短横线) - 选择 地域,例如
华东1(杭州),对应 region IDcn-hangzhou - 读写权限保持默认的 私有(文件通过服务端代理访问,Bucket 不需要公开)
- 其它选项按默认即可,点击 完成创建
记录以下信息:
- Bucket 名称 →
ALIYUN_OSS_BUCKET - 地域 ID(控制台 Bucket 概览页的 地域 字段,例如
oss-cn-hangzhou中的cn-hangzhou)→ALIYUN_OSS_REGION - 外网访问 Endpoint(Bucket 概览页的 Endpoint(外网访问) 字段,例如
oss-cn-hangzhou.aliyuncs.com)→ALIYUN_OSS_ENDPOINT
为 RAM 用户授予 OSS 权限
推荐使用 RAM 用户的 AccessKey,不要直接使用阿里云主账号 AccessKey。如果你已经按照 阿里云手机号登录 创建过 RAM 用户,可以直接给同一个用户追加授权。
- 登录 阿里云 RAM 控制台
- 进入 身份管理 → 用户,选中目标 RAM 用户
- 点击 权限管理 → 新增授权
- 资源范围选择 账号级别,在 权限策略 中搜索并勾选系统策略
AliyunOSSFullAccess,然后点击 确认新增授权

这是阿里云官方推荐的做法,挂载系统策略后该 RAM 用户即可读写 OSS。
获取或复用 AccessKey
官方文档:创建 AccessKey
如果还没有 AccessKey:
- 在 RAM 用户详情页打开 认证管理 或 AccessKey 标签
- 点击 创建 AccessKey,按提示完成安全校验
- 创建成功后立即复制保存:
AccessKey ID→ALIBABA_CLOUD_ACCESS_KEY_IDAccessKey Secret→ALIBABA_CLOUD_ACCESS_KEY_SECRET
AccessKey Secret 只会在创建时显示一次。如果丢失,只能禁用旧密钥并重新创建。
如果你已经为手机号登录配置过同一个 RAM 用户的 AccessKey,直接复用即可,不要再为同一个用户创建多对 AccessKey。
切换 Storage Provider
在 packages/app-config/src/app-config.ts 中,把 common.storage.provider 从 "r2" 改成 "aliyun-oss":
storage: {
enabled: true,
provider: "aliyun-oss", // 从 "r2" 改成 "aliyun-oss"
publicPath: "/api/storage",
// ...其余字段保持不变
},切换后,所有 avatar / attachment 上传、下载、列举、删除都会自动走 OSS Provider,业务代码、上传组件、Better Auth 头像逻辑都不需要改。
填入本地与生产环境变量
本地开发写入 apps/server/.dev.vars:
ALIBABA_CLOUD_ACCESS_KEY_ID=your-access-key-id
ALIBABA_CLOUD_ACCESS_KEY_SECRET=your-access-key-secret
ALIYUN_OSS_BUCKET=your-oss-bucket
ALIYUN_OSS_REGION=your-oss-region
ALIYUN_OSS_ENDPOINT=your-oss-endpoint生产部署写入 apps/server/.env.production:
ALIBABA_CLOUD_ACCESS_KEY_ID=your-access-key-id
ALIBABA_CLOUD_ACCESS_KEY_SECRET=your-access-key-secret
ALIYUN_OSS_BUCKET=your-oss-bucket
ALIYUN_OSS_REGION=your-oss-region
ALIYUN_OSS_ENDPOINT=your-oss-endpoint切换到 OSS 后,R2_PUBLIC_URL 不再需要,可以从两个环境文件中删除。apps/server/wrangler.jsonc 中的 r2_buckets 绑定(STORAGE)也不再被读取,可以保留以便随时切回,也可以删除。
推送生产 Secrets
部署到 Cloudflare Workers 前,把生产密钥推送到 Workers Secrets:
pnpm -F server secrets:bulk:production推送成功后,Worker 运行时通过 env.ALIBABA_CLOUD_ACCESS_KEY_ID、env.ALIBABA_CLOUD_ACCESS_KEY_SECRET、env.ALIYUN_OSS_BUCKET、env.ALIYUN_OSS_REGION、env.ALIYUN_OSS_ENDPOINT 读取这些变量。更新任意一个值后重新执行这条命令即可生效,不需要因为 Secret 变化重新部署代码。
本地验证文件上传
启动服务端与客户端:
pnpm dev:server
pnpm dev:web登录后在个人资料页上传一张头像。前端会向 /api/storage/upload 提交文件,服务端调用 OSS Provider 的 put 方法把文件写入 avatars/<userId>/...,并返回如下形式的公共 URL:
http://localhost:3001/api/storage/aliyun-oss/avatars/<userId>/<uuid>.png后续读取由服务端的 /api/storage/aliyun-oss/<key> 路由代理回 OSS,Bucket 本身保持私有即可。
可以在 OSS 控制台的 文件管理 中确认对象已经写入对应前缀;在浏览器中直接打开上面那条公共 URL 也应该能看到图片。