Implantar no Node.js

Nesta página

O EmDash roda no Node.js 22.16 ou posterior. Este guia usa SQLite e armazenamento local para um servidor. Use PostgreSQL ou libSQL quando várias instâncias precisarem de um banco, e armazenamento compatível com S3 quando a mídia precisar sobreviver independentemente do disco do servidor.

Pré-requisitos

  • Node.js v22.16.0 ou superior
  • Um provedor de hospedagem Node.js ou VPS

Configurar o site

Configure o EmDash para implantação no 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",
			}),
		}),
	],
});

Compilar e executar

  1. Compile o projeto:

    npm run build
  2. Inicie o servidor:

    node ./dist/server/entry.mjs

    Defina EMDASH_ENCRYPTION_KEY e outras credenciais de runtime pelo ambiente de processo do provedor de hospedagem antes de iniciar o servidor. A entrada Node standalone não carrega .env automaticamente. Para uma execução local que use o arquivo .env gerado, inicie com node --env-file=.env ./dist/server/entry.mjs.

O servidor roda em http://localhost:4321 por padrão. Com o modo de migração auto padrão, a primeira solicitação aplica as migrações core pendentes. Um banco novo também recebe o seed embutido. Manage core database migrations explica como migrar antes de retomar o tráfego de produção.

Tarefas agendadas

O agendador embutido roda somente enquanto um processo Node.js estiver em execução. Ele cuida de publicação agendada, tarefas de plugins e manutenção geral.

Mantenha pelo menos um processo Node.js em execução contínua em produção. Tarefas agendadas pausam quando todos os processos param ou dormem.

Sandbox de plugins

Plugins do marketplace e os listados sob sandboxed: [] precisam de um sandbox runner. No Node.js, o runner é @emdash-cms/sandbox-workerd, que executa plugins em um processo filho workerd. Plugin Sandbox cobre a instalação, como o processo workerd roda e seus modos de falha.

Escolher serviços de dados de produção

Use o seguinte padrão quando o banco permanecer em um volume persistente e a mídia for para armazenamento compatível com S3:

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

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

Docker

Adicione um .dockerignore para manter o contexto de build pequeno:

node_modules
dist
.git

Crie um 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"]

O arquivo seed é lido no build e embutido no bundle, portanto não precisa ser copiado para a imagem de runtime. As migrações rodam na primeira solicitação após um deploy; o seed só se aplica quando o banco não tem collections e a configuração não foi concluída — dados existentes nunca são sobrescritos.

Compile a imagem e execute o container:

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

Um arquivo Docker Compose gerencia o mesmo container com um volume nomeado:

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

volumes:
  emdash-data:

Inicie a stack em segundo plano:

docker compose up -d

Ambiente de runtime

Leia as credenciais de banco e armazenamento do ambiente do processo quando o servidor iniciar. As seguintes variáveis suportam a configuração acima:

Criptografia de configurações de plugins

EMDASH_ENCRYPTION_KEY criptografa configurações de plugins declaradas como secrets. Um valor malformado produz uma mensagem de inicialização voltada ao operador, e operações de configurações secretas de plugins falham até o valor ser corrigido.

Gere um valor válido e adicione o resultado ao ambiente do processo do servidor:

npx emdash secrets generate  # add the result to your environment

O valor é fornecido pelo operador e não é armazenado no banco. Mantenha-o em um gerenciador de secrets e em um backup de recuperação separado. Durante a rotação, forneça primeiro a nova chave e retenha chaves mais antigas após vírgulas até que cada secret de plugin tenha sido salvo novamente. O EmDash não reporta atualmente quais IDs de chave permanecem em uso, então acompanhe cada credencial resalva e verifique sua integração antes de remover uma chave antiga. Restaurar o banco sem uma chave referenciada deixa as configurações correspondentes ilegíveis.

Opcional: overrides de valores estáveis

O EmDash gera automaticamente o secret HMAC de preview e o salt de hash de IP do comentarista e os persiste no banco no primeiro uso. As variáveis de ambiente abaixo os fixam em um valor que você controla — útil quando um processo separado precisa compartilhar um secret com o site principal.

VariávelDescrição
EMDASH_PREVIEW_SECRETOverride do secret HMAC de preview gerado automaticamente.
EMDASH_IP_SALTOverride do salt de hash de IP do comentarista gerado automaticamente.
EMDASH_AUTH_SECRETOpcional. Se definido, usado como fonte do salt de IP (a menos que EMDASH_IP_SALT também esteja definido, o que tem precedência), mantendo estáveis os hashes de IP do comentarista para instalações que já dependem dele. Deixe indefinido para uma nova implantação.

Veja Secrets and key management para o formato da chave, cada secret suportado e os efeitos de rotação ou perda.

Banco de dados e armazenamento

VariávelDescriçãoExemplo
DATABASE_PATHCaminho para o banco SQLite/data/emdash.db
HOSTHost do servidor0.0.0.0
PORTPorta do servidor4321
S3_ENDPOINTURL do endpoint S3https://xxx.r2.cloudflarestorage.com
S3_BUCKETNome do bucket S3my-media-bucket
S3_ACCESS_KEY_IDChave de acesso S3AKIA...
S3_SECRET_ACCESS_KEYChave secreta S3...
S3_REGIONRegião S3auto
S3_PUBLIC_URLURL pública para mídiahttps://cdn.example.com

Armazenamento persistente

SQLite exige armazenamento em disco persistente. Garanta que sua plataforma de hospedagem forneça:

  • Um volume montado ou disco persistente
  • Acesso de escrita ao diretório do banco
  • Mecanismos de backup para o arquivo do banco

Faça backup do arquivo SQLite e do diretório de uploads. Pare o processo antes de substituir qualquer um durante a recuperação. Veja Backups.

Verificações de saúde

Adicione um endpoint de health check para balanceadores de carga:

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

Este endpoint prova que o processo Node.js pode servir rotas Astro. Não prova que o banco, o backend de armazenamento, o estado de migrações ou o sandbox de plugins estão saudáveis. Verifique essas dependências separadamente antes de enviar tráfego a um novo release.

Verificar antes de enviar tráfego

Após iniciar um novo build, verifique os mesmos serviços de runtime que as solicitações de produção usam:

  1. Solicite /health e uma página de conteúdo pública. Ambas devem retornar uma resposta bem-sucedida.
  2. Execute npx emdash migrate --check a partir do projeto compilado. Deve relatar nenhuma migração pendente ou desconhecida para o banco configurado.
  3. Entre em /_emdash/admin, crie ou edite um rascunho descartável e publique-o. Confirme que a página pública mostra a alteração.
  4. Envie um arquivo de mídia descartável e abra a URL retornada. Exclua o arquivo após verificar.
  5. Se o site usa plugins sandboxed, invoque uma rota ou hook de plugin e confirme que o log do servidor não tem erro sandbox-unavailable nem de inicialização do workerd.

Mantenha a nova instância fora do balanceador de carga até que cada verificação aplicável passe.