阿里雲 OSS
大約 10 分鐘、不需要花錢,就能在阿里雲上替孤雲準備好一個儲存桶,以及一對只授權這個桶的金鑰。本文是官方引導;控制台介面請以你打開時為準。
新手建議從海外地域(例如香港 cn-hongkong)開始:不需要網域、備案或憑證。想要內地速度,先讀「內地地域的兩個硬限制」。本文依繁體介面用詞;控制台若顯示簡體,按鈕名稱請按同義對照。
要準備什麼
- 一個阿里雲帳號;沒有就先註冊,並完成實名認證(個人可用身分證)。
- 一個付款方式。開通 OSS 本身是 ¥0.00;費用只產生在實際儲存量、請求次數與外網流量上。
- 一個全域唯一的桶名,例如
your-bucket-name:3–63 位小寫字母、數字和短橫線,首尾必須是字母或數字。 - 只有內地路線才需要:一個已完成 ICP 備案的網域、HTTPS 憑證,以及一台符合條件的內地伺服器(輕量應用伺服器 / ECS,包年包月 ≥3 個月、帶公網頻寬)用來領取備案服務碼。
- 建議用電腦操作:RAM 與 AccessKey 的控制台在電腦上順手得多。
只走海外地域的話,不需要網域、備案、憑證,也不需要多買伺服器。
分步操作
-
第 1 步
註冊阿里雲帳號並完成實名認證
- 打開阿里雲註冊頁,用手機號或電子郵件註冊。
- 完成實名認證(個人可用身分證);認證通過後才能開通 OSS。
- 內地路線建議把網域、備案與 OSS 放在同一個帳號,後面少一步。
-
第 2 步
開通物件儲存 OSS
- 在控制台搜尋「物件儲存 OSS」,進入產品頁點「立即開通」。
- 開通頁列出的訂單金額是 ¥0.00;必須勾選「我已閱讀並同意…專屬條款」,再點「去支付」。
- 支付頁確認金額 ¥0.00,完成後點「管理控制台」進入 OSS 控制台。開通本身不收費。
-
第 3 步
建立儲存桶(Bucket)
- 在「Bucket 列表」點「建立 Bucket」。
- 桶名全域唯一,例如
your-bucket-name:3–63 位小寫字母、數字和短橫線,首尾必須是字母或數字。 - 地域選離你和主要使用者最近的。海外建議香港
cn-hongkong;內地請先讀下面的硬限制。 - 讀寫權限選「私有」,「阻止公共存取」保持開啟。
- 儲存類型用「標準」,版本控制保持關閉(孤雲不使用多版本)。
-
第 4 步
建立 RAM 子使用者並取得金鑰
- 進入「存取控制 RAM」→「身分管理 → 使用者」→「建立使用者」。
- 勾選「OpenAPI 呼叫存取」(較新的介面寫成「使用永久 AccessKey 存取」)—— 都是指用 AccessKey 呼叫;不要勾選控制台登入。
- 建立完成後,AccessKey ID 與 Secret 只顯示一次,立刻複製保存;關掉頁面就再也看不到 Secret。
- 不要使用主帳號(根帳號)金鑰,也不要掛
AliyunOSSFullAccess。
-
第 5 步
掛上最小權限策略
- 在「權限管理 → 權限策略」裡新建一條自訂策略,切到腳本(JSON)編輯方式。
- 貼上下面的最小權限策略,把
your-bucket-name換成你的真實桶名。 - 回到使用者頁面,把這條自訂策略授權給剛才建立的子使用者。
- 不要把資源範圍縮小到某個目錄:孤雲還要在
.guyun/前綴下寫入垃圾桶清單、裝置連線記錄,以及跨裝置交接用的.guyun/handoff/;縮小會讓這些寫入失敗。 - 不要授予
oss:*、刪桶、改 Bucket ACL 或管理歷史版本;縮圖屬於oss:GetObject,不需要額外權限。
-
第 6 步
把四個值填進孤雲
- 打開孤雲的「新增儲存」,服務商選「阿里雲 OSS」。
- 填:Bucket 名稱 = 你的桶名;地域 = 桶所在地域(例如
cn-hongkong);Endpoint =https://oss-{地域}.aliyuncs.com;AccessKey ID 與 Secret = 剛才那對金鑰。 - 海外地域的位址方式用「Bucket 子網域」;綁了自訂網域就把 Endpoint 改成你的網域,位址方式選「自訂網域 CNAME」。
- 金鑰只保存在本機 Keychain,不上傳、不同步;不要貼到聊天、文件或程式碼裡。
-
第 7 步
測試連線並儲存
- 回到孤雲點「測試連線並儲存」,它只呼叫 ListObjectsV2 列出一次根目錄。
- 讀得到不代表寫得進去:建議在桶裡建一個臨時目錄,做一次上傳 / 下載 / 刪除,再把臨時目錄刪掉。
- 連不上時對照下面的「常見錯誤」,按錯誤碼排查。
四條路線
先挑一條符合你現有條件的路線 —— 各條的接入工作量差很多。
| 路徑 | 需要準備 | 代價 | 適合誰 |
|---|---|---|---|
海外地域(例如香港 cn-hongkong) | 只要 OSS 與一對金鑰 | 內地連線跨境,速度略慢 | 新手推薦,沒有備案問題 |
| 內地地域 + 自訂網域 | 已備案的網域 + HTTPS 憑證 + 一台符合條件的內地伺服器(換備案服務碼) | 備案要 1–20 個工作日,還要額外買伺服器 | 有網域、要內地速度的人 |
| 內地地域 + 預設網域 | 僅限 2025-03-20 之前開通 OSS 的帳號 | 新帳號不可用,會得到 PublicEndpointForbidden | 老帳號 |
| 不想看這些,走 ROS | 只要 OSS | 多兩次點擊(複製並貼上範本) | 想省事的人 |
最小權限 RAM 策略
把這段 JSON 貼進你正在新建的自訂策略(腳本編輯)。它只授權這一個桶的讀寫,不含刪桶與 Bucket 設定。
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": ["oss:ListObjects", "oss:GetBucketLocation", "oss:ListMultipartUploads"],
"Resource": ["acs:oss:*:*:your-bucket-name"]
},
{
"Effect": "Allow",
"Action": ["oss:GetObject", "oss:PutObject", "oss:DeleteObject", "oss:AbortMultipartUpload", "oss:ListParts"],
"Resource": ["acs:oss:*:*:your-bucket-name/*"]
}
]
}
把 your-bucket-name 換成真實桶名 —— 這一處沒替換是新手最常見的 403 原因。
掛策略時的三條紅線
不要把資源範圍縮小到某個目錄。 除了你自己的檔案,孤雲還要在 .guyun/ 前綴下寫入垃圾桶清單、裝置連線記錄,以及跨裝置交接用的短命記錄 .guyun/handoff/;縮小會讓這些寫入失敗。
不要授予 oss:* 或 AliyunOSSFullAccess,也不要允許刪桶、改 Bucket ACL 或管理歷史版本。 縮圖屬於 oss:GetObject,上面的策略已經夠用。
不要使用主帳號金鑰。 替孤雲單獨建一個 RAM 子使用者,只授權這一個桶。
內地地域的兩個硬限制
① 備案服務碼:OSS 不提供。 替 OSS 的網域辦備案時要選一個備案服務碼,而服務碼只由符合條件的內地伺服器產品贈送(輕量應用伺服器 / ECS,內地節點、包年包月且時長 ≥3 個月、已購公網頻寬)。OSS 不在名單裡,免費試用與按量付費的 ECS 也不符合條件。網域若在境外註冊商(GoDaddy、Namecheap、Cloudflare 等),還要先轉入境內註冊商才能備案。
② PublicEndpointForbidden:預設外網網域被拒。 2025-03-20 起新開通 OSS 的帳號,用預設外網網域(例如 oss-cn-hangzhou.aliyuncs.com)存取內地 Bucket 的資料類 API(上傳、下載都算)一律被拒。它限制的是網域,不是權限:桶設為私有、阻止公共存取、不對外提供任何連結,一樣受限;判斷依據是 OSS 的開通時間,不是建桶時間,與桶權限無關;S3 相容網域 s3.oss-{地域}.aliyuncs.com 同樣受限。
要留在內地地域,就得綁定一個已備案的自訂網域(並配置 HTTPS 憑證);否則請換香港或其他海外地域 —— 那裡的預設網域不受這條限制。
ROS 一鍵路線:一次建好桶、RAM 使用者與金鑰
不想一步步點,就讓阿里雲的資源編排(ROS)按下面這份範本一次建好:私有且阻止公共存取的桶、只授權該桶的 RAM 使用者,以及這個使用者的 AccessKey。完成後從資源棧的「輸出」複製 AccessKey ID 與 Secret。
- 打開 ROS 控制台:
https://ros.console.aliyun.com/。國際站帳號用ros.console.alibabacloud.com。 - 複製下面的範本全文,在建立頁選「指定範本 → 輸入範本」,範本內容格式選 ROS + JSON,貼進去再點下一步。
- 坑 1:依賴要顯式寫。 範本裡給策略與 AccessKey 指定 RAM 使用者時,用
Ref取參數裡的使用者名不會讓 ROS 自動建立依賴,必須顯式寫DependsOn: AppUser(這份範本裡已經寫好,並用Fn::GetAtt引用資源屬性);改範本時把這兩處丟掉,會得到The user … is not exists一類的驗證錯誤。 - 坑 2:RAM 的
DisplayName上限是 12 個字元(官方文件寫 1–128,實際 API 只允許 12,中文算 1 個)。超過會在校驗階段被擋下;這份範本用的是固定值「孤雲存儲」,桶名放在備註裡。 - 坑 3:建立頁下方有一個「安全確認」勾選框(「我確認,阿里雲 ROS 可能建立 RAM 資源」),不勾選無法建立。資源棧名稱保持預設即可(形如
guyun_2026-09-11_xxxx)。 - 失敗時點資源棧的「事件」看原因:桶名被佔用最常見;得到
The Parameter (BucketName) was not defined in template表示範本沒貼進去(回第 1 步重來);漏勾「安全確認」也會被擋下。 - 同一帳號裡再建一個桶時,把建立頁裡的
RAM 使用者名從預設的guyun-app改成別的(例如guyun-{bucket})—— 同名使用者已存在時建立會失敗。 - 刪資源棧會連同它建的桶與 RAM 使用者一起刪掉,桶裡有資料時不要隨手刪。
ROS 範本(原文)
複製全文,貼到 ROS 建立頁的「輸入範本」裡。
{
"ROSTemplateFormatVersion": "2015-09-01",
"Description": {
"zh-cn": "为孤云创建:私有且阻止公共访问的 OSS Bucket、只授权该桶读写的 RAM 用户、以及该用户的 AccessKey。AccessKey ID 与 Secret 会出现在资源栈的「输出」里,复制回应用即可。",
"en": "Creates, for Guyun: a private OSS bucket with public access blocked, a RAM user limited to that bucket, and an AccessKey for it. The AccessKey ID and secret appear in the stack outputs; copy them back into the app."
},
"Parameters": {
"BucketName": {
"Type": "String",
"Label": {
"zh-cn": "Bucket 名称",
"en": "Bucket name"
},
"Description": {
"zh-cn": "全局唯一。3–63 位,只能用小写字母、数字和短横线,首尾必须是字母或数字。例如 my-photos-2026。",
"en": "Globally unique. 3–63 characters: lowercase letters, digits and hyphens, starting and ending with a letter or digit. For example my-photos-2026."
},
"AllowedPattern": "^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$",
"MinLength": 3,
"MaxLength": 63
},
"RamUserName": {
"Type": "String",
"Label": {
"zh-cn": "RAM 用户名",
"en": "RAM user name"
},
"Description": {
"zh-cn": "给应用专用的子账号。如果账号下已经有同名用户,请改成别的名字再创建。",
"en": "A dedicated sub-account for the app. If a user with this name already exists, pick another one."
},
"Default": "guyun-app",
"AllowedPattern": "^[a-zA-Z0-9._-]{1,64}$",
"MinLength": 1,
"MaxLength": 64
}
},
"Resources": {
"Bucket": {
"Type": "ALIYUN::OSS::Bucket",
"Properties": {
"BucketName": {
"Ref": "BucketName"
},
"AccessControl": "private",
"StorageClass": "Standard",
"BlockPublicAccess": true
}
},
"AppUser": {
"Type": "ALIYUN::RAM::User",
"Properties": {
"UserName": {
"Ref": "RamUserName"
},
"DisplayName": {
"Fn::Sub": "孤云存储"
},
"Comments": {
"Fn::Sub": "孤云专用存储用户;授权桶 ${BucketName} 的读写;随资源栈删除。"
}
}
},
"BucketPolicy": {
"Type": "ALIYUN::RAM::ManagedPolicy",
"DependsOn": "AppUser",
"Properties": {
"PolicyName": {
"Fn::Sub": "guyun-${BucketName}-rw"
},
"Description": {
"Fn::Sub": "Guyun: read and write ${BucketName} only. No bucket-level administration."
},
"PolicyDocument": {
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:ListObjects",
"oss:GetBucketLocation",
"oss:ListMultipartUploads"
],
"Resource": [
{
"Fn::Sub": "acs:oss:*:*:${BucketName}"
}
]
},
{
"Effect": "Allow",
"Action": [
"oss:GetObject",
"oss:PutObject",
"oss:DeleteObject",
"oss:AbortMultipartUpload",
"oss:ListParts"
],
"Resource": [
{
"Fn::Sub": "acs:oss:*:*:${BucketName}/*"
}
]
}
]
},
"Users": [
{
"Fn::GetAtt": [
"AppUser",
"UserName"
]
}
]
}
},
"AccessKey": {
"Type": "ALIYUN::RAM::AccessKey",
"DependsOn": "AppUser",
"Properties": {
"UserName": {
"Fn::GetAtt": [
"AppUser",
"UserName"
]
}
}
}
},
"Outputs": {
"BucketName": {
"Label": {
"zh-cn": "Bucket 名称",
"en": "Bucket name"
},
"Description": {
"zh-cn": "填到应用的「Bucket 名称」里。",
"en": "Paste into the app's bucket name field."
},
"Value": {
"Ref": "BucketName"
}
},
"RegionId": {
"Label": {
"zh-cn": "地域",
"en": "Region"
},
"Description": {
"zh-cn": "资源栈所在地域,也就是 Bucket 的地域。",
"en": "The stack's region, which is the bucket's region."
},
"Value": {
"Ref": "ALIYUN::Region"
}
},
"Endpoint": {
"Label": {
"zh-cn": "HTTPS Endpoint",
"en": "HTTPS endpoint"
},
"Description": {
"zh-cn": "走默认域名时填到应用的「HTTPS Endpoint」里(地址方式选「Bucket 子域名」);如果之后绑了自定义域名,Endpoint 要改成那个域名。",
"en": "With the default endpoint, paste this into the app's HTTPS endpoint field (addressing: virtual host). If you bind a custom domain later, the endpoint becomes that domain instead."
},
"Value": {
"Fn::Sub": "https://oss-${ALIYUN::Region}.aliyuncs.com"
}
},
"AccessKeyId": {
"Label": {
"zh-cn": "AccessKey ID",
"en": "AccessKey ID"
},
"Description": {
"zh-cn": "复制后填到应用的「AccessKey ID」里。",
"en": "Copy into the app's AccessKey ID field."
},
"Value": {
"Fn::GetAtt": [
"AccessKey",
"AccessKeyId"
]
}
},
"AccessKeySecret": {
"Label": {
"zh-cn": "AccessKey Secret",
"en": "AccessKey secret"
},
"Description": {
"zh-cn": "只在这里显示,复制后填进应用的 Keychain;不要粘贴到聊天、文档或代码里。",
"en": "Shown here only. Copy it into the app's Keychain; never paste it into a chat, document or repository."
},
"Value": {
"Fn::GetAtt": [
"AccessKey",
"AccessKeySecret"
]
}
}
},
"Metadata": {
"ALIYUN::ROS::Interface": {
"ParameterGroups": [
{
"Parameters": [
"BucketName"
],
"Label": {
"default": "OSS"
}
},
{
"Parameters": [
"RamUserName"
],
"Label": {
"default": "RAM"
}
}
],
"Outputs": [
"BucketName",
"RegionId",
"Endpoint",
"AccessKeyId",
"AccessKeySecret"
]
}
}
}
這份範本與上面的手動路線做出完全一樣的資源與權限:私有且阻止公共存取的桶、只授權該桶的策略、為該使用者建立的 AccessKey。範本內容就在本頁,不需要信任任何第三方託管。
官方來源
控制台文案會變,這幾頁是查證依據。
- 地域與外網 Endpoint 總表 (另開新視窗)
- 透過自訂網域存取 OSS(內地地域預設網域的限制) (另開新視窗)
- 如何取得備案服務碼(OSS 不在名單裡) (另開新視窗)
- OSS 自訂網域的備案要求與子網域規則 (另開新視窗)
- PublicEndpointForbidden 錯誤說明 (另開新視窗)
- 用 AWS SDK 存取 OSS(S3 相容端點同樣受限) (另開新視窗)
- 建立 RAM 使用者 (另開新視窗)
- ROS:自訂建立資源棧頁面 (另開新視窗)
- 開啟 ROS 控制台 (另開新視窗)
抄下這四個值
這四個值要填進孤雲的「新增儲存」頁:
| 抄下這個值 | 填進孤雲的哪一格 |
|---|---|
桶名your-bucket-name(換成你的真實桶名) | 桶名稱 |
地域cn-hongkong | 地域 / Region |
端點https://oss-cn-hongkong.aliyuncs.com | Endpoint |
| 金鑰 RAM 子使用者的 AccessKey ID 與 Secret | AccessKey ID 與 Secret |
怎麼知道成了
- 孤雲的「測試連線並儲存」回報成功,能列出桶的根目錄(空桶回傳空清單也算成功)。
- 想完整驗證:在桶裡建一個臨時目錄,上傳一個檔案、下載一次、再刪掉 —— 三步都通過,讀寫權限就齊了。
- 常見錯誤都沒出現:沒有 403,沒有
PublicEndpointForbidden,沒有SignatureDoesNotMatch。
回到孤雲,點「測試連線並儲存」。
常見錯誤
在「測試連線並儲存」裡看到這些錯誤碼時,按下面的順序排查。
| 現象 / 錯誤碼 | 含義 | 怎麼辦 |
|---|---|---|
403 AccessDenied | 金鑰沒權限,或自訂策略裡的桶名沒替換成真實桶名;也可能策略沒授權給這個子使用者 | 回第 5 步核對:your-bucket-name 是否已替換、策略是否掛在這個使用者上、金鑰是否屬於該使用者 |
PublicEndpointForbidden | 內地地域 + 預設外網網域 + OSS 在 2025-03-20 之後開通 | 綁定已備案的自訂網域(Endpoint 換成該網域、位址方式選 CNAME),或把桶換到香港 / 其他海外地域 |
SignatureDoesNotMatch / InvalidAccessKeyId | 金鑰複製錯了(Secret 只顯示一次,沒存下就再也拿不到),或 ID 與 Secret 不是同一對 | 在 RAM 使用者下重新建立一對 AccessKey,把兩個值一起複製回孤雲 |
| 連線測試通過,但上傳失敗 | 測試只呼叫了 ListObjectsV2 —— 讀得到不代表寫得進去 | 確認策略裡有 oss:PutObject / oss:DeleteObject,再在臨時目錄裡做一次上傳 / 下載 / 刪除 |
錯誤碼不在表裡時,把完整錯誤和 Request ID 一起記下來 —— 提工單時要用。