Desplegar en Node.js

En esta página

EmDash se ejecuta en Node.js 22.16 o posterior. Esta guía usa SQLite y almacenamiento local para un servidor. Usa PostgreSQL o libSQL cuando varias instancias necesiten una base de datos, y almacenamiento compatible con S3 cuando los medios deban sobrevivir independientemente del disco del servidor.

Requisitos previos

  • Node.js v22.16.0 o superior
  • Un proveedor de hosting Node.js o VPS

Configurar el sitio

Configura EmDash para el despliegue en 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",
			}),
		}),
	],
});

Construir y ejecutar

  1. Construye el proyecto:

    npm run build
  2. Inicia el servidor:

    node ./dist/server/entry.mjs

    Establece EMDASH_ENCRYPTION_KEY y otras credenciales de runtime a través del entorno de proceso del proveedor de hosting antes de iniciar el servidor. La entrada Node standalone no carga .env automáticamente. Para una ejecución local que use el archivo .env generado, inícialo con node --env-file=.env ./dist/server/entry.mjs.

El servidor se ejecuta en http://localhost:4321 por defecto. Con el modo de migración auto predeterminado, la primera solicitud aplica las migraciones core pendientes. Una base de datos nueva también recibe el seed embebido. Manage core database migrations explica cómo migrar antes de reiniciar el tráfico de producción.

Tareas programadas

El programador integrado solo se ejecuta mientras un proceso Node.js está en marcha. Gestiona la publicación programada, las tareas de plugins y el mantenimiento general.

Mantén al menos un proceso Node.js en ejecución continua en producción. Las tareas programadas se pausan cuando todos los procesos se detienen o duermen.

Sandbox de plugins

Los plugins del marketplace y los listados bajo sandboxed: [] necesitan un sandbox runner. En Node.js, el runner es @emdash-cms/sandbox-workerd, que ejecuta plugins en un proceso hijo workerd. Plugin Sandbox cubre la instalación, cómo se ejecuta el proceso workerd y sus modos de fallo.

Elegir servicios de datos de producción

Usa el siguiente patrón cuando la base de datos permanezca en un volumen persistente y los medios se muevan a almacenamiento compatible con S3:

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

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

Docker

Añade un .dockerignore para mantener pequeño el contexto de 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"]

El archivo seed se lee en tiempo de build y se incrusta en el bundle, por lo que no necesita copiarse a la imagen de runtime. Las migraciones se ejecutan en la primera solicitud tras un deploy; el seed solo se aplica cuando la base de datos no tiene colecciones y la configuración no se ha completado — los datos existentes nunca se sobrescriben.

Construye la imagen y ejecuta el contenedor:

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

Un archivo Docker Compose gestiona el mismo contenedor con un volumen con nombre:

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

volumes:
  emdash-data:

Inicia el stack en segundo plano:

docker compose up -d

Entorno de runtime

Lee las credenciales de base de datos y almacenamiento del entorno del proceso cuando el servidor arranca. Las siguientes variables admiten la configuración anterior:

Cifrado de ajustes de plugins

EMDASH_ENCRYPTION_KEY cifra los ajustes de plugins declarados como secrets. Un valor malformado produce un mensaje de arranque orientado al operador, y las operaciones de ajustes secretos de plugins fallan hasta que se corrija el valor.

Genera un valor válido y añade el resultado al entorno del proceso del servidor:

npx emdash secrets generate  # add the result to your environment

El valor lo proporciona el operador y no se almacena en la base de datos. Guárdalo en un gestor de secrets y en una copia de recuperación separada. Durante la rotación, proporciona primero la nueva clave y retiene las claves antiguas tras comas hasta que cada secret de plugin se haya guardado de nuevo. EmDash no informa actualmente qué IDs de clave siguen en uso, así que rastrea cada credencial vuelva a guardarse y verifica su integración antes de eliminar una clave antigua. Restaurar la base de datos sin una clave referenciada deja ilegibles los ajustes correspondientes.

Opcional: overrides de valores estables

EmDash genera automáticamente el secreto HMAC de vista previa y la sal de hash de IP del comentarista y los persiste en la base de datos en el primer uso. Las variables de entorno siguientes los fijan a un valor que controlas — útil cuando un proceso separado necesita compartir un secreto con tu sitio principal.

VariableDescripción
EMDASH_PREVIEW_SECRETOverride del secreto HMAC de vista previa autogenerado.
EMDASH_IP_SALTOverride de la sal de hash de IP del comentarista autogenerada.
EMDASH_AUTH_SECRETOpcional. Si está definida, se usa como fuente de sal de IP (salvo que también esté EMDASH_IP_SALT, que tiene precedencia), manteniendo estables los hashes de IP del comentarista para instalaciones que ya dependen de ella. Déjala sin definir en un despliegue nuevo.

Consulta Secrets and key management para el formato de clave, cada secreto admitido y los efectos de la rotación o pérdida.

Base de datos y almacenamiento

VariableDescripciónEjemplo
DATABASE_PATHRuta a la base de datos SQLite/data/emdash.db
HOSTHost del servidor0.0.0.0
PORTPuerto del servidor4321
S3_ENDPOINTURL del endpoint S3https://xxx.r2.cloudflarestorage.com
S3_BUCKETNombre del bucket S3my-media-bucket
S3_ACCESS_KEY_IDClave de acceso S3AKIA...
S3_SECRET_ACCESS_KEYClave secreta S3...
S3_REGIONRegión S3auto
S3_PUBLIC_URLURL pública para medioshttps://cdn.example.com

Almacenamiento persistente

SQLite requiere almacenamiento en disco persistente. Asegúrate de que tu plataforma de hosting proporcione:

  • Un volumen montado o disco persistente
  • Acceso de escritura al directorio de la base de datos
  • Mecanismos de copia de seguridad para el archivo de la base de datos

Haz copia de seguridad tanto del archivo SQLite como del directorio de subidas. Detén el proceso antes de reemplazar cualquiera durante la recuperación. Consulta Backups.

Comprobaciones de salud

Añade un endpoint de health check para balanceadores de carga:

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

Este endpoint demuestra que el proceso Node.js puede servir rutas Astro. No demuestra que la base de datos, el backend de almacenamiento, el estado de migraciones o el sandbox de plugins estén sanos. Verifica esas dependencias por separado antes de enviar tráfico a un nuevo release.

Verificar antes de enviar tráfico

Tras iniciar un nuevo build, verifica los mismos servicios de runtime que usan las solicitudes de producción:

  1. Solicita /health y una página de contenido pública. Ambas deben devolver una respuesta correcta.
  2. Ejecuta npx emdash migrate --check desde el proyecto construido. Debe informar de que no hay migraciones pendientes o desconocidas para la base de datos configurada.
  3. Inicia sesión en /_emdash/admin, crea o edita un borrador desechable y publícalo. Confirma que la página pública muestra el cambio.
  4. Sube un archivo multimedia desechable y abre su URL devuelta. Elimina el archivo tras verificarlo.
  5. Si el sitio usa plugins sandboxed, invoca una ruta o hook de plugin y confirma que el log del servidor no tiene errores de sandbox-unavailable ni de arranque de workerd.

Mantén la nueva instancia fuera del balanceador de carga hasta que cada comprobación aplicable pase.