Auf Node.js bereitstellen

Auf dieser Seite

EmDash läuft auf Node.js 22.16 oder höher. Diese Anleitung verwendet SQLite mit lokalem oder S3-kompatiblem Speicher; libSQL und PostgreSQL funktionieren auf Node.js genauso — siehe Datenbankoptionen.

Voraussetzungen

  • Node.js v22.16.0 oder höher
  • Ein Node.js-Hosting-Anbieter oder VPS

Konfiguration

Konfigurieren Sie EmDash für Node.js-Deployment:

import { defineConfig } from "astro/config";
import node from "@astrojs/node";
import emdash, { local, s3 } from "emdash/astro";
import { sqlite } from "emdash/db";

export default defineConfig({
	output: "server",
	adapter: node({ mode: "standalone" }),
	integrations: [
		emdash({
			database: sqlite({ url: "file:./data/emdash.db" }),
			storage: local({
				directory: "./data/uploads",
				baseUrl: "/_emdash/api/media/file",
			}),
		}),
	],
});

Erstellen und Ausführen

  1. Projekt erstellen:

    npm run build
  2. Server starten:

    node ./dist/server/entry.mjs

Der Server läuft standardmäßig auf http://localhost:4321. Migrationen werden bei der ersten Anfrage angewendet. Wenn die Datenbank leer ist und das Setup nicht abgeschlossen wurde, wird Ihre Seed-Datei (oder der eingebaute Standard, wenn Sie keine haben) ebenfalls bei dieser ersten Anfrage angewendet.

Geplante Aufgaben

Der eingebaute Scheduler läuft nur, solange ein Node.js-Prozess ausgeführt wird. Er behandelt geplante Veröffentlichung, Plugin-Aufgaben und allgemeine Wartung.

Halten Sie mindestens einen Node.js-Prozess in der Produktion kontinuierlich am Laufen. Geplante Aufgaben pausieren, wenn alle Prozesse stoppen oder schlafen.

Plugin-Sandbox

Marketplace-Plugins und die unter sandboxed: [] aufgelisteten Plugins benötigen einen Sandbox-Runner. Auf Node.js ist der Runner @emdash-cms/sandbox-workerd, der Plugins in einem workerd-Kindprozess ausführt. Plugin-Sandbox behandelt die Installation, wie der workerd-Prozess läuft und seine Fehlermodi.

Produktionsspeicher

Für die Produktion verwenden Sie S3-kompatiblen Speicher anstelle des lokalen Dateisystems:

import emdash, { s3 } from "emdash/astro";

export default defineConfig({
	integrations: [
		emdash({
			database: sqlite({ url: `file:${process.env.DATABASE_PATH}` }),
			storage: s3({
				endpoint: process.env.S3_ENDPOINT,
				bucket: process.env.S3_BUCKET,
				accessKeyId: process.env.S3_ACCESS_KEY_ID,
				secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
				publicUrl: process.env.S3_PUBLIC_URL, // Optionale CDN-URL
			}),
		}),
	],
});

Docker

Fügen Sie eine .dockerignore hinzu, um den Build-Kontext klein zu halten:

node_modules
dist
.git

Erstellen Sie ein Dockerfile:

FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./

RUN mkdir -p data

ENV HOST=0.0.0.0
ENV PORT=4321

EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]

Die Seed-Datei wird zur Build-Zeit gelesen und in das Bundle eingebunden, muss also nicht in das Runtime-Image kopiert werden. Migrationen werden bei der ersten Anfrage nach einem Deploy ausgeführt; der Seed wird nur angewendet, wenn die Datenbank keine Collections hat und das Setup nicht abgeschlossen wurde — bestehende Daten werden nie überschrieben.

Erstellen Sie das Image und starten Sie den Container:

docker build -t my-emdash-site .
docker run -p 4321:4321 -v emdash-data:/app/data my-emdash-site

Eine Docker-Compose-Datei verwaltet denselben Container mit einem benannten Volume:

services:
  emdash:
    build: .
    ports:
      - "4321:4321"
    volumes:
      - emdash-data:/app/data
    restart: unless-stopped

volumes:
  emdash-data:

Starten Sie den Stack im Hintergrund:

docker compose up -d

Umgebungsvariablen

Empfohlen: Verschlüsselungsschlüssel

EMDASH_ENCRYPTION_KEY ist der Schlüssel zum Verschlüsseln von Plugin-Geheimnissen im Ruhezustand. Der Schlüssel wird beim Start validiert; die Plugin-Geheimnis-Verschlüsselung verwendet ihn sobald aktiviert. Setzen Sie ihn bei jedem Deployment, damit Geheimnisse ohne spätere Konfigurationsänderung geschützt sind.

Generieren Sie einen Schlüssel und fügen Sie das Ergebnis Ihrer Umgebung hinzu:

npx emdash secrets generate  # Ergebnis Ihrer Umgebung hinzufügen

Der Schlüssel wird von Ihnen bereitgestellt und nie in der Datenbank gespeichert; nur verschlüsselter Chiffretext wird gespeichert. Sichern Sie ihn an einem dauerhaften Ort (einem Passwort-Manager, KMS oder dem Geheimnis-Speicher Ihres Teams) — ihn zu verlieren bedeutet, jedes damit verschlüsselte Geheimnis zu verlieren.

Optional: Stabile-Wert-Overrides

EmDash generiert automatisch das Preview-HMAC-Geheimnis und den Kommentator-IP-Hash-Salt und speichert sie beim ersten Gebrauch in der Datenbank. Die folgenden Umgebungsvariablen fixieren sie auf einen von Ihnen kontrollierten Wert — nützlich wenn ein separater Prozess ein Geheimnis mit Ihrer Hauptseite teilen muss.

VariableBeschreibung
EMDASH_PREVIEW_SECRETOverride für das automatisch generierte Preview-HMAC-Geheimnis.
EMDASH_IP_SALTOverride für den automatisch generierten Kommentator-IP-Hash-Salt.
EMDASH_AUTH_SECRETOptional. Wenn gesetzt, als IP-Salt-Quelle verwendet (es sei denn EMDASH_IP_SALT ist auch gesetzt, das Vorrang hat), um Kommentator-IP-Hashes für Installationen stabil zu halten, die bereits darauf angewiesen sind. Für ein neues Deployment nicht gesetzt lassen.

Datenbank und Speicher

VariableBeschreibungBeispiel
DATABASE_PATHPfad zur SQLite-Datenbank/data/emdash.db
HOSTServer-Host0.0.0.0
PORTServer-Port4321
S3_ENDPOINTS3-Endpunkt-URLhttps://xxx.r2.cloudflarestorage.com
S3_BUCKETS3-Bucket-Namemy-media-bucket
S3_ACCESS_KEY_IDS3-ZugriffsschlüsselAKIA...
S3_SECRET_ACCESS_KEYS3-Geheimschlüssel...
S3_PUBLIC_URLÖffentliche URL für Medienhttps://cdn.example.com

Persistenter Speicher

SQLite erfordert persistenten Festplattenspeicher. Stellen Sie sicher, dass Ihre Hosting-Plattform bietet:

  • Ein eingehängtes Volume oder persistente Festplatte
  • Schreibzugriff auf das Datenbankverzeichnis
  • Backup-Mechanismen für die Datenbankdatei

Gesundheitsprüfungen

Fügen Sie einen Gesundheitsprüfungs-Endpunkt für Load Balancer hinzu:

export const GET = () => {
  return new Response("OK", { status: 200 });
};

Konfigurieren Sie Ihre Plattform, um /health für Liveness-Probes zu überprüfen.