Deploy su Node.js

In questa pagina

EmDash funziona su Node.js 22.16 o successivo. Questa guida usa SQLite con storage locale o compatibile S3; libSQL e PostgreSQL funzionano allo stesso modo su Node.js — vedi Opzioni database.

Prerequisiti

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

Configurazione

Configura EmDash per il deployment 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",
			}),
		}),
	],
});

Compilazione ed esecuzione

  1. Compila il progetto:

    npm run build
  2. Avvia il server:

    node ./dist/server/entry.mjs

Il server gira su http://localhost:4321 per impostazione predefinita. Le migrazioni vengono applicate alla prima richiesta. Se il database è vuoto e il setup non è stato completato, il file seed (o quello predefinito integrato se non ne hai uno) viene applicato anch’esso alla prima richiesta.

Attività pianificate

Lo scheduler integrato funziona 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 tutti i processi si fermano o vanno in sleep.

Sandbox dei plugin

I plugin del marketplace e quelli elencati sotto sandboxed: [] necessitano di un runner sandbox. Su Node.js, il runner è @emdash-cms/sandbox-workerd, che esegue i plugin in un processo figlio workerd. Plugin Sandbox copre l’installazione, come funziona il processo workerd e le sue modalità di errore.

Storage di produzione

Per la produzione, usa storage compatibile S3 invece del filesystem locale:

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, // URL CDN opzionale
			}),
		}),
	],
});

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 al momento del build e incorporato nel bundle, quindi non ha bisogno di essere copiato nell’immagine di runtime. Le migrazioni vengono eseguite alla prima richiesta dopo un deploy; il seed viene applicato solo quando il database non ha collezioni e il setup non è stato completato — i dati esistenti non vengono mai sovrascritti.

Costruisci 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

Variabili d’ambiente

Consigliato: chiave di crittografia

EMDASH_ENCRYPTION_KEY è la chiave per crittografare i segreti dei plugin a riposo. La chiave viene validata all’avvio; la crittografia dei segreti dei plugin la usa una volta abilitata. Impostala ad ogni deployment così i segreti sono protetti senza un cambio di configurazione successivo.

Genera una chiave e aggiungi il risultato al tuo ambiente:

npx emdash secrets generate  # aggiungi il risultato al tuo ambiente

La chiave è fornita da te e mai memorizzata nel database; solo il testo cifrato viene memorizzato. Esegui il backup in un luogo durevole (un gestore di password, KMS o il vault dei segreti del tuo team) — perderla significa perdere ogni segreto crittografato con essa.

Opzionale: override di valore stabile

EmDash auto-genera il segreto HMAC di preview e il salt di hash IP del commentatore e li persiste nel database al primo utilizzo. Le variabili d’ambiente sottostanti li fissano a un valore che controlli — utile quando un processo separato deve condividere un segreto con il tuo sito principale.

VariabileDescrizione
EMDASH_PREVIEW_SECRETOverride per il segreto HMAC di preview auto-generato.
EMDASH_IP_SALTOverride per il salt di hash IP del commentatore auto-generato.
EMDASH_AUTH_SECRETOpzionale. Se impostato, usato come fonte del salt IP (a meno che non sia impostato anche EMDASH_IP_SALT, che ha precedenza), mantenendo gli hash IP stabili per le installazioni che già dipendono da esso. Lascialo non impostato per un nuovo deployment.

Database e storage

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 segreta S3...
S3_PUBLIC_URLURL pubblica per i mediahttps://cdn.example.com

Storage persistente

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

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

Controlli di salute

Aggiungi un endpoint di controllo salute per i bilanciatori di carico:

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

Configura la tua piattaforma per verificare /health per i probe di liveness.