EmDash 运行在 Node.js 22.16 或更高版本上。本指南对单台服务器使用 SQLite 和本地存储。当多个实例需要同一个数据库时,使用 PostgreSQL 或 libSQL;当媒体必须独立于服务器磁盘存活时,使用 S3 兼容存储。
先决条件
- Node.js v22.16.0 或更高
- Node.js 主机提供商或 VPS
配置站点
为 Node.js 部署配置 EmDash:
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",
}),
}),
],
});
构建并运行
-
构建项目:
npm run build -
启动服务器:
node ./dist/server/entry.mjs在启动服务器之前,通过主机提供商的进程环境设置
EMDASH_ENCRYPTION_KEY和其他运行时凭证。独立 Node 入口不会自动加载.env。对于使用生成的.env文件的本地运行,请用node --env-file=.env ./dist/server/entry.mjs启动。
服务器默认运行在 http://localhost:4321。在默认的 auto 迁移模式下,第一次请求会应用待处理的核心迁移。全新数据库还会收到嵌入的 seed。Manage core database migrations 说明如何在恢复生产流量之前进行迁移。
计划任务
内置调度器仅在 Node.js 进程运行时运行。它处理计划发布、插件任务和一般维护。
在生产中至少持续运行一个 Node.js 进程。当每个进程都停止或休眠时,计划任务会暂停。
插件沙箱
市场插件和列在 sandboxed: [] 下的插件需要沙箱运行器。在 Node.js 上,运行器是 @emdash-cms/sandbox-workerd,它在 workerd 子进程中运行插件。Plugin Sandbox 涵盖安装、workerd 进程如何运行及其故障模式。
选择生产数据服务
当数据库保留在持久卷上、媒体迁移到 S3 兼容存储时,使用以下模式:
import emdash, { s3 } from "emdash/astro";
export default defineConfig({
integrations: [
emdash({
database: sqlite({ url: `file:${process.env.DATABASE_PATH}` }),
storage: s3(),
}),
],
});
Docker
添加 .dockerignore 以保持构建上下文较小:
node_modules
dist
.git
创建 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"]
seed 文件在构建时读取并内联到包中,因此无需复制到运行时镜像。迁移在部署后的第一次请求时运行;仅当数据库没有集合且设置尚未完成时才应用 seed——现有数据永远不会被覆盖。
构建镜像并运行容器:
docker build -t my-emdash-site .
docker run -p 4321:4321 -v emdash-data:/app/data my-emdash-site
Docker Compose 文件用命名卷管理同一容器:
services:
emdash:
build: .
ports:
- "4321:4321"
volumes:
- emdash-data:/app/data
restart: unless-stopped
volumes:
emdash-data:
在后台启动堆栈:
docker compose up -d
运行时环境
服务器启动时从进程环境读取数据库和存储凭证。以下变量支持上述配置:
插件设置加密
EMDASH_ENCRYPTION_KEY 加密声明为密钥的插件设置。格式错误的值会产生面向操作员的启动消息,在修复该值之前,插件密钥设置操作会失败。
生成有效值并将结果添加到服务器进程环境:
npx emdash secrets generate # add the result to your environment
该值由操作员提供,不存储在数据库中。将其保存在密钥管理器和单独的恢复备份中。轮换期间,先提供新密钥,并在逗号后保留较旧密钥,直到每个插件密钥都再次保存。EmDash 目前不报告哪些密钥 ID 仍在使用,因此请跟踪每个重新保存的凭证,并在移除旧密钥之前验证其集成。在没有被引用密钥的情况下恢复数据库会使相应设置不可读。
可选:稳定值覆盖
EmDash 自动生成预览 HMAC 密钥和评论者 IP 哈希 盐,并在首次使用时持久化到数据库。下面的环境变量 将它们固定为你控制的值——当单独的进程需要与主站点 共享密钥时很有用。
| 变量 | 描述 |
|---|---|
EMDASH_PREVIEW_SECRET | 自动生成的预览 HMAC 密钥的覆盖。 |
EMDASH_IP_SALT | 自动生成的评论者 IP 哈希盐的覆盖。 |
EMDASH_AUTH_SECRET | 可选。若设置,用作 IP 盐来源(除非也设置了 EMDASH_IP_SALT,后者优先),使已依赖它的安装保持评论者 IP 哈希稳定。新部署请保持未设置。 |
有关键钥格式、每个受支持的密钥以及轮换或丢失的影响,请参见 Secrets and key management。
数据库与存储
| 变量 | 描述 | 示例 |
|---|---|---|
DATABASE_PATH | SQLite 数据库路径 | /data/emdash.db |
HOST | 服务器主机 | 0.0.0.0 |
PORT | 服务器端口 | 4321 |
S3_ENDPOINT | S3 端点 URL | https://xxx.r2.cloudflarestorage.com |
S3_BUCKET | S3 存储桶名称 | my-media-bucket |
S3_ACCESS_KEY_ID | S3 访问密钥 | AKIA... |
S3_SECRET_ACCESS_KEY | S3 秘密密钥 | ... |
S3_REGION | S3 区域 | auto |
S3_PUBLIC_URL | 媒体的公开 URL | https://cdn.example.com |
持久存储
SQLite 需要持久磁盘存储。确保你的托管平台提供:
- 已挂载的卷或持久磁盘
- 对数据库目录的写访问
- 数据库文件的备份机制
同时备份 SQLite 文件和上传目录。在恢复期间替换其中任一者之前,先停止进程。参见 Backups。
健康检查
为负载均衡器添加健康检查端点:
export const GET = () => {
return new Response("OK", { status: 200 });
};
此端点证明 Node.js 进程可以提供 Astro 路由。它不证明数据库、存储后端、迁移状态或插件沙箱是健康的。在向新版本发送流量之前,请单独验证这些依赖。
发送流量前验证
启动新构建后,验证生产请求使用的相同运行时服务:
- 请求
/health和一个公开内容页。两者都必须返回成功响应。 - 从已构建的项目运行
npx emdash migrate --check。它必须报告所配置数据库没有待处理或未知迁移。 - 登录
/_emdash/admin,创建或编辑一次性草稿并发布。确认公开页面显示更改。 - 上传一次性媒体文件并打开返回的 URL。验证后删除该文件。
- 若站点使用沙箱插件,调用一个插件路由或 hook,并确认服务器日志没有 sandbox-unavailable 或
workerd启动错误。
在每个适用检查通过之前,将新实例保持在负载均衡器之外。