Plugin-Sandbox konfigurieren

Auf dieser Seite

Sandboxed Plugins benötigen neben ihrer Plugin-Deklaration einen Plattform-Runner. Marketplace- und Registry-Installationen verwenden immer diesen Runner, ebenso wie Plugins, die unter sandboxed: [] aufgeführt sind. Native Plugins unter plugins: [] laufen im EmDash-Serverprozess und erhalten keine Sandbox-Isolation.

Der Runner hängt von der Deployment-Plattform ab. Auf Cloudflare Workers wird jedes Plugin als Dynamic Worker ausgeführt, der über das Worker Loader Binding erstellt wird. Unter Node.js startet der Server workerd, die Open-Source Workers-Runtime, als Kindprozess und führt jedes Plugin als Service darin aus. Die Option sandboxRunner von emdash() wählt den Runner aus und aktiviert den gehosteten Registry-Katalog. Ohne sie werden Plugins unter sandboxed: [] nicht geladen. Eine ausdrücklich konfigurierte Registry bleibt durchsuchbar, aber die Installation oder Aktualisierung eines Sandboxed Plugins schlägt mit SANDBOX_NOT_AVAILABLE fehl.

Die folgende Tabelle fasst zusammen, was jeder Runner benötigt und durchsetzt.

Cloudflare WorkersNode.js
sandboxRunnersandbox() von @emdash-cms/cloudflare"@emdash-cms/sandbox-workerd/sandbox"
AnforderungenWorkers Paid-Plan, ein worker_loaders Binding, PluginBridge-Export vom Worker-EinstiegspunktDas workerd-Paket
DatenbankzugriffDas DB D1 Binding, unabhängig vom konfigurierten AdapterDie konfigurierte Datenbank
Erzwungene LimitsCPU-Zeit, Subrequests, WandzeitWandzeit

Cloudflare Workers

Dynamic Workers sind im Workers Paid-Plan verfügbar. Die *-cloudflare-Templates enthalten den unten stehenden Einstiegspunkt-Export, lassen das Binding jedoch auskommentiert, sodass neue Projekte im Workers Free-Plan deployen, es sei denn, Sie aktivieren Sandboxed Plugins während des Scaffoldings.

  1. Aktivieren Sie das Worker Loader Binding in wrangler.jsonc. Der Runner liest es unter dem Namen LOADER und wählt die Cloudflare-Sandbox nur dann aus, wenn dieses Binding vorhanden ist:

    {
    	"worker_loaders": [
    		{
    			"binding": "LOADER",
    		},
    	],
    }

    Wenn die Wrangler-Konfiguration benannte Umgebungen verwendet, setzen Sie CLOUDFLARE_ENV während des Astro-Builds. Das Cloudflare Vite-Plugin und sandbox() lesen dann dieselbe Umgebung. Bindings werden nicht vererbt, fügen Sie also LOADER zu jeder benannten Umgebung hinzu, die Sandboxed Plugins ausführt.

  2. Exportieren Sie PluginBridge aus dem Worker-Einstiegspunkt und richten Sie main auf diese Datei. PluginBridge ist der Einstiegspunkt, über den Sandboxed Plugins auf Inhalte, Medien, Speicher und E-Mail zugreifen; der Runner sucht es in den Exporten des Einstiegsmoduls:

    import handler, { createScheduledHandler, PluginBridge } from "@emdash-cms/cloudflare/worker";
    
    export { PluginBridge };
    
    export default {
    	...handler,
    	scheduled: createScheduledHandler(),
    } satisfies ExportedHandler;
    {
    	"main": "./src/worker.ts",
    }
  3. Wählen Sie den Runner in der emdash()-Integration:

    import { d1, r2, sandbox } from "@emdash-cms/cloudflare";
    
    emdash({
    	database: d1({ binding: "DB" }),
    	storage: r2({ binding: "MEDIA" }),
    	sandboxRunner: sandbox(),
    });

Node.js

  1. Installieren Sie den Runner zusammen mit workerd, das eine Peer-Abhängigkeit ist:

    npm install @emdash-cms/sandbox-workerd workerd

    Das workerd-Paket installiert die Binärdatei für die aktuelle Plattform (Linux, macOS und Windows auf x64; Linux und macOS auf arm64) über eine optionale Abhängigkeit. Installieren Sie mit aktivierten optionalen Abhängigkeiten auf der Plattform, auf der der Server läuft. Führen Sie die Installation in einem Multi-Stage Docker Build in einer Stufe mit derselben Plattform wie die Runtime-Stufe durch.

  2. Wählen Sie den Runner in der emdash()-Integration:

    import { sqlite } from "emdash/db";
    
    emdash({
    	database: sqlite({ url: "file:./data/emdash.db" }),
    	sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
    });

Der Runner deklariert Miniflare als optionale Abhängigkeit. Paketmanager installieren es standardmäßig. Wenn NODE_ENV auf development steht, was astro dev setzt, übergibt der Runner die Plugins an Miniflare, das seinen eigenen workerd-Prozess verwaltet; die untenstehende Absturzrichtlinie gilt nicht. Wenn optionale Abhängigkeiten ausgelassen wurden, verwendet der Runner stattdessen workerd. astro preview setzt NODE_ENV auf production und node ./dist/server/entry.mjs lässt es ungesetzt; beide verwenden workerd.

Wie der workerd-Prozess läuft

EmDash startet workerd während der Initialisierung bei der ersten Anfrage an die Website, sobald die Sandboxed Plugins geladen sind, und wartet bis zu 10 Sekunden, bis die Plugin-Services antworten. Das Installieren oder Aktualisieren eines Plugins über den Admin startet ihn neu. Alles, was workerd nach stdout oder stderr schreibt, erscheint in der Serverausgabe mit dem Präfix [emdash:workerd].

Plugin-Services lauschen auf 127.0.0.1, und der Kanal zurück zum Server ist ein Unix Domain Socket (ein 127.0.0.1 TCP-Port unter Windows). Es muss kein eingehender Port geöffnet werden.

Der Kindprozess erhält nur PATH, HOME, TMPDIR, TMP, TEMP, LANG und LC_ALL aus der Serverumgebung, sodass Geheimnisse in der Serverumgebung nicht in die Sandbox gelangen. Um mehr Variablen weiterzugeben, setzen Sie EMDASH_WORKERD_PASSTHROUGH_ENV auf eine kommagetrennte Liste von Variablennamen.

Wenn workerd unerwartet beendet wird, protokolliert der Runner [emdash:workerd] workerd exited with <reason> und startet ihn bei der nächsten Aufrufung neu, mit einer Verzögerung, die bei 1 Sekunde beginnt und sich bis auf 30 Sekunden verdoppelt. Wenn workerd innerhalb von 60 Sekunden mehr als fünfmal abstürzt, stoppt der Runner den Neustart und protokolliert [emdash:workerd] workerd crashed 5 times in 60 seconds, giving up. Von da an schlägt jeder Sandboxed Plugin Hook und jede Route fehl mit Plugin sandbox unavailable for <plugin>: workerd crashed 5 times in 60 seconds and the runner stopped retrying; restart the server. Ein Neustart des Servers startet workerd erneut, ebenso wie das Installieren oder Aktualisieren eines Plugins über den Admin. Ein SIGTERM an den Server beendet workerd mit.

Ressourcenlimits

Jeder Runner wendet denselben Satz von Limits pro Plugin-Aufruf an. Die Limits sind fest; die emdash()-Integration hat keine Option dafür.

LimitWertCloudflare WorkersNode.js
CPU-Zeit50 msVom Worker Loader erzwungen; das Plugin wirft einen Fehler beim ErreichenNicht erzwungen
Subrequests10Vom Worker Loader erzwungen; das Plugin wirft einen Fehler beim ErreichenNicht erzwungen
Speicher128 MBNicht pro Plugin erzwungen; die Isolate-Speichergrenze der Plattform giltNicht erzwungen
Wandzeit30 sVom Runner erzwungenVom Runner erzwungen

Wenn ein Hook oder eine Route das Wandzeit-Limit überschreitet, schlägt der Aufruf fehl mit Plugin <id> exceeded wall-time limit of 30000ms during hook:<name> (oder route:<name>). Bei einem Hook protokolliert EmDash den Fehler mit dem Präfix EmDash: Sandboxed plugin <id> und setzt die Anfrage ohne das Ergebnis dieses Plugins fort. Eine Plugin-Route, die das Limit überschreitet, schlägt für den Aufrufer fehl.

Wenn der Runner nicht verfügbar ist

Auf Cloudflare Workers prüft sandbox() zur Build-Zeit wrangler.jsonc. Ohne ein worker_loaders Binding namens LOADER lässt es den Runner ungesetzt und protokolliert die folgende Warnung:

[emdash] Sandboxed plugins are disabled because wrangler.jsonc has no LOADER Worker Loader binding. Worker Loader requires a Workers paid plan.

Ein ausgewählter Runner kann zur Laufzeit trotzdem nicht verfügbar sein: auf Cloudflare Workers, wenn das deployed LOADER Binding oder der PluginBridge-Export fehlt, und unter Node.js, wenn workerd nicht installiert ist oder seine Binärdatei nicht ausgeführt werden kann. EmDash protokolliert dann eine Warnung mit der Ursache, die der Runner nach dem Doppelpunkt meldet. Die folgende Warnung wird auf Cloudflare Workers protokolliert, wenn das Binding fehlt:

EmDash: Plugin sandbox is configured but not available on this platform: the worker has no worker_loaders binding named LOADER. Sandboxed plugins will not be loaded.

Plugins unter sandboxed: [] werden nicht geladen, installierte Marketplace- und Registry-Plugins werden nicht ausgeführt, und eine neue Installation über den Admin schlägt mit dem Fehlercode SANDBOX_NOT_AVAILABLE fehl. Der Rest der Website ist nicht betroffen.

Sandboxed Plugins im Prozess ausführen

Setzen Sie sandbox: false in emdash(), um die Plugins unter sandboxed: [] und installierte Marketplace-Plugins im Serverprozess auszuführen, ohne Isolation oder Limits. Es ist eine Debug-Option, die einen Fehler in einem Plugin von einem Fehler in der Sandbox unterscheidet. Die folgende Konfiguration schaltet die Sandbox auf einer Node.js-Website aus:

emdash({
	sandboxRunner: "@emdash-cms/sandbox-workerd/sandbox",
	sandbox: false,
});

Auf Cloudflare Workers weigert sich die Runtime mit sandbox: false is not supported in Cloudflare Workers zu starten.

Fehlerbehebung

Jeder Eintrag wird durch die Nachricht überschrieben, wie der Server sie protokolliert, oder durch den Fehlercode, den der Admin zurückgibt.

„[emdash] Sandboxed plugins are disabled because wrangler.jsonc has no LOADER Worker Loader binding”

Der Cloudflare-Adapter hat keinen Sandbox-Runner ausgewählt, da die Build-Zeit Wrangler-Konfiguration kein worker_loaders Binding namens LOADER hat. Dies ist die erwartete Konfiguration im Workers Free-Plan. Bei einem Workers Paid-Plan aktivieren Sie das Binding in wrangler.jsonc und bauen die Website neu.

„Plugin sandbox is configured but not available on this platform”

Der Text nach dem Doppelpunkt nennt die Ursache. Auf Cloudflare Workers bedeutet the worker has no worker_loaders binding named LOADER, dass wrangler.jsonc ein worker_loaders Binding namens LOADER benötigt, und the worker entrypoint does not export PluginBridge bedeutet, dass die Datei, auf die main zeigt, PluginBridge exportieren muss. Das Deployen des Bindings erfordert den Workers Paid-Plan.

Unter Node.js bedeutet workerd is missing or its binary does not run on this platform, dass der Runner workerd nicht ausführen konnte. Führen Sie die installierte Binärdatei direkt aus, damit die Prüfung kein fehlendes Paket herunterladen kann:

./node_modules/.bin/workerd --version

Unter Windows führen Sie node_modules\\.bin\\workerd.cmd --version aus. Wenn der Befehl fehlschlägt, fehlt workerd in node_modules oder die installierte Binärdatei läuft nicht auf dieser Plattform. Installieren Sie auf der Zielplattform mit aktivierten optionalen Abhängigkeiten neu.

„workerd failed to start within 10 seconds”

Der Kindprozess wurde gestartet, aber seine Plugin-Services haben nicht innerhalb von 10 Sekunden geantwortet. Die mit [emdash:workerd] präfixierten Zeilen vor dieser Nachricht enthalten die Ausgabe von workerd selbst, einschließlich Konfigurations- und Startfehler. Der Runner versucht es beim nächsten Aufruf erneut.

„workerd crashed 5 times in 60 seconds, giving up”

Der Runner hat den Neustart von workerd eingestellt. Die Zeilen [emdash:workerd] workerd exited with <reason> vor dieser Nachricht nennen den Exit-Code oder das Signal jedes Absturzes. Beheben Sie die Ursache und starten Sie dann den Server neu.

SANDBOX_NOT_AVAILABLE bei der Installation eines Plugins

Die Installationsanfrage des Admins wurde abgelehnt, weil der Runner fehlt oder nicht verfügbar ist. Wenn ein Runner konfiguriert ist, endet die Fehlermeldung mit derselben Ursache wie die obige Startwarnung. Konfigurieren Sie den Runner für die Plattform oder beheben Sie die Ursache und deployen Sie neu.