把 Obsidian 附件搬到 Cloudflare R2
Obsidian vault 用 git 同步,附件丟在裡面久了 repo 就越來越肥。加上有些筆記引用了外部圖床的圖片,偶爾就看到圖掛掉,索性一次整理乾淨,把所有附件搬到 Cloudflare R2 自己管。
整體思路是:貼圖到 Obsidian → 自動上傳到 R2 → wikilink 改寫成公開 URL → git 不再追蹤圖片。
架構
Obsidian (Mac)
├─ 貼圖 → Image auto upload Plugin
│ ↓ HTTP POST
├─ PicList(Docker,跑在 NAS 或任一台機器)
│ ↓ S3 API
└─ Cloudflare R2 bucket
↓ Custom Domain
https://attachments.yourdomain.com/
用 PicList 當中繼的原因是它有 GUI 方便設定,又支援 S3 API,可以直接對接 R2。
一、設定 Cloudflare R2
- Dashboard → R2 → Create bucket(名稱自訂,例如
obsidian-attachments) - Bucket → Settings → Public access → Connect Custom Domain,綁上你的 subdomain(走 Cloudflare CDN,出站不收費)
- R2 → Manage API Tokens → Create API Token:
- 權限選 Object Read & Write,限定這個 bucket
- 記下
Access Key ID和Secret Access Key
Endpoint 格式:
https://<accountid>.r2.cloudflarestorage.com/<bucket-name>
注意 endpoint 後面要加 bucket 名稱,不然引用路徑會不對。
二、跑 PicList Docker
我把 PicList 部署在 NAS 上,這樣不用開著 Mac 也能上傳。任何能跑 Docker 的機器都可以。
docker-compose.yml
services:
piclist:
image: kuingsmile/piclist:latest
container_name: piclist
restart: always
ports:
- "36677:36677"
volumes:
- ./config:/root/.piclist
command: node /usr/local/bin/picgo-server -k ${PICLIST_SECRET_KEY}
PICLIST_SECRET_KEY 是你自訂的 API 金鑰,用來保護上傳 endpoint。
config/config.json
{
"picBed": {
"current": "aws-s3-plist",
"uploader": "aws-s3-plist",
"aws-s3-plist": {
"_configName": "R2",
"accessKeyID": "<R2_ACCESS_KEY_ID>",
"secretAccessKey": "<R2_SECRET_ACCESS_KEY>",
"bucketName": "obsidian-attachments",
"uploadPath": "attachments/{year}/{md5}.{extName}",
"region": null,
"endpoint": "https://<accountid>.r2.cloudflarestorage.com/<bucket-name>",
"proxy": null,
"urlPrefix": "https://attachments.yourdomain.com/",
"pathStyleAccess": true,
"rejectUnauthorized": true,
"acl": "public-read",
"disableBucketPrefixToURL": false
}
},
"picgoPlugins": {},
"settings": {
"server": {
"port": 36677,
"host": "0.0.0.0",
"enable": true
},
"autoCopy": false
}
}
urlPrefix 填你綁的 custom domain,圖片上傳後回傳的 URL 會用這個前綴。
測試連線
# 健康檢查
curl http://<piclist-host>:36677/heartbeat
# 上傳測試
curl -X POST "http://<piclist-host>:36677/upload?picbed=aws-s3-plist&configName=R2&key=<SECRET_KEY>" \
-H "Content-Type: application/json" \
-d '{"list":["https://www.google.com/favicon.ico"]}'
常見問題
| 症狀 | 原因 |
|---|---|
Upload failed, please check your network and config | endpoint 沒加 bucket 名稱,或 key 填錯 |
connection refused | container 沒跑起來或 port 沒映射 |
401 | secret key 不對 |
三、設定 Obsidian 插件
安裝社群插件 Image auto upload Plugin,設定如下:
| 選項 | 值 |
|---|---|
| Auto pasted upload | ✅ 開啟 |
| Default uploader | PicGo(app) |
| PicGo server upload route | http://<piclist-host>:36677/upload?key=<SECRET_KEY> |
| Remote server mode | ✅ 開啟 |
| Work on network | 關閉 |
Remote server mode 一定要開,因為 PicList 跑在另一台機器,讀不到 Mac 的本地路徑,開啟後插件會用 base64 傳圖片內容。
日後工作流
貼圖到 Obsidian 後,Image auto upload 會自動:
- 把圖透過 PicList 上傳到 R2
- 把 wikilink 改寫成 R2 公開 URL
git repo 從此不再追蹤圖片,附件大小和 R2 存取費用都會落在 Cloudflare 的免費額度內(目前 R2 10 GB 免費、每月 1000 萬次免費讀取)。
原始碼: https://gist.github.com/ParinLL/e5f7869a9abf80c6e79313c78ddd5b93#file-migrate-external-images-py https://gist.github.com/ParinLL/e5f7869a9abf80c6e79313c78ddd5b93#file-migrate-to-r2-py