I plugin sandboxed vengono eseguiti in un runtime isolato fornito da un runner sandbox. Le installazioni dal marketplace e dal registro vengono sempre eseguite in sandbox, così come i plugin elencati sotto sandboxed: [] nell’integrazione emdash(). I plugin elencati sotto plugins: [] vengono eseguiti nel processo del server e non utilizzano il runner.
Il runner dipende dalla piattaforma di deploy. Su Cloudflare Workers, ogni plugin viene eseguito come Dynamic Worker creato tramite il binding Worker Loader. Su Node.js, il server avvia workerd, il runtime Workers open-source, come processo figlio ed esegue ogni plugin come servizio al suo interno. L’opzione sandboxRunner di emdash() seleziona il runner. Senza di essa, i plugin sotto sandboxed: [] non vengono mai caricati, e un marketplace configurato fa fallire il build con “Marketplace requires sandboxRunner to be configured”.
La tabella seguente riassume ciò che ogni runner richiede e applica.
| Cloudflare Workers | Node.js | |
|---|---|---|
sandboxRunner | sandbox() da @emdash-cms/cloudflare | "@emdash-cms/sandbox-workerd/sandbox" |
| Requisiti | Piano Workers Paid, un binding worker_loaders, PluginBridge esportato dal punto di ingresso del Worker | Il pacchetto workerd |
| Accesso al DB | Il binding D1 DB, indipendente dall’adapter configurato | Il database configurato |
| Limiti applicati | Tempo CPU, subrequest, wall time | Wall time |
Cloudflare Workers
I Dynamic Workers sono disponibili nel piano Workers Paid. Il runner necessita del binding e dell’export del punto di ingresso mostrati sotto; i template *-cloudflare forniscono entrambi.
-
Aggiungete il binding Worker Loader a
wrangler.jsonc. Il runner lo legge con il nomeLOADER:{ "worker_loaders": [ { "binding": "LOADER", }, ], } -
Esportate
PluginBridgedal punto di ingresso del Worker e puntatemaina quel file.PluginBridgeè il punto di ingresso attraverso il quale i plugin sandboxed accedono a contenuti, media, storage ed email; il runner lo cerca nelle esportazioni del modulo di ingresso:import handler, { createScheduledHandler, PluginBridge } from "@emdash-cms/cloudflare/worker"; export { PluginBridge }; export default { ...handler, scheduled: createScheduledHandler(), } satisfies ExportedHandler;{ "main": "./src/worker.ts", } -
Selezionate il runner nell’integrazione
emdash():import { d1, r2, sandbox } from "@emdash-cms/cloudflare"; emdash({ database: d1({ binding: "DB" }), storage: r2({ binding: "MEDIA" }), sandboxRunner: sandbox(), });
Node.js
-
Installate il runner insieme a
workerd, che è una dipendenza peer:npm install @emdash-cms/sandbox-workerd workerdIl pacchetto
workerdinstalla il binario per la piattaforma corrente (Linux, macOS e Windows su x64; Linux e macOS su arm64) tramite una dipendenza opzionale. Installate con le dipendenze opzionali abilitate, sulla piattaforma dove il server viene eseguito. In un build Docker multi-stage, eseguite l’installazione in uno stage con la stessa piattaforma dello stage runtime. -
Selezionate il runner nell’integrazione
emdash():import { sqlite } from "emdash/db"; emdash({ database: sqlite({ url: "file:./data/emdash.db" }), sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox", }); -
Per lo sviluppo, installate
miniflarecome dipendenza di sviluppo:npm install -D miniflareQuando
NODE_ENVèdevelopment, cheastro devimposta, eminiflareè installato, il runner passa i plugin a Miniflare, che gestisce il proprio processoworkerd; la politica di crash sotto non si applica.astro previewimpostaNODE_ENVaproductionenode ./dist/server/entry.mjslo lascia non impostato; entrambi usanoworkerd.
Come funziona il processo workerd
EmDash avvia workerd durante l’inizializzazione alla prima richiesta al sito, una volta che i plugin sandboxed sono caricati, e attende fino a 10 secondi che i servizi dei plugin rispondano. L’installazione o l’aggiornamento di un plugin dall’admin lo riavvia. Tutto ciò che workerd scrive su stdout o stderr appare nell’output del server con il prefisso [emdash:workerd].
I servizi dei plugin ascoltano su 127.0.0.1, e il canale di ritorno verso il server è un socket di dominio Unix (una porta TCP 127.0.0.1 su Windows). Non è necessario aprire porte in ingresso.
Il processo figlio riceve solo PATH, HOME, TMPDIR, TMP, TEMP, LANG e LC_ALL dall’ambiente del server, quindi i segreti nell’ambiente del server rimangono fuori dal sandbox. Per passare più variabili, impostate EMDASH_WORKERD_PASSTHROUGH_ENV con un elenco di nomi di variabili separati da virgola.
Se workerd termina inaspettatamente, il runner registra [emdash:workerd] workerd exited with <reason> e lo riavvia alla prossima invocazione, con un ritardo che parte da 1 secondo e raddoppia fino a 30 secondi. Quando workerd crasha più di cinque volte in 60 secondi, il runner smette di riavviarlo e registra [emdash:workerd] workerd crashed 5 times in 60 seconds, giving up. Da quel momento, ogni hook e route di plugin sandboxed fallisce con Plugin sandbox unavailable for <plugin>: workerd is not running fino al riavvio del server. Un SIGTERM al server termina anche workerd.
Limiti delle risorse
Ogni runner applica lo stesso insieme di limiti per invocazione di plugin. I limiti sono fissi; l’integrazione emdash() non ha opzioni per modificarli.
| Limite | Valore | Cloudflare Workers | Node.js |
|---|---|---|---|
| Tempo CPU | 50 ms | Applicato dal Worker Loader; il plugin lancia quando raggiunge il limite | Non applicato |
| Subrequest | 10 | Applicato dal Worker Loader; il plugin lancia quando raggiunge il limite | Non applicato |
| Memoria | 128 MB | Non applicato per plugin; il tetto di memoria dell’isolato della piattaforma si applica | Non applicato |
| Wall time | 30 s | Applicato dal runner | Applicato dal runner |
Quando un hook o route supera il limite di wall-time, l’invocazione fallisce con Plugin <id> exceeded wall-time limit of 30000ms during hook:<name> (o route:<name>). Per un hook, EmDash registra il fallimento con il prefisso EmDash: Sandboxed plugin <id> e prosegue la richiesta senza il risultato di quel plugin. Una route di plugin che supera il limite fallisce per il suo chiamante.
Quando il runner non è disponibile
Un runner configurato può comunque non essere disponibile: su Cloudflare Workers quando manca il binding worker_loaders o l’export PluginBridge, su Node.js quando workerd non è installato o il suo binario non viene eseguito. EmDash registra quindi il seguente avviso all’avvio del runtime:
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.
I plugin sotto sandboxed: [] non vengono caricati, i plugin installati dal marketplace e dal registro non vengono eseguiti, e una nuova installazione dall’admin fallisce con il codice di errore SANDBOX_NOT_AVAILABLE. Il resto del sito non è interessato.
Eseguire plugin sandboxed nel processo
Impostate sandbox: false in emdash() per eseguire i plugin sotto sandboxed: [] e i plugin installati dal marketplace nel processo del server, senza isolamento né limiti. È un’opzione di debug che distingue un bug in un plugin da un bug nel sandbox. La seguente configurazione disattiva il sandbox su un sito Node.js:
emdash({
sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
sandbox: false,
});
Su Cloudflare Workers, il runtime rifiuta di avviarsi con sandbox: false is not supported in Cloudflare Workers.
Risoluzione dei problemi
Ogni voce è intestata dal messaggio come lo registra il server, o dal codice di errore restituito dall’admin.
”Plugin sandbox is configured but not available on this platform”
Su Cloudflare Workers, verificate entrambi i requisiti: wrangler.jsonc ha un binding worker_loaders chiamato LOADER, e main punta a un file che esporta PluginBridge. Il deploy del binding richiede il piano Workers Paid.
Su Node.js, eseguite il binario che il runner usa:
npx workerd --version
Se il comando fallisce, workerd manca da node_modules o il binario installato non viene eseguito su questa piattaforma. Reinstallate sulla piattaforma target con le dipendenze opzionali abilitate.
”workerd failed to start within 10 seconds”
Il processo figlio è stato avviato, ma i suoi servizi di plugin non hanno risposto entro 10 secondi. Le righe con prefisso [emdash:workerd] prima di questo messaggio contengono l’output di workerd stesso, inclusi errori di configurazione e avvio. Il runner riprova alla prossima invocazione.
”workerd crashed 5 times in 60 seconds, giving up”
Il runner ha smesso di riavviare workerd. Le righe [emdash:workerd] workerd exited with <reason> prima di questo messaggio indicano il codice di uscita o il segnale di ogni crash. Correggete la causa, poi riavviate il server.
SANDBOX_NOT_AVAILABLE durante l’installazione di un plugin
La richiesta di installazione dell’admin è stata rifiutata perché il runner manca o non è disponibile. Configurate il runner per la piattaforma, o correggete la causa dell’avviso di avvio sopra, e ridistribuite.