Distribuire su Node.js

In questa pagina

EmDash gira su Node.js 22.16 o successivo. Questa guida usa SQLite e archiviazione locale per un server. Usa PostgreSQL o libSQL quando più istanze hanno bisogno di un database, e archiviazione compatibile S3 quando i media devono sopravvivere indipendentemente dal disco del server.

Prerequisiti

  • Node.js v22.16.0 o superiore
  • Un provider di hosting Node.js o un VPS

Configurare il sito

Configura EmDash per la distribuzione su Node.js:

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",
			}),
		}),
	],
});

Compilare e avviare

  1. Compila il progetto:

    npm run build
  2. Avvia il server:

    node ./dist/server/entry.mjs

    Imposta EMDASH_ENCRYPTION_KEY e altre credenziali runtime tramite l’ambiente di processo del provider di hosting prima di avviare il server. L’entry Node standalone non carica .env automaticamente. Per un’esecuzione locale che usa il file .env generato, avvialo con node --env-file=.env ./dist/server/entry.mjs.

Il server gira su http://localhost:4321 per impostazione predefinita. Con la modalità di migrazione auto predefinita, la prima richiesta applica le migrazioni core in sospeso. Un database nuovo riceve anche il seed incorporato. Manage core database migrations spiega come migrare prima di ripristinare il traffico di produzione.

Attività pianificate

Lo scheduler integrato gira solo mentre un processo Node.js è in esecuzione. Gestisce la pubblicazione pianificata, le attività dei plugin e la manutenzione generale.

Mantieni almeno un processo Node.js in esecuzione continua in produzione. Le attività pianificate si mettono in pausa quando ogni processo si ferma o va in sleep.

Sandbox dei plugin

I plugin del marketplace e quelli elencati sotto sandboxed: [] richiedono un sandbox runner. Su Node.js, il runner è @emdash-cms/sandbox-workerd, che esegue i plugin in un processo figlio workerd. Plugin Sandbox copre l’installazione, come gira il processo workerd e i suoi modi di guasto.

Scegliere i servizi dati di produzione

Usa il seguente schema quando il database resta su un volume persistente e i media si spostano su archiviazione compatibile S3:

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

export default defineConfig({
	integrations: [
			emdash({
				database: sqlite({ url: `file:${process.env.DATABASE_PATH}` }),
				storage: s3(),
		}),
	],
});

Docker

Aggiungi un .dockerignore per mantenere piccolo il contesto di build:

node_modules
dist
.git

Crea un 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"]

Il file seed viene letto in fase di build e incorporato nel bundle, quindi non deve essere copiato nell’immagine runtime. Le migrazioni vengono eseguite alla prima richiesta dopo un deploy; il seed si applica solo quando il database non ha collection e il setup non è stato completato — i dati esistenti non vengono mai sovrascritti.

Compila l’immagine e avvia il container:

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

Un file Docker Compose gestisce lo stesso container con un volume nominato:

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

volumes:
  emdash-data:

Avvia lo stack in background:

docker compose up -d

Ambiente runtime

Leggi le credenziali di database e archiviazione dall’ambiente del processo all’avvio del server. Le seguenti variabili supportano la configurazione sopra:

Crittografia delle impostazioni dei plugin

EMDASH_ENCRYPTION_KEY crittografa le impostazioni dei plugin dichiarate come secret. Un valore malformato produce un messaggio di avvio rivolto all’operatore, e le operazioni sulle impostazioni secret dei plugin falliscono finché il valore non viene corretto.

Genera un valore valido e aggiungi il risultato all’ambiente del processo del server:

npx emdash secrets generate  # add the result to your environment

Il valore è fornito dall’operatore e non viene memorizzato nel database. Conservalo in un secret manager e in un backup di recupero separato. Durante la rotazione, fornisci prima la nuova chiave e mantieni le chiavi più vecchie dopo le virgole finché ogni secret del plugin non è stato salvato di nuovo. EmDash non segnala attualmente quali ID chiave restano in uso, quindi traccia ogni credenziale risalvata e verifica la sua integrazione prima di rimuovere una chiave vecchia. Ripristinare il database senza una chiave referenziata lascia illeggibili le impostazioni corrispondenti.

Opzionale: override di valori stabili

EmDash genera automaticamente il secret HMAC di anteprima e il sale hash IP del commentatore e li persiste nel database al primo uso. Le variabili d’ambiente sotto li fissano a un valore che controlli — utile quando un processo separato deve condividere un secret con il sito principale.

VariabileDescrizione
EMDASH_PREVIEW_SECRETOverride del secret HMAC di anteprima autogenerato.
EMDASH_IP_SALTOverride del sale hash IP del commentatore autogenerato.
EMDASH_AUTH_SECRETOpzionale. Se impostato, usato come fonte del sale IP (a meno che non sia impostato anche EMDASH_IP_SALT, che ha precedenza), mantenendo stabili gli hash IP del commentatore per le installazioni che già vi fanno affidamento. Lasciarlo non impostato per una nuova distribuzione.

Vedi Secrets and key management per il formato della chiave, ogni secret supportato e gli effetti di rotazione o perdita.

Database e archiviazione

VariabileDescrizioneEsempio
DATABASE_PATHPercorso al database SQLite/data/emdash.db
HOSTHost del server0.0.0.0
PORTPorta del server4321
S3_ENDPOINTURL dell’endpoint S3https://xxx.r2.cloudflarestorage.com
S3_BUCKETNome del bucket S3my-media-bucket
S3_ACCESS_KEY_IDChiave di accesso S3AKIA...
S3_SECRET_ACCESS_KEYChiave secret S3...
S3_REGIONRegione S3auto
S3_PUBLIC_URLURL pubblico per i mediahttps://cdn.example.com

Archiviazione persistente

SQLite richiede archiviazione su disco persistente. Assicurati che la piattaforma di hosting fornisca:

  • Un volume montato o un disco persistente
  • Accesso in scrittura alla directory del database
  • Meccanismi di backup per il file del database

Fai il backup sia del file SQLite sia della directory degli upload. Ferma il processo prima di sostituire uno dei due durante il recupero. Vedi Backups.

Health check

Aggiungi un endpoint di health check per i bilanciatori di carico:

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

Questo endpoint dimostra che il processo Node.js può servire route Astro. Non dimostra che database, backend di archiviazione, stato delle migrazioni o sandbox dei plugin siano sani. Verifica quelle dipendenze separatamente prima di inviare traffico a un nuovo release.

Verificare prima di inviare traffico

Dopo aver avviato una nuova build, verifica gli stessi servizi runtime usati dalle richieste di produzione:

  1. Richiedi /health e una pagina di contenuto pubblica. Entrambe devono restituire una risposta di successo.
  2. Esegui npx emdash migrate --check dal progetto compilato. Deve segnalare nessuna migrazione in sospeso o sconosciuta per il database configurato.
  3. Accedi a /_emdash/admin, crea o modifica una bozza usa e getta e pubblicala. Conferma che la pagina pubblica mostra la modifica.
  4. Carica un file media usa e getta e apri l’URL restituito. Elimina il file dopo la verifica.
  5. Se il sito usa plugin sandboxed, invoca una route o un hook del plugin e conferma che il log del server non ha errori sandbox-unavailable o di avvio workerd.

Tieni la nuova istanza fuori dal bilanciatore di carico finché ogni controllo applicabile non passa.