刘光辉
2 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# docker-compose / start-all.sh 环境变量模板
#
# ══ 用法 ══
#
#   任何环境(开发本机/测试服务器/交付):cp .env.example .env,按下面的【场景】改值。
#   compose 自动读仓库根 .env;start-all.sh 启动时会加载全部 KEY=VALUE。.env 不入库。
#
#   切客户库 = 手改 .env 的 4 个键(§1 坐标 2 个 + §2/§3 密码 2 个)。改完必须重启
#   (Druid 池在启动时定死,配置不热改),并先跑 ./docker/preflight.sh 防连错库:
#       容器栈:docker compose up -d --force-recreate
#       宿主栈:./start-all.sh stop && ./start-all.sh
#
#
# ══ 场景速查:数据库连哪 × 服务怎么跑,两维正交、自由组合 ══
#
#   ── 维度一:数据库坐标(只动 §1-§3 的 4 个键)────────────────────────────
#
#   | 数据库            | CUSTOMER_DB_HOST/PORT   | 两对 DB 密码(§2 §3)    |
#   |-------------------|-------------------------|--------------------------|
#   | 本机容器 PG(默认)| cx-postgres / 5432      | 默认值即可(出厂密码)    |
#   | 本机自装 PG       | 127.0.0.1 / 自装端口     | 自装库的真实密码          |
#
#   业务库 jnpf_init 与流程引擎库 jnpf_flow 都由这组坐标推导,必然同源(§3 红线)。
#
#   Redis 同样三档(§5 的 JNPF_REDIS_HOST/PORT/PASSWORD 三键,全不设 = 本机容器 cx-redis
#
#   ── 维度二:服务怎么跑 ──────────────────────────────────────────────────
#
#   | 跑法                       | 要求                                          |
#   |----------------------------|-----------------------------------------------|
#   | 全栈容器 docker compose up | .env 原样即用,无额外要求                      |
#   | 宿主 ./start-all.sh        | /etc/hosts 需下面 5 条 cx-*;cx-postgres 坐标 |
#   |(基础设施仍跑容器)         | 会自动翻译成宿主发布端口 127.0.0.1:5433        |
#
#       127.0.0.1 cx-infra cx-redis cx-flow-engine
#
#   ── redis 想用宿主自装的(不跑 Redis 容器)──────────────────────────────
#   同时支持宿主 ./start-all.sh 和 Docker 业务容器时,按 §5 分别设置宿主/容器坐标:
#   宿主 JVM 用 127.0.0.1,容器用 cx-infra(compose 已映射到 host-gateway)。
#   requirepass 必须与 §5 的 JNPF_REDIS_PASSWORD 相同。
#   ⚠️ 流程引擎 cx-flow-engine 没有自装形态,任何跑法都要起它的容器。
#   (RocketMQ 已于 2026-08-10 移除,事件总线改走 Redis pub/sub,见补丁 #10)
#
#
#   ── OnlyOffice 文档在线编辑 ─────────────────────────────────────────────
#   §6 一节,只有 ONLYOFFICE_JWT_SECRET 必填(缺了 compose 直接报错起不来),
#   其余 10 个键都有默认值 = 本机 compose 形态。交付环境务必换掉这个 secret:
#   回调端点匿名可达,它是唯一的安全边界。
 
 
# ════════════════════════════════════════════════════════════════════════════
# 1. 客户坐标(唯一开关:业务库 jnpf_init 与引擎库 jnpf_flow 都由它推导,必然同源)
# ════════════════════════════════════════════════════════════════════════════
# 本机 = compose 栈内的 cx-postgres。宿主 java -jar(start-all.sh)会自动把
# cx-postgres:5432 翻译成 127.0.0.1:5433(宿主发布端口),无需另配。
CUSTOMER_DB_HOST=cx-postgres
CUSTOMER_DB_PORT=5432
 
# 栈内 PG 开关,必须与上面这对坐标配套(cx-postgres 收在 localdb profile 内,默认不启动):
#   CUSTOMER_DB_HOST=cx-postgres      → 保留本行,compose 才会起 cx-postgres 容器
#                                        还会因 external 卷 postgres_pgdata 不存在把整栈拦下)
# 两者不配套时 preflight 会直接报错,不会让你带着错配起栈。
COMPOSE_PROFILES=localdb
 
 
# ════════════════════════════════════════════════════════════════════════════
# 2. 业务库凭据(须与目标 PG 实例的真实角色密码一致)
# ════════════════════════════════════════════════════════════════════════════
# 默认值 = 本机容器 PG 出厂密码(install.sh 建库时写入),本机场景不用改。
JNPF_APP_DB_USER=jnpf_app
JNPF_APP_DB_PASSWORD=change-me
 
 
# ════════════════════════════════════════════════════════════════════════════
# 3. 流程引擎库凭据
# ════════════════════════════════════════════════════════════════════════════
# 地址由 §1 客户坐标自动推导,与业务库结构性同源。
# 🔴 绝对不要设 JNPF_FLOW_DB_URL 来指引擎库!它是整串覆盖的逃生口,会把引擎库与
#    业务库拆成两个来源(半切)——2026-08-03 事故:49 个流程模板 44 个报「找不到流程
JNPF_FLOW_DB_USER=jnpf_flow_app
JNPF_FLOW_DB_PASSWORD=change-me
 
 
# ════════════════════════════════════════════════════════════════════════════
# 4. 本机栈私有(跟「连哪个客户」无关,是这台机器自己容器栈的设置)
# ════════════════════════════════════════════════════════════════════════════
# 两角色的 PG 连接数配额(供 create-app-roles.sh;防单角色占满连接槽饿死流程引擎,L029)。
# 多客户实例(max_conn=150):120/20;客户1老实例(400):350/35;交付单环境(200):150/30。
# 铁律:两者之和 < max_connections − 3。未设时脚本内置默认 150/30。
JNPF_APP_CONN_LIMIT=120
JNPF_FLOW_CONN_LIMIT=20
# 栈内 PG(cx-postgres,COMPOSE_PROFILES=localdb 时)的 max_connections,未设默认 200;改后须重建 cx-postgres。
# 以命令行 -c 传入,优先级高于 ALTER SYSTEM——在库里 ALTER SYSTEM SET max_connections 不会生效,只能改这里。
#PG_MAX_CONNECTIONS=200
# PG 超级用户密码(仅运维用;只在 initdb 全新数据卷时写入,既有卷改密须 ALTER USER)
JNPF_PG_PASSWORD=change-me
 
 
# ════════════════════════════════════════════════════════════════════════════
# 5. Redis
# ════════════════════════════════════════════════════════════════════════════
# cx-redis 的 requirepass;业务侧经 compose / start-all 透传(datasource.yaml 占位符),
# 改这里即全局轮换。
JNPF_REDIS_PASSWORD=change-me
# Redis 坐标(datasource.yaml 占位符;与 PG 的 CUSTOMER_DB_HOST/PORT 同构)。
# 宿主自装 Redis、且业务可能在宿主和 Docker 两种形态运行时使用下面四行:
# JNPF_REDIS_HOST/PORT 供 ./start-all.sh;JNPF_DOCKER_REDIS_HOST/PORT 仅由 compose 注入容器。
#JNPF_REDIS_HOST=127.0.0.1
#JNPF_REDIS_PORT=6379
#JNPF_DOCKER_REDIS_HOST=cx-infra
#JNPF_DOCKER_REDIS_PORT=6379
 
 
# ════════════════════════════════════════════════════════════════════════════
# 6. OnlyOffice Document Server(Office 文档在线预览/编辑)
# ════════════════════════════════════════════════════════════════════════════
# 消费方两侧:cx-onlyoffice 容器(DS 本体)+ cx-biz-common 的 onlyoffice 能力模块
# 本节只有 JWT_SECRET 必填,其余全部有默认值 = 本机 compose 形态,cp 即用。
 
# ── 必填:DS 与后端之间的唯一信任凭据 ──
# 两侧必须同值:
#   - cx-onlyoffice 容器:作为 JWT_SECRET 环境变量注入(docker-compose.yml)
#   - cx-biz-common:经 config/shared/jnpf-biz-common.yaml 的 onlyoffice.jwt-secret 占位符消费
# 后端用它签发编辑器 config,DS 用它签发保存回调;不一致的表现是编辑器一直转圈
# 或回调静默失败,且两侧日志都不明显——改这里即全局轮换,改完两个容器都要重启。
# 🔴 回调路径 /api/biz/onlyoffice/callback 已进网关白名单(平台补丁 #9),该端点
#    匿名可达,这个 secret 是它唯一的安全边界,交付环境务必换成随机值。
ONLYOFFICE_JWT_SECRET=your-secret-key
 
# ── 四个地址键:每个都是**某一方的视角**,别混着填 ──
# 容器栈(docker compose):四个全不设即可,默认值就是本机形态。
# 宿主栈(./start-all.sh):脚本已自动 export 下面 3 个 host.docker.internal 形态的值
#   (DS 在容器里、网关和后端在宿主上),一般不用在 .env 里设;显式设了则以 .env 为准。
#
#   键                          | 视角     | 容器栈默认            | 宿主栈(start-all.sh 自动值)
#   ----------------------------|---------|----------------------|------------------------------
#   ONLYOFFICE_DS_PUBLIC_URL    | 浏览器   | http://localhost:20000 | 同左(override 发布的端口)
#   ONLYOFFICE_FILE_FETCH_BASE_URL | DS   | http://cx-gateway:30000 | http://host.docker.internal:30000
#   ONLYOFFICE_CALLBACK_BASE_URL   | DS   | http://cx-gateway:30000 | http://host.docker.internal:30000
#   ONLYOFFICE_DS_INTERNAL_URL     | 后端 | http://cx-onlyoffice    | http://localhost:20000
#
# 浏览器视角:加载编辑器 api.js 的地址。容器名浏览器解析不了,本机走 override 发布的 20000。
# 交付环境改为 Nginx 反代的 https://<域名>/onlyoffice(方案 §8.4,与 §7 域名四键配套改)。
#ONLYOFFICE_DS_PUBLIC_URL=http://localhost:20000
# DS 视角:DS 回源拉原始文档。/api/file/Image/** 在网关白名单内,DS 无登录态靠 securityKey 取件。
#ONLYOFFICE_FILE_FETCH_BASE_URL=http://cx-gateway:30000
# DS 视角:DS 保存回调。必须经网关——直连 30015 按 L042 会被 inner-auth 拒。
#ONLYOFFICE_CALLBACK_BASE_URL=http://cx-gateway:30000
# 后端视角:后端反向拉取 DS 产物。回调里 DS 给的 url 是它自己视角的主机名,后端不一定直连得到,
# 配了本项就只保留其 path+query 换到这个主机上;留空则原样使用 DS 给的 url。
#ONLYOFFICE_DS_INTERNAL_URL=http://cx-onlyoffice
# 本机 OnlyOffice 自定义字体目录:docker compose 将其只读挂载到 Document Server,
# 不复制进镜像或交付包;其他机器需改为本机实际存在的目录。
ONLYOFFICE_CUSTOM_FONT_DIR=./onlyoffice-fonts
 
# ── 编辑行为开关 ──
# 通用上传控件是否允许 OnlyOffice 在线编辑;仍须字段 onlineEdit 和当前表单/流程权限。
# 后端默认 false;本地需要开放编辑时设为 true。
ONLYOFFICE_UPLOAD_FILE_EDIT_ENABLED=true
# 编辑锁的心跳超时(分钟)。锁正常由 status 2/4 回调释放,本项是浏览器崩溃等异常场景的
# 兜底,否则文档会永久锁死。
#ONLYOFFICE_LOCK_TIMEOUT_MINUTES=30
# 编辑器里是否给下载/打印入口,默认全关。
# ⚠️ 只收界面入口,**不是安全边界**:知道 URL 的人照样能经 /api/file/Image/** 把原文件拉走。
#ONLYOFFICE_ALLOW_DOWNLOAD=false
#ONLYOFFICE_ALLOW_PRINT=false
# 未登记 bizModule 时是否一律只读。默认 false(放行编辑 + 一条 warn),兼容不传 bizModule 的
# 既有调用方。🔴 该登记的都登记完之后应当置 true——否则「漏登记」的表现是悄悄放行编辑,
# 而不是能被人发现的报错。登记表在 config/shared/jnpf-biz-common.yaml 的 edit-permission.modules。
#ONLYOFFICE_EDIT_PERMISSION_STRICT=false
 
# ── ELN 模板标注插件 ──
# 公网基础地址(浏览器视角,DS 从这里加载插件资源)+ 发布版本(对应不可变发布目录)。
#ONLYOFFICE_PLUGIN_PUBLIC_BASE_URL=http://localhost:4173/onlyoffice-plugins
#ONLYOFFICE_PLUGIN_RELEASE=0.1.0-dev
 
 
# ════════════════════════════════════════════════════════════════════════════
# 7. 域名四键(L023 双消费方:须浏览器可达且容器内可达)
# ════════════════════════════════════════════════════════════════════════════
# 本机不设(config/shared/system-config.yaml 内置默认即本机形态)。
# 部署环境必设为服务器实际地址,例如:
#JNPF_API_DOMAIN=http://your-server
#JNPF_APP_DOMAIN=http://your-server/
#JNPF_FRONT_DOMAIN=http://your-server/
#JNPF_FLOW_DOMAIN=http://cx-flow-engine:31000
 
 
# ════════════════════════════════════════════════════════════════════════════
# 8. 文件存储与日志落盘
# ════════════════════════════════════════════════════════════════════════════
# ── 业务文件(附件/图片/导出件)──
# 宿主侧文件根目录(compose 挂载用);Mac 默认 /Users/Shared,可不设。
# 业务进程读的是 JNPF_FILE_DIR(resources.yaml);容器内固定 /data/jnpf-files/。
# Win/Linux 按各自习惯改,例如 JNPF_DATA_DIR=D:/jnpf-data 或 /data/jnpf。
#JNPF_DATA_DIR=/Users/Shared
#JNPF_FILE_DIR=/Users/Shared/
 
# ── SeaweedFS(S3 兼容接口,DMS 与通用文件使用不同 bucket)──
# 部署前创建 jnpf-dms、jnpf-common;建议两组凭证仅能访问各自 bucket。
# 必须是应用容器可访问的 S3 Gateway;宿主机 8333 端口按本仓库约定使用 cx-infra。
SEAWEEDFS_ENDPOINT=http://cx-infra:8333/
SEAWEEDFS_DMS_ENABLED=true
SEAWEEDFS_DMS_ACCESS_KEY=change-me
SEAWEEDFS_DMS_SECRET_KEY=change-me
SEAWEEDFS_DMS_BUCKET_NAME=jnpf-dms
SEAWEEDFS_DMS_BASE_PATH=files/
SEAWEEDFS_COMMON_ENABLED=true
SEAWEEDFS_COMMON_ACCESS_KEY=change-me
SEAWEEDFS_COMMON_SECRET_KEY=change-me
SEAWEEDFS_COMMON_BUCKET_NAME=jnpf-common
SEAWEEDFS_COMMON_BASE_PATH=files/
 
# ── DMS 全文检索(Meilisearch)──
#
#   形态                          | DMS_MEILISEARCH_URL              | 索引前缀
#   ------------------------------|----------------------------------|----------------------
#   本机 Docker + start-all.sh    | http://127.0.0.1:7700            | dms_documents_dev
#   cx-dms 与 Meilisearch 同网络  | http://cx-meilisearch:7700       | 按环境定
#
DMS_SEARCH_ENABLED=false
DMS_MEILISEARCH_URL=http://cx-meilisearch:7700
# 🔴 必须填 DMS 后端专用【受限】API Key(search/documents.add/indexes.create),
#    绝不能填 Meilisearch 的 Master Key,也不要下发给前端。
DMS_MEILISEARCH_API_KEY=
# 🔴 改这个前缀就必须同步改 API Key 的 indexes 范围(dms_documents_bositao_*),
#    否则 DMS 写索引会 403。真实索引名 = 本前缀 + "_" + 租户哈希。
DMS_MEILISEARCH_INDEX_NAME=dms_documents_bositao
#
# ⚠️ 打开 DMS_SEARCH_ENABLED 之前就存在的文件【不会】自动进索引(无历史回填),
#    只有新上传/新修订才建索引。扫描版 PDF 同理需要 OCR Adapter,当前无实现。
 
# ── 应用日志(2026-08-11 起已 bind mount 出容器)──
# 🔴 两个变量别搞混,后缀 _HOST 的才是你要改的那个:
#
#   变量                | 在哪一侧   | 值            | 谁消费
#   --------------------|-----------|---------------|--------------------------------
#   JNPF_LOG_DIR_HOST   | 宿主机 ★  | 默认 ./logs   | docker-compose.yml 的 volumes 源
#   JNPF_LOG_DIR        | 容器内    | /data/jnpf-logs | logger.yaml 的 log.path(compose 已固定,不用改)
#
#   docker-compose.yml 里那行挂载长这样:
#       - ${JNPF_LOG_DIR_HOST:-./logs}:/data/jnpf-logs
#         └── 宿主机目录 ────────────┘ └─ 容器内目录 ─┘
#
# 各服务自动写 <宿主目录>/<服务名>/log_{error,warn,info,debug,total}.log,
# 直接 tail -f logs/jnpf-lims/log_error.log 即可,容器重建/删除都不丢。
# 按天+按大小双维度滚动(logback SizeAndTimeBasedRollingPolicy:跨天或满 10MB 即切,
# 归档进 <服务名>/{error,warn,info,total}/YYYY-MM-DD/ 子目录,保留 7 天),归档同样在宿主上。
#
# 交付/测试环境建议指到数据盘,别让日志堆在部署目录里(下面是**宿主机**路径):
#JNPF_LOG_DIR_HOST=/var/log/jnpf
# ⚠️ Linux 上该目录由容器内 root 创建,非 root 用户读日志需要 sudo。
 
 
# ════════════════════════════════════════════════════════════════════════════
# 9. Compose / 构建
# ════════════════════════════════════════════════════════════════════════════
# 全栈统一产品版本:自建镜像 tag 随此值走,发版=改这一个值;未设默认 1.0.0
#CX_VERSION=1.0.0
# 交付/生产(只用基线,排除 override 的本地调试端口发布):
#COMPOSE_FILE=docker-compose.yml
# 访问不了 Docker Hub 时解开,SWR 国内源(开发机同样适用,2026-08-10 换机实证:
# 不解开则 cx-web 构建报 auth.docker.io i/o timeout,业务镜像的 JRE 基底同理):
#BASE_IMAGE=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/bellsoft/liberica-openjre-rocky:21
# nginx 基底两种写法二选一:
#   ① 短名(推荐,同 cx-redis 待遇)——由 make pull-infra 从 SWR retag,
#      必须经 make images/pull-infra,否则 docker 会去 docker.io 找不存在的 library/cx-nginx
#NGINX_BASE_IMAGE=cx-nginx:1.27-alpine
#   ② SWR 长名(不依赖 retag,任何 docker compose build 都能用)
#NGINX_BASE_IMAGE=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/nginx:1.27-alpine
 
# 是否启动 PDF 异步任务 Worker。为 false 时,新上传的 Word 文件仍会登记任务,但不会执行转换
#DMS_PDF_GENERATION_WORKER_ENABLED=true
 
# ════════════════════════════════════════════════════════════════════════════
# 10. 开发环境一键审批(宿主机启动)
# ════════════════════════════════════════════════════════════════════════════
# 默认关闭;仅用于开发环境,开启后仍须管理员登录并提供本轮原生电子签名。
# 前端仅在开发模式、已提交且审批中的流程详情显示入口。
# start-all.sh 读取根目录 .env;值为 true 时,为 jnpf-platform 加载
# workflow-dev-tools profile。prod / production profile 下不注册此工具接口。
# 表单范围由 config/host-override/workflow-development.yaml 的 form-ids 控制:
# 空列表允许所有流程,非空列表仅允许指定表单。
# 修改后执行 ./start-all.sh restart jnpf-platform 生效。
# 后台任务仅保存在进程内存;关闭页面不停止,服务重启后不会自动续跑。
WORKFLOW_AUTO_APPROVE_ENABLED=false