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
-
Compila il progetto:
npm run build -
Avvia il server:
node ./dist/server/entry.mjsImposta
EMDASH_ENCRYPTION_KEYe altre credenziali runtime tramite l’ambiente di processo del provider di hosting prima di avviare il server. L’entry Node standalone non carica.envautomaticamente. Per un’esecuzione locale che usa il file.envgenerato, avvialo connode --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.
| Variabile | Descrizione |
|---|---|
EMDASH_PREVIEW_SECRET | Override del secret HMAC di anteprima autogenerato. |
EMDASH_IP_SALT | Override del sale hash IP del commentatore autogenerato. |
EMDASH_AUTH_SECRET | Opzionale. 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
| Variabile | Descrizione | Esempio |
|---|---|---|
DATABASE_PATH | Percorso al database SQLite | /data/emdash.db |
HOST | Host del server | 0.0.0.0 |
PORT | Porta del server | 4321 |
S3_ENDPOINT | URL dell’endpoint S3 | https://xxx.r2.cloudflarestorage.com |
S3_BUCKET | Nome del bucket S3 | my-media-bucket |
S3_ACCESS_KEY_ID | Chiave di accesso S3 | AKIA... |
S3_SECRET_ACCESS_KEY | Chiave secret S3 | ... |
S3_REGION | Regione S3 | auto |
S3_PUBLIC_URL | URL pubblico per i media | https://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:
- Richiedi
/healthe una pagina di contenuto pubblica. Entrambe devono restituire una risposta di successo. - Esegui
npx emdash migrate --checkdal progetto compilato. Deve segnalare nessuna migrazione in sospeso o sconosciuta per il database configurato. - Accedi a
/_emdash/admin, crea o modifica una bozza usa e getta e pubblicala. Conferma che la pagina pubblica mostra la modifica. - Carica un file media usa e getta e apri l’URL restituito. Elimina il file dopo la verifica.
- 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.