Novu 3.19.0 配置参数详解

Novu 3.19.0 自托管环境变量体系详解:参数三层结构与生效链路实测、全量参数表、密钥/地址/Mongo/Redis/S3/功能开关逐类语义与生产配置模板。

NovuNovu即时通信2026/10/21

Novu 3.19.0 配置参数详解

目标:讲透 Novu 3.19.0 自托管部署的环境变量体系——参数从 .env 文件到容器生效的完整链路、全量参数清单、逐类语义与实测行为。全部结论在 Ubuntu 22.04 + Docker Compose 部署的 Novu 3.19.0 上实测(部署过程见 《Docker Compose 部署 Novu 指南》,组件定位见 《Novu 3.19.0 介绍与选型指南》)。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Novu 3.19.0(官方 Compose 发行形态:api/worker/ws/dashboard + mongo:8.0.17 + redis:alpine)
  • 宿主端口:API 8148、WS 8149、Dashboard 8150
  • 参数体系:官方 .env.example(2.2KB,5 组共 40+ 键)+ docker-compose.yml 中各服务 environment: 透传白名单
  • 版本核对命令:curl -sS http://192.168.146.128:8148/v1/health-check,实测返回 apiVersion: 3.19.0

二、前置条件

  • 已按部署指南完成 Novu 3.19.0 的 Compose 部署且 6 服务 healthy;
  • 能编辑部署目录下的 docker-compose.yml 与 .env;
  • 理解 Compose 变量注入规则:.env 是变量源,compose 文件里 ${VAR} 引用后写入服务 environment:,变量只在容器创建时注入,改完必须 docker compose up -d 重建才生效。

三、参数查看与修改方式

3.1 参数的三层结构

Novu 自托管没有配置文件,参数体系分三层(实测结构):

  1. .env 文件:所有变量的唯一取值来源(部署目录下,与 compose 文件同目录);
  2. compose 文件的 environment: 白名单:每个服务只接收显式列出的变量,.env 里写了但没被某服务引用的键对该服务无效;
  3. 运行时容器环境:最终生效值,用 printenv 核对。
# 核对 api 服务实际生效的关键变量(实测回显)
cd /opt/novu && docker compose exec api printenv | grep -E '^(NODE_ENV|IS_SELF_HOSTED|DISABLE_USER_REGISTRATION|PORT)='
NODE_ENV=local
PORT=3000
DISABLE_USER_REGISTRATION=true
IS_SELF_HOSTED=true
# worker 服务端口与队列库序号(实测回显)
docker compose exec worker printenv | grep -E '^(PORT|REDIS_DB_INDEX)='
REDIS_DB_INDEX=2
PORT=3004

3.2 修改参数并令其生效(实测全链路)

以官方提供的注册开关 DISABLE_USER_REGISTRATION 为例(它默认不在官方 compose 透传白名单里,需两步):

第 1 步,.env 追加变量:

cd /opt/novu && echo 'DISABLE_USER_REGISTRATION=true' >> .env

第 2 步,在 compose 文件 api 服务的 environment: 段追加透传行(与 IS_SELF_HOSTED: ${IS_SELF_HOSTED} 同级):

      IS_SELF_HOSTED: ${IS_SELF_HOSTED}
      DISABLE_USER_REGISTRATION: ${DISABLE_USER_REGISTRATION}

第 3 步,重建使配置注入(compose 自动识别 environment 变化的服务并 Recreate,实测输出节选):

docker compose up -d
 Container worker Healthy
 Container api Healthy

第 4 步,实测验证生效——新邮箱注册被拒:

curl -sS -o /dev/null -w 'HTTP %{http_code}\n' -X POST http://192.168.146.128:8148/v1/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"email":"newuser@quzuo.net","password":"Q1w2e3r4#","firstName":"New","lastName":"User"}'
curl -sS -X POST http://192.168.146.128:8148/v1/auth/register -H 'Content-Type: application/json' \
  -d '{"email":"newuser@quzuo.net","password":"Q1w2e3r4#","firstName":"New","lastName":"User"}'
HTTP 400
{"error":"Bad Request","statusCode":400,"timestamp":"2026-10-21T14:35:54.355Z","path":"/v1/auth/register","message":"Account creation is disabled","ctx":{"error":"Bad Request","statusCode":400}}

⚠️ 只改 .env 不改 compose 白名单、或改完不执行 up -d,参数都不生效。实测中「改了没反应」的问题几乎全部出在这两处。

3.3 布尔/开关类参数的取值习惯

开关统一用字符串布尔(true/false),compose 里引用时建议写成 ${VAR} 并在 .env 落 true/false 字面量;留空字符串与 false 在 Novu 的布尔解析中均按关闭处理,但显式写 false 更可读。

四、参数总览

按功能域分组的全量参数表(取值均为本环境实测值;「生效服务」列来自官方 compose 的 environment 白名单实测归纳):

功能域参数实测取值生效服务一句话语义
密钥JWT_SECRET64 位 hexapi, wsJWT 签名密钥(必填)
密钥STORE_ENCRYPTION_KEY32 字符 hexapi, worker渠道凭证加解密(必填,须恰好 32 字符)
密钥NOVU_SECRET_KEY64 位 hexapi环境根密钥/演示密钥来源(必填)
密钥SUBSCRIBER_WIDGET_JWT_EXPIRATION_TIME15dapi, worker收件箱订阅者 JWT 有效期
地址HOST_NAMEhttp://192.168.146.128(作为 .env 内插值根)对外主机名根
地址VITE_API_HOSTNAME${HOST_NAME}:8148dashboard前端拼 API 地址
地址VITE_WEBSOCKET_HOSTNAME${HOST_NAME}:8149dashboard前端拼 WS 地址
地址API_ROOT_URL${HOST_NAME}:8148api, workerAPI 对外根地址
地址FRONT_BASE_URL${HOST_NAME}:8150apidashboard 对外根地址
地址API_CONTEXT_PATH/WS_CONTEXT_PATH/WEBHOOK_CONTEXT_PATH/FRONT_BASE_CONTEXT_PATH/GLOBAL_CONTEXT_PATH空api, worker, ws, dashboard反向代理统一前缀
运行NODE_ENVlocal全部环境名(dev/test/production/ci/local)
运行IS_SELF_HOSTEDtrueapi自托管标识(必须 true)
运行IS_V2_ENABLEDtrueapiv2 API 体系开关
运行IS_API_IDEMPOTENCY_ENABLEDfalseapi触发幂等开关
运行IS_API_RATE_LIMITING_ENABLEDfalseapiAPI 限流开关
运行IS_NEW_MESSAGES_API_RESPONSE_ENABLEDtrueapimessages 接口新版响应结构
运行DISABLE_USER_REGISTRATIONtrue(实测开启)api禁止新用户注册
运行IS_EMAIL_INLINE_CSS_DISABLEDfalseworker邮件模板内联 CSS 开关
运行IS_USE_MERGED_DIGEST_ID_ENABLEDfalseworkerdigest 合并 ID 策略
MongoMONGO_URLmongodb://root:***@mongodb:27017/novu-db?authSource=adminapi, worker, ws连接串
MongoMONGO_INITDB_ROOT_USERNAME/PASSWORDroot / 演示口令mongodb初始管理员(仅空卷首启生效)
MongoMONGO_MAX_POOL_SIZE / MONGO_MIN_POOL_SIZE10 / 5api, worker, ws连接池上下限
MongoMONGO_AUTO_CREATE_INDEXEStrueapi首启自动建索引
RedisREDIS_HOST / REDIS_PORTredis / 6379api, worker, ws队列 Redis 地址
RedisREDIS_PASSWORD空api, worker, ws队列 Redis 密码
RedisREDIS_DB_INDEX2(compose 写死)api, workerBullMQ 队列所在 db
RedisREDIS_CACHE_SERVICE_HOST / PORT空 / 6379api, worker缓存实例(留空=缓存关闭)
RedisREDIS_SKIP_VERSION_CHECKfalseapi, worker经代理连 Redis 且无 INFO 命令时置 true
S3S3_LOCAL_STACK${HOST_NAME}:4566api, workerS3 兼容端点
S3S3_BUCKET_NAME / S3_REGIONnovu-local / us-east-1api, worker桶名/区域
S3AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYtest / testapi, workerS3 凭证
端口API_PORT3000api容器内 API 端口
端口WS_PORT3002ws容器内 WS 端口
端口WORKER_PORT3004(compose 默认)worker容器内 worker 端口
队列BROADCAST_QUEUE_CHUNK_SIZE100worker广播触发单批处理量
队列MULTICAST_QUEUE_CHUNK_SIZE100worker组播触发单批处理量
观测SENTRY_DSN空api, workerSentry 错误上报
观测NEW_RELIC_ENABLED / APP_NAME / LICENSE_KEYfalse / 占位 / 占位全部New Relic APM

⚠️ 官方 .env.example 中 MONGO_URL=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@mongodb:27017/novu-db?authSource=admin 使用了 .env 内嵌变量插值(Compose v2.24+ 支持)。改 Mongo 口令时只改 MONGO_INITDB_ROOT_PASSWORD 一处即可,不要把 MONGO_URL 写死,否则两处易失配导致 api 连库失败。

五、核心参数分类详解

5.1 密钥三件套(JWT_SECRET / STORE_ENCRYPTION_KEY / NOVU_SECRET_KEY)

  • JWT_SECRET:api 与 ws 共用,签发/校验登录态与收件箱 JWT。更换后所有已登录会话与已签发的组件 token 立即失效,用户需重新登录;
  • STORE_ENCRYPTION_KEY:用于加密各渠道 Provider 的接入凭证(如 SMTP 密码、Twilio token)。⚠️ 官方要求必须恰好 32 字符(openssl rand -hex 16 产出),长度不对时集成凭证无法加解密;该密钥更换后旧凭证将解密失败,需重新录入全部集成凭证;
  • NOVU_SECRET_KEY:环境根密钥。注册组织/环境后实际发起 API 调用时使用的是各环境的 ApiKey(见 API 使用篇),该根密钥是密钥体系的种子,务必妥善保存。

三键生成的实测命令与产物:

openssl rand -hex 32   # JWT_SECRET / NOVU_SECRET_KEY
openssl rand -hex 16   # STORE_ENCRYPTION_KEY(32 字符)
fade86f0d43ee13a31d528da5d1acfa41aeabddee5fa49e32b23ed2e54ad0105
b9c562f194b51df3054236f1a18de9af

5.2 地址与前端拼接(HOST_NAME 与 VITE_* 四件套)

HOST_NAME 是插值根;真正决定浏览器行为的是 dashboard 服务读到的 VITE_API_HOSTNAME/VITE_WEBSOCKET_HOSTNAME 与 api/worker 读到的 API_ROOT_URL、FRONT_BASE_URL。实测要点:

  • dashboard 是静态前端,构建时模板把这些值渲染进页面,值必须是浏览器可达地址(从办公室访问服务器就写服务器 IP/域名,不能写 localhost);
  • 宿主端口改过映射后(如 API 宿主 8148 → 容器 3000),这四项里的端口必须写宿主端口;
  • 改完执行 docker compose up -d 重建 dashboard/api/worker,浏览器强刷(Ctrl+Shift+R)后生效。

反向代理场景:GLOBAL_CONTEXT_PATH=novu + API_CONTEXT_PATH=api + WS_CONTEXT_PATH=ws 可让 API/WS 挂在 https://company.com/novu/api、https://company.com/novu/ws 路径下;dashboard 恒以自身端口/域名独立服务,不受这组变量控制。

5.3 MongoDB 组(连接串与初始化)

  • MONGO_URL:api/worker/ws 三服务共用,连接 novu-db 库;实测 worker 内 printenv 确认注入;
  • MONGO_INITDB_ROOT_USERNAME/PASSWORD:只在数据卷为空的首启生效(mongo 镜像初始化逻辑)。首启后改口令需进 mongo 改用户密码并同步 MONGO_URL,否则 api 报认证失败;
  • MONGO_MAX_POOL_SIZE=10/MONGO_MIN_POOL_SIZE=5:Node 驱动连接池,高并发触发场景按 CPU/内存上调(16GB 内存机器可到 20/10);
  • MONGO_AUTO_CREATE_INDEXES=true:首启自动建全部索引,生产保持 true(关闭需手工建索引,无运维收益)。

5.4 Redis 组(队列与缓存分离)

  • 队列固定走 REDIS_HOST:REDIS_PORT 的 db2(compose 写死 REDIS_DB_INDEX: 2,实测容器内生效值 2),承载 BullMQ 任务队列(trigger-handler/standard/process-subscriber/ws_socket_queue 等队列实测可见);
  • REDIS_CACHE_SERVICE_HOST/PORT 是可选的第二用途:给 Inbox feed 与未读数等热点查询做缓存。实测留空时缓存关闭;开启时官方建议小规模部署与队列共用同一 Redis 实例(填同值),大规模部署分离独立实例;
  • REDIS_SKIP_VERSION_CHECK=true 适用于经不支持 INFO 命令的代理连 Redis 的托管场景,常规直连保持 false。

5.5 S3 组(存储端点)

  • S3_LOCAL_STACK 默认指向 ${HOST_NAME}:4566,官方 compose 并未内置 S3/localstack 服务——该默认值在纯官方 compose 部署里指向一个不存在的端点,实测不影响 api 健康与 In-App 消息主链路;需要附件/大内容存储时自建 MinIO 等 S3 兼容服务后改此项;
  • AWS_ACCESS_KEY_ID=test/AWS_SECRET_ACCESS_KEY=test 是 localstack 习惯默认凭证,对接真实 S3/MinIO 时替换为真实凭证并补 S3_BUCKET_NAME(需预先创建桶)。

5.6 功能开关(IS_* 与 DISABLE_*)

  • IS_SELF_HOSTED=true:自托管必须保持,影响多处云服务逻辑分支;
  • IS_API_RATE_LIMITING_ENABLED:API 层限流开关,默认 false;生产建议 true(限流阈值由服务端内置策略控制);
  • IS_API_IDEMPOTENCY_ENABLED:触发接口幂等(相同 transactionId 去重),对触发源可能重试的业务建议 true;
  • IS_V2_ENABLED=true/IS_NEW_MESSAGES_API_RESPONSE_ENABLED=true:v3.19.0 默认开启的新 API 体系,保持默认即可;
  • DISABLE_USER_REGISTRATION=true:实测生效(第三章 3.2,HTTP 400 Account creation is disabled);注意它默认不在 compose 白名单,需按 3.2 两步接入。

5.7 队列批次(BROADCAST_QUEUE_CHUNK_SIZE / MULTICAST_QUEUE_CHUNK_SIZE)

worker 每次从队列取出的广播/组播批次大小(默认各 100)。广播触发(to 为 topic 或大批 subscriber)时批次过大会拉高单 job 内存,批次过小增加调度开销;默认值在 8GB 内存机器上无需调整,万级订阅者广播场景可降至 50 观察内存。

5.8 观测与上报(SENTRY_DSN / NEW_RELIC_*)

  • SENTRY_DSN 留空即不上报;自托管环境保持留空(错误看本地日志 docker compose logs);
  • NEW_RELIC_ENABLED=false 时其余 NEW_RELIC_* 无需配置;开启需提供 LICENSE_KEY,仅在已采购 New Relic 时使用;
  • 3.x 的 Trace/StepRun 深度观测依赖 ClickHouse(官方 compose 未含),未部署 ClickHouse 时 worker 日志出现 Failed to create ClickHouse table,属预期噪音,不影响通知主链路(实测触发与消息落地均正常)。

六、生产配置模板

按部署规模给出两档推荐配置(差异项列出,其余保持官方默认):

小规模(≤1 万订阅者/日,8GB 内存单机,官方基线形态):

NODE_ENV=production
MONGO_MAX_POOL_SIZE=10
MONGO_MIN_POOL_SIZE=5
REDIS_CACHE_SERVICE_HOST=redis        # 与队列共用实例,开热点缓存
REDIS_CACHE_SERVICE_PORT=6379
IS_API_RATE_LIMITING_ENABLED=true
IS_API_IDEMPOTENCY_ENABLED=true
DISABLE_USER_REGISTRATION=true        # 建好管理账号后关闭公开注册
IS_SELF_HOSTED=true

适用场景:单业务线、In-App+Email 为主、无独立 SRE 团队的团队自用平台;MongoDB 与 Redis 与业务服务同机部署。

中规模(1 万-10 万订阅者/日,16GB+ 内存,MongoDB 独立实例 + 缓存独立实例):

NODE_ENV=production
MONGO_MAX_POOL_SIZE=20
MONGO_MIN_POOL_SIZE=10
MONGO_URL=mongodb://${MONGO_INITDB_ROOT_USERNAME}:${MONGO_INITDB_ROOT_PASSWORD}@<mongo-host>:27017/novu-db?authSource=admin
REDIS_HOST=<queue-redis-host>         # 队列 Redis 独立实例,开 AOF
REDIS_CACHE_SERVICE_HOST=<cache-redis-host>  # 缓存 Redis 独立实例
IS_API_RATE_LIMITING_ENABLED=true
IS_API_IDEMPOTENCY_ENABLED=true
DISABLE_USER_REGISTRATION=true
BROADCAST_QUEUE_CHUNK_SIZE=50         # 大广播场景下调批次防内存尖峰

适用场景:多业务线共用、含 SMS/Push 多渠道、需要附件存储(另配 MinIO/S3 并改 S3_* 五项)。两档均需按 5.1 完成三密钥自生成,演示口令一律替换。

七、常见问题(FAQ)

Q1:改了 .env 为什么不生效? 三个可能:没有执行 docker compose up -d 重建(变量只在容器创建时注入);该键不在目标服务的 compose environment: 白名单(如 DISABLE_USER_REGISTRATION,需按 3.2 加透传行);改了 MONGO_URL 但 MONGO_INITDB_ROOT_PASSWORD 没同步。用 docker compose exec <服务> printenv | grep <键> 看实际生效值定位。

Q2:STORE_ENCRYPTION_KEY 长度校验报错? 该键必须恰好 32 字符。用 openssl rand -hex 16 生成(32 个 hex 字符),不要用 hex 32(64 字符)。

Q3:把 REDIS_CACHE_SERVICE_HOST 填了值但 Inbox 查询没变快? 缓存默认关闭,填写后需重建 api/worker 生效;且缓存只覆盖 Inbox feed/未读数与触发链路 DAL 热点查询,低流量场景感知不明显。

Q4:Mongo 口令改动后 api 起不来? 首启后 Mongo 用户已固化在数据卷里。正确顺序:进 mongo 改用户密码 → 同步 .env 两处(MONGO_INITDB_ROOT_PASSWORD 与 MONGO_URL 若写死)→ docker compose up -d。若首启时就失配导致初始化失败,down -v 清卷重建(⚠️ 清卷丢数据)。

Q5:worker 日志大量 Failed to create ClickHouse table? 3.x 观测特性依赖 ClickHouse,官方 compose 未包含,报错不影响通知主链路,可忽略;需要 trace 时自建 ClickHouse 并补相关变量。

八、参考链接