Blossom 檔案伺服器

執行於獨立主機名稱上的媒體託管:內容定址上傳、本機或 S3 相容儲存,以及 kind-24242 認證。

概觀

nostrfy 可以作為 Blossom blob 伺服器:用戶端上傳以其 SHA-256 雜湊定址的檔案, 中繼將它們提供回去。與 REST API 一樣,它執行在同一連接埠上的專用主機名稱。

設定

toml
[blossom]
host = "media.example.com"          # required — enables the feature
storage = "local"                   # "local" or "s3"
local_path = "./data/images"        # local storage root
max_upload_bytes = 20971520         # 20 MiB
min_free_bytes = 33554432           # refuse uploads when the disk has less free space
restrict_uploads = false            # only allow-listed pubkeys may upload

# For S3 / Cloudflare R2:
s3_endpoint = "https://<account>.r2.cloudflarestorage.com"
s3_region = "auto"
s3_bucket = "nostr-media"
s3_access_key = "..."
s3_secret_key = "..."

在反向代理中將 media.example.com 指向同一連接埠,然後重新啟動。該主機上的 GET / 會傳回 Blossom 伺服器資訊文件。使用 storage = "s3" 時, 端點必須是 HTTPS,除非主機是回環位址(例如用於測試的本機 MinIO)。

儲存配置

兩種後端都使用 <npub1...> 階層,以檔案的 SHA-256 為鍵:

  • local — 檔案位於 <local_path>/<npub1...>/<sha256>
  • s3 / R2 — 設定的儲存桶中的物件 <npub1...>/<sha256>

Blob 位元組從不進入中繼資料庫 — LMDB 只保存 sha256 → 擁有者對應與上傳 允許清單。

端點

方法路徑認證說明
GET/—Blossom 伺服器資訊
GET / HEAD/<sha256>[.ext]—取得 / 探測 blob(位元組範圍,206)
PUT/uploadkind 24242 (t=upload, x=sha256, expiration)上傳 blob — 201 新建,200 已存在
HEAD/uploadkind 24242 (t=upload, x=sha256, expiration)BUD-06 預檢 — 上傳會被接受嗎?
PUT/mediakind 24242 (t=media, x=sha256, expiration)BUD-05 媒體上傳(原樣儲存)
HEAD/mediakind 24242 (t=media, x=sha256, expiration)BUD-05 預檢 — 上傳會被接受嗎?
GET/list/<pubkey>kind 24242 (t=list, expiration)由請求公鑰上傳的 blob(游標 + limit)
DELETE/<sha256>kind 24242 (t=delete, x=sha256, expiration)刪除 blob(僅上傳者)

安全說明

  • 使用者上傳的位元組以 X-Content-Type-Options: nosniff 提供。
  • HTML/SVG/XML/JavaScript 還會附加 Content-Disposition: attachment 與 沙箱 CSP,因此媒體來源不能用於儲存型 XSS。
  • 權杖接受規範中的 base64url(無填充)形式與帶填充的標準形式 (BUD-11)。
  • X-SHA-256 標頭會與實際位元組驗證 — 不符時傳回 409。
  • 檔案以 ETag、Cache-Control: immutable 與儲存的內容類型提供。
  • 被 NIP-86 banpubkey 封鎖的公鑰在每個端點上都會被拒絕。

範例

sh
# Server info
curl https://media.example.com/

# Upload (auth event from your Blossom client, e.g. via nak or the nostr-tools blossom helper)
curl -X PUT -H "Authorization: Nostr <auth>" -H "Content-Type: image/png" --data-binary @photo.png https://media.example.com/upload

# Fetch
curl https://media.example.com/<sha256>

# List your own uploads (auth event with t=list; the path pubkey must be yours)
curl -H "Authorization: Nostr <auth>" https://media.example.com/list/<pubkey-hex>

# Delete (auth event with t=delete and x=<sha256>)
curl -X DELETE -H "Authorization: Nostr <auth>" https://media.example.com/<sha256>

限制上傳

在 [blossom] 區段中設定 restrict_uploads = true:

toml
[blossom]
host = "media.example.com"
restrict_uploads = true

允許清單儲存在中繼資料庫(LMDB)中,用專用指令管理 — 無需重新啟動, 常駐程式會自動重載:

sh
nostrfy blossom allow npub1...          # allow a pubkey (npub1... or hex)
nostrfy blossom deny npub1...           # revoke a pubkey
nostrfy blossom list                    # show the list and restrict_uploads

未列入允許清單的公鑰上傳會被 403 拒絕。

備份與遷移

備份設定的 blob 儲存與 database.path,以保留完整的 清單與授權狀態。sha256 → 擁有者對應持久化在 LMDB 中,因此重新啟動是 瞬時的,無需記憶體索引或啟動掃描 — 查找直接從資料庫讀取對應。升級後的首次啟動會 自動執行一次性遷移,從舊 blob 重建對應;標記會跳過後續重新啟動。