沙箱外掛在沙箱執行器提供的隔離執行時中執行。Marketplace 和登錄檔安裝始終在沙箱中執行,emdash() 整合中 sandboxed: [] 下列出的外掛也是如此。plugins: [] 下列出的外掛在伺服器程序中執行,不使用執行器。
執行器取決於部署平台。在 Cloudflare Workers 上,每個外掛作為透過 Worker Loader 繫結建立的 Dynamic Worker 執行。在 Node.js 上,伺服器啟動 workerd(開源 Workers 執行時)作為子程序,並將每個外掛作為其中的服務執行。emdash() 的 sandboxRunner 選項選擇執行器。沒有它,sandboxed: [] 下的外掛永遠不會被載入,配置的 marketplace 會使建置失敗並顯示「Marketplace requires sandboxRunner to be configured」。
下表總結了每個執行器的需求和強制執行的內容。
| Cloudflare Workers | Node.js | |
|---|---|---|
sandboxRunner | @emdash-cms/cloudflare 的 sandbox() | "@emdash-cms/sandbox-workerd/sandbox" |
| 要求 | Workers 付費方案、worker_loaders 繫結、從 Worker 進入點匯出的 PluginBridge | workerd 套件 |
| 資料庫存取 | DB D1 繫結(與配置的適配器無關) | 配置的資料庫 |
| 強制限制 | CPU 時間、子請求、牆鐘時間 | 牆鐘時間 |
Cloudflare Workers
Dynamic Workers 在 Workers 付費方案 中可用。執行器需要以下繫結和進入點匯出;*-cloudflare 範本附帶了兩者。
-
將 Worker Loader 繫結新增到
wrangler.jsonc。執行器以LOADER名稱讀取它:{ "worker_loaders": [ { "binding": "LOADER", }, ], } -
從 Worker 進入點匯出
PluginBridge,並將main指向該檔案。PluginBridge是沙箱外掛存取內容、媒體、儲存和電子郵件的進入點;執行器在進入模組的匯出中查找它:import handler, { createScheduledHandler, PluginBridge } from "@emdash-cms/cloudflare/worker"; export { PluginBridge }; export default { ...handler, scheduled: createScheduledHandler(), } satisfies ExportedHandler;{ "main": "./src/worker.ts", } -
在
emdash()整合中選擇執行器:import { d1, r2, sandbox } from "@emdash-cms/cloudflare"; emdash({ database: d1({ binding: "DB" }), storage: r2({ binding: "MEDIA" }), sandboxRunner: sandbox(), });
Node.js
-
與作為對等相依性的
workerd一起安裝執行器:npm install @emdash-cms/sandbox-workerd workerdworkerd套件透過可選相依性為目前平台(x64 上的 Linux、macOS 和 Windows;arm64 上的 Linux 和 macOS)安裝二進位檔案。在伺服器執行的平台上啟用可選相依性進行安裝。在多階段 Docker 建置中,在與執行時階段相同平台的階段中執行安裝。 -
在
emdash()整合中選擇執行器:import { sqlite } from "emdash/db"; emdash({ database: sqlite({ url: "file:./data/emdash.db" }), sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox", }); -
對於開發,安裝
miniflare作為開發相依性:npm install -D miniflare當
NODE_ENV為development(astro dev設定)且miniflare已安裝時,執行器將外掛傳遞給 Miniflare,由 Miniflare 管理自己的workerd程序;以下當機策略不適用。astro preview將NODE_ENV設定為production,node ./dist/server/entry.mjs不設定;兩者都使用workerd。
workerd 程序如何執行
EmDash 在網站首次請求時的初始化期間啟動 workerd,在沙箱外掛載入後,等待最多 10 秒讓外掛服務應答。從管理後台安裝或更新外掛會重新啟動它。workerd 寫入 stdout 或 stderr 的所有內容都以 [emdash:workerd] 前綴出現在伺服器輸出中。
外掛服務在 127.0.0.1 上監聽,返回伺服器的通道是 Unix 網域通訊端(Windows 上是 127.0.0.1 TCP 連接埠)。無需開啟入站連接埠。
子程序僅從伺服器環境接收 PATH、HOME、TMPDIR、TMP、TEMP、LANG 和 LC_ALL,因此伺服器環境中的密鑰不會進入沙箱。要傳遞更多變數,將 EMDASH_WORKERD_PASSTHROUGH_ENV 設定為逗號分隔的變數名稱列表。
如果 workerd 意外退出,執行器記錄 [emdash:workerd] workerd exited with <reason> 並在下次呼叫時重新啟動,延遲從 1 秒開始,翻倍至 30 秒。當 workerd 在 60 秒內當機超過五次時,執行器停止重啟並記錄 [emdash:workerd] workerd crashed 5 times in 60 seconds, giving up。此後,所有沙箱外掛鉤子和路由都會失敗並顯示 Plugin sandbox unavailable for <plugin>: workerd is not running,直到伺服器重啟。向伺服器傳送 SIGTERM 也會終止 workerd。
資源限制
每個執行器對每次外掛呼叫套用相同的限制集。限制是固定的;emdash() 整合沒有相關選項。
| 限制 | 值 | Cloudflare Workers | Node.js |
|---|---|---|---|
| CPU 時間 | 50 ms | 由 Worker Loader 強制;外掛達到限制時拋出 | 未強制 |
| 子請求 | 10 | 由 Worker Loader 強制;外掛達到限制時拋出 | 未強制 |
| 記憶體 | 128 MB | 不按外掛強制;平台的隔離區記憶體上限適用 | 未強制 |
| 牆鐘時間 | 30 s | 由執行器強制 | 由執行器強制 |
當鉤子或路由超過牆鐘時間限制時,呼叫失敗並顯示 Plugin <id> exceeded wall-time limit of 30000ms during hook:<name>(或 route:<name>)。對於鉤子,EmDash 以 EmDash: Sandboxed plugin <id> 前綴記錄失敗,並在沒有該外掛結果的情況下繼續處理請求。超過限制的外掛路由對其呼叫者失敗。
當執行器不可用時
配置的執行器仍可能不可用:在 Cloudflare Workers 上缺少 worker_loaders 繫結或 PluginBridge 匯出時,在 Node.js 上 workerd 未安裝或其二進位檔案無法執行時。EmDash 在執行時啟動時記錄以下警告:
EmDash: Plugin sandbox is configured but not available on this platform. Sandboxed plugins will not be loaded. If using @emdash-cms/sandbox-workerd/sandbox, ensure workerd is installed.
sandboxed: [] 下的外掛不會被載入,已安裝的 marketplace 和登錄檔外掛不會執行,從管理後台進行的新安裝會失敗並顯示錯誤碼 SANDBOX_NOT_AVAILABLE。網站的其餘部分不受影響。
在程序內執行沙箱外掛
在 emdash() 中設定 sandbox: false 以在沒有隔離或限制的情況下在伺服器程序中執行 sandboxed: [] 下的外掛和已安裝的 marketplace 外掛。這是一個除錯選項,用於區分外掛中的錯誤和沙箱中的錯誤。以下配置在 Node.js 網站上關閉沙箱:
emdash({
sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
sandbox: false,
});
在 Cloudflare Workers 上,執行時拒絕以 sandbox: false is not supported in Cloudflare Workers 啟動。
疑難排解
每個條目以伺服器記錄的訊息或管理後台傳回的錯誤碼為標題。
“Plugin sandbox is configured but not available on this platform”
在 Cloudflare Workers 上,檢查兩個要求:wrangler.jsonc 有一個名為 LOADER 的 worker_loaders 繫結,main 指向匯出 PluginBridge 的檔案。部署繫結需要 Workers 付費方案。
在 Node.js 上,執行執行器使用的二進位檔案:
npx workerd --version
如果命令失敗,workerd 在 node_modules 中缺失或安裝的二進位檔案無法在此平台上執行。在目標平台上啟用可選相依性重新安裝。
“workerd failed to start within 10 seconds”
子程序已啟動,但其外掛服務未在 10 秒內應答。此訊息之前的 [emdash:workerd] 前綴行包含 workerd 本身的輸出,包括配置和啟動錯誤。執行器將在下次呼叫時重試。
“workerd crashed 5 times in 60 seconds, giving up”
執行器已停止重啟 workerd。此訊息之前的 [emdash:workerd] workerd exited with <reason> 行指出每次當機的退出碼或訊號。修復原因,然後重啟伺服器。
安裝外掛時出現 SANDBOX_NOT_AVAILABLE
由於執行器缺失或不可用,管理後台的安裝請求被拒絕。為平台配置執行器,或修復上述啟動警告的原因,然後重新部署。