Déployer sur Node.js

Sur cette page

EmDash fonctionne sur Node.js 22.16 ou supérieur. Ce guide utilise SQLite et le stockage local pour un serveur. Utilisez PostgreSQL ou libSQL lorsque plusieurs instances ont besoin d’une même base de données, et un stockage compatible S3 lorsque les médias doivent survivre indépendamment du disque du serveur.

Prérequis

  • Node.js v22.16.0 ou supérieur
  • Un hébergeur Node.js ou un VPS

Configurer le site

Configurez EmDash pour le déploiement 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",
			}),
		}),
	],
});

Compiler et exécuter

  1. Compiler le projet :

    npm run build
  2. Démarrer le serveur :

    node ./dist/server/entry.mjs

Le serveur fonctionne sur http://localhost:4321 par défaut. Avec le mode de migration par défaut auto, la première requête applique les migrations core en attente. Une base de données vierge reçoit également le seed embarqué. Gérer les migrations de base de données core explique comment migrer avant de redémarrer le trafic de production.

Tâches planifiées

Le planificateur intégré ne fonctionne que pendant l’exécution d’un processus Node.js. Il gère les publications planifiées, les tâches de plugins et la maintenance générale.

Gardez au moins un processus Node.js en exécution continue en production. Les tâches planifiées se mettent en pause lorsque tous les processus s’arrêtent ou se mettent en veille.

Sandbox de plugins

Les plugins du marketplace et ceux listés sous sandboxed: [] nécessitent un exécuteur sandbox. Sur Node.js, l’exécuteur est @emdash-cms/sandbox-workerd, qui exécute les plugins dans un processus enfant workerd. Sandbox de plugins couvre l’installation, le fonctionnement du processus workerd et ses modes de défaillance.

Choisir les services de données de production

Utilisez le modèle suivant lorsque la base de données reste sur un volume persistant et que les médias sont déplacés vers un stockage compatible S3 :

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

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

Docker

Ajoutez un .dockerignore pour réduire le contexte de build :

node_modules
dist
.git

Créez 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"]

Le fichier seed est lu au moment du build et intégré dans le bundle, il n’a donc pas besoin d’être copié dans l’image de runtime. Les migrations s’exécutent à la première requête après un déploiement ; le seed ne s’applique que lorsque la base de données n’a pas de collections et que la configuration n’a pas été complétée — les données existantes ne sont jamais écrasées.

Compilez l’image et exécutez le conteneur :

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

Un fichier Docker Compose gère le même conteneur avec un volume nommé :

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

volumes:
  emdash-data:

Démarrez la pile en arrière-plan :

docker compose up -d

Environnement d’exécution

Lisez les identifiants de base de données et de stockage depuis l’environnement du processus au démarrage du serveur. Les variables suivantes supportent la configuration ci-dessus :

Validation de la clé de chiffrement

EMDASH_ENCRYPTION_KEY ne chiffre actuellement pas les secrets de plugins ni aucune autre donnée stockée. Si la variable est définie, EmDash vérifie son format au démarrage, mais les valeurs des secrets de plugins restent en clair dans la base de données.

Si vous définissez la variable, générez une valeur valide et ajoutez le résultat à votre environnement :

npx emdash secrets generate  # ajouter le résultat à votre environnement

La valeur est fournie par l’opérateur et n’est pas stockée dans la base de données. La perdre n’a pas d’impact sur la récupération de données car aucune donnée stockée n’en dépend. Traitez la base de données et ses sauvegardes comme sensibles car elles contiennent des secrets de plugins en clair.

Optionnel : surcharges de valeurs stables

EmDash génère automatiquement le secret HMAC de prévisualisation et le sel de hachage d’IP des commentateurs et les persiste dans la base de données lors de la première utilisation. Les variables d’environnement ci-dessous les fixent à une valeur que vous contrôlez — utile lorsqu’un processus séparé doit partager un secret avec votre site principal.

VariableDescription
EMDASH_PREVIEW_SECRETSurcharge du secret HMAC de prévisualisation généré automatiquement.
EMDASH_IP_SALTSurcharge du sel de hachage d’IP des commentateurs généré automatiquement.
EMDASH_AUTH_SECRETOptionnel. Si défini, utilisé comme source de sel d’IP (sauf si EMDASH_IP_SALT est également défini, qui a la priorité), gardant les hachages d’IP des commentateurs stables pour les installations qui en dépendent déjà. Ne pas définir pour un nouveau déploiement.

Voir Secrets et gestion des clés pour le format de clé, chaque secret supporté et les effets de la rotation ou de la perte.

Base de données et stockage

VariableDescriptionExemple
DATABASE_PATHChemin vers la base SQLite/data/emdash.db
HOSTHôte du serveur0.0.0.0
PORTPort du serveur4321
S3_ENDPOINTURL du point de terminaison S3https://xxx.r2.cloudflarestorage.com
S3_BUCKETNom du bucket S3my-media-bucket
S3_ACCESS_KEY_IDClé d’accès S3AKIA...
S3_SECRET_ACCESS_KEYClé secrète S3...
S3_REGIONRégion S3auto
S3_PUBLIC_URLURL publique pour les médiashttps://cdn.example.com

Stockage persistant

SQLite nécessite un stockage disque persistant. Assurez-vous que votre plateforme d’hébergement fournit :

  • Un volume monté ou un disque persistant
  • Un accès en écriture au répertoire de la base de données
  • Des mécanismes de sauvegarde pour le fichier de base de données

Sauvegardez à la fois le fichier SQLite et le répertoire de téléchargements. Arrêtez le processus avant de remplacer quoi que ce soit lors d’une récupération. Voir Sauvegardes.

Vérifications de santé

Ajoutez un point de terminaison de vérification de santé pour les répartiteurs de charge :

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

Ce point de terminaison prouve que le processus Node.js peut servir des routes Astro. Il ne prouve pas que la base de données, le backend de stockage, l’état de migration ou le sandbox de plugins soit sain. Vérifiez ces dépendances séparément avant d’envoyer du trafic vers une nouvelle version.

Vérifier avant d’envoyer du trafic

Après le démarrage d’un nouveau build, vérifiez les mêmes services d’exécution que les requêtes de production utilisent :

  1. Demandez /health et une page de contenu publique. Les deux doivent retourner une réponse réussie.
  2. Exécutez npx emdash migrate --check depuis le projet compilé. Il ne doit rapporter aucune migration en attente ou inconnue pour la base de données configurée.
  3. Connectez-vous à /_emdash/admin, créez ou modifiez un brouillon jetable et publiez-le. Confirmez que la page publique affiche le changement.
  4. Téléchargez un fichier média jetable et ouvrez son URL retournée. Supprimez le fichier après vérification.
  5. Si le site utilise des plugins sandboxés, invoquez une route ou un hook de plugin et confirmez que le journal du serveur n’a pas d’erreur sandbox-indisponible ou de démarrage workerd.

Gardez la nouvelle instance hors du répartiteur de charge jusqu’à ce que chaque vérification applicable réussisse.