Parin's Space
返回文章列表

把 Obsidian 附件搬到 Cloudflare R2

· 閱讀時間 2 分鐘

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

  1. Dashboard → R2 → Create bucket(名稱自訂,例如 obsidian-attachments
  2. Bucket → SettingsPublic accessConnect Custom Domain,綁上你的 subdomain(走 Cloudflare CDN,出站不收費)
  3. R2 → Manage API Tokens → Create API Token
    • 權限選 Object Read & Write,限定這個 bucket
    • 記下 Access Key IDSecret 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 configendpoint 沒加 bucket 名稱,或 key 填錯
connection refusedcontainer 沒跑起來或 port 沒映射
401secret key 不對

三、設定 Obsidian 插件

安裝社群插件 Image auto upload Plugin,設定如下:

選項
Auto pasted upload✅ 開啟
Default uploaderPicGo(app)
PicGo server upload routehttp://<piclist-host>:36677/upload?key=<SECRET_KEY>
Remote server mode開啟
Work on network關閉

Remote server mode 一定要開,因為 PicList 跑在另一台機器,讀不到 Mac 的本地路徑,開啟後插件會用 base64 傳圖片內容。


日後工作流

貼圖到 Obsidian 後,Image auto upload 會自動:

  1. 把圖透過 PicList 上傳到 R2
  2. 把 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

Template: https://gist.github.com/ParinLL/f3b281868b601c9cd3f59a1d167497cf#file-template-migrate-current-file-picturetor2-md