Grist 1.7.21 配置参数详解

grist-core v1.7.21 核心配置参数逐项实测详解:页面标题后缀、单组织模式、UI 特性开关、导入限额(413 实证)、SQLite WAL、Prometheus 指标、JSON 日志、强制登录、TypeORM 切 PostgreSQL 全链路(22 张表与全新安装态结论);每个参数均含默认值、修改方法与可观察验证证据,2026-10-28 实测。

GristGrist电子表格2026/10/28

Grist 1.7.21 配置参数详解

目标:把 grist-core v1.7.21 自托管运维中最常用的配置参数逐项讲清并全部实测验证——每个参数都给出:作用、默认值、修改方法、生效后的可观察证据(页面配置、API 响应、文件系统变化、日志或 HTTP 状态码),最后附参数速查总表与元数据库切换 PostgreSQL 的全链路实录。实测基线是 《Grist 1.7.21 安装部署指南》交付的服务器(Ubuntu 24.04 + systemd 托管 + nginx 反代,/etc/grist.env 为配置载体),全部操作于 2026-10-28 完成并留有回显;产品认知见 《Grist 1.7.21 介绍与选型指南》。


一、配置机制总览

Grist 服务端的配置载体是环境变量。裸机 systemd 部署下,统一落在 /etc/grist.env,由 grist.service 的 EnvironmentFile= 注入。实测的基线内容:

PORT=3000
GRIST_HOST=127.0.0.1
GRIST_SERVE_SAME_ORIGIN=true
GRIST_SANDBOX_FLAVOR=unsandboxed
GRIST_DATA_DIR=/opt/grist/grist-docs
GRIST_DEFAULT_EMAIL=admin@example.com
GRIST_SESSION_SECRET=Xk9vPq2mRt7sWb1nJd4hYf6gLz0cEa8u
GRIST_PAGE_TITLE_SUFFIX= · 数据实验室

修改-生效-验证的标准闭环(本文每个参数都用这套方法实测):

# 1) 修改:向 /etc/grist.env 追加或修改变量
# 2) 生效:
systemctl restart grist        # 实测重启到就绪约 8-12 秒
# 3) 验证:curl http://127.0.0.1:3000/ 或对应观测点

多数前端可见的参数会出现在页面内嵌的 gristConfig 对象里,可以直接抓取验证:

curl -s http://127.0.0.1:3000/o/docs/ | grep -o '"pageTitleSuffix":"[^"]*"'

二、站点呈现类参数

2.1 GRIST_PAGE_TITLE_SUFFIX:浏览器标签页后缀

  • 作用:所有页面 <title> 的统一后缀,多环境(测试/生产)区分的最低成本手段;
  • 实测:设 GRIST_PAGE_TITLE_SUFFIX= · 数据实验室 并重启后,页面嵌入配置出现:
$ curl -s http://127.0.0.1:3000/o/docs/ | grep -o '"pageTitleSuffix":"[^"]*"'
"pageTitleSuffix":"· 数据实验室"

2.2 GRIST_SINGLE_ORG / GRIST_ORG_IN_PATH:单组织模式

  • 作用:把站点收口为单一组织(org),URL 呈现方式随之变化;
  • 实测(GRIST_SINGLE_ORG=gristlab,配合 GRIST_ORG_IN_PATH=true):
    • 默认多组织模式下 GET / 会 302 到 /o/docs/(org 是安装时创建的 docs);设置后 GET / 直接 200 渲染,/o/gristlab 也返回 200;
    • GRIST_ORG_IN_PATH=true 表示 org 走路径段 /o/<org>(官方没有 GRIST_ORG_IN_HOST 变量,域名式呈现需自行在外层做泛域名);
  • 注意(实测确认的行为边界):该变量主要作用于 URL 呈现层。安装时创建的组织名是 docs,改成 gristlab 后站点内组织列表仍显示原有 Personal 组织——它不会把已有组织改名。

2.3 GRIST_HIDE_UI_ELEMENTS / GRIST_UI_FEATURES / GRIST_SUPPORT_ANON:界面特性开关

  • GRIST_HIDE_UI_ELEMENTS:黑名单,从默认特性集中摘除指定项;
  • GRIST_UI_FEATURES:反向白名单,只保留列出的特性(代码点 sendAppPage.ts 的特性过滤逻辑);
  • GRIST_SUPPORT_ANON:控制匿名访问相关 UI(关闭后页面嵌入配置中 supportAnon:false);
  • 实测 A/B 对比:默认抓取页面 features 数组:
默认:  ["helpCenter","billing","templates","multiSite","multiAccounts",
        "importFromAirtable","sendToDrive","createSite","supportGrist","themes",
        "importFromAirtable","importFromGrist","automations","oauthApps"]
设置 GRIST_HIDE_UI_ELEMENTS=templates,helpCenter 后:
       helpCenter / templates 从 features 消失,页面中 "templates" 计 0 次

社区版运维常用它隐藏托管版才有的入口(templates、helpCenter 等)。

三、资源限额类参数

3.1 GRIST_MAX_UPLOAD_IMPORT_MB:导入文件上限

  • 作用:限制单次导入/上传文件大小,代码点 ActiveDocImport.ts(const limit = (Number(process.env.GRIST_MAX_UPLOAD_IMPORT_MB) * 1024 * 1024) || Infinity,超限抛出 413);
  • 实测设 GRIST_MAX_UPLOAD_IMPORT_MB=1,走完整 API 链路验证:
# 1) 种会话(minimal 登录自动种 cookie)
curl -s -c cj.txt "http://127.0.0.1:3000/login?next=/" -o /dev/null
# 2) 上传文件(注意必须是 /v/<构建tag>/uploads,缺 X-Requested-With 头会被拒)
curl -s -b cj.txt -H "X-Requested-With: XMLHttpRequest" \
     -F "upload=@big.csv" http://127.0.0.1:3000/v/6dfae2f/uploads
{"uploadId":"2"}
# 3) 导入为文档
curl -s -b cj.txt -X POST http://127.0.0.1:3000/api/workspaces/2/import \
     -H "Content-Type: application/json" \
     -d '{"uploadId":"2","documentName":"big3"}'

实测结果:0.95 MB(1001071 字节)导入成功 200(新建文档);3.39 MB(3388734 字节)被拒:

HTTP 413
{"error":"Imported files must not exceed 1.0MB",...}
  • 两道门的提醒:这是 Grist 应用层的门;nginx 侧还有 client_max_body_size(见 《Grist 1.7.21 安装部署指南》 5.3 节)。调大限额时两处要一起核,否则 413 会先从 nginx 报出来,错误样式完全不同。

四、存储类参数

4.1 GRIST_SQLITE_MODE:文档 SQLite 的日志模式

  • 作用:控制每个文档(.grist 文件本质是 SQLite 库)的 journal 模式,代码点 DocStorage.ts:默认 nosync(synchronous OFF,性能优先)、可选 sync(FULL)、wal;
  • 实测设 GRIST_SQLITE_MODE=wal,重启后打开文档,数据目录出现 sidecar 文件:
-rw-r--r-- 1 root root 167936 .../grist-docs/7x5V8ANAPJ8gXBWEiM2Dfe.grist
-rw-r--r-- 1 root root  32768 7x5V8ANAPJ8gXBWEiM2Dfe.grist-shm
-rw-r--r-- 1 root root      0 7x5V8ANAPJ8gXBWEiM2Dfe.grist-wal

只读校验 journal 模式:

$ python3 -c "import sqlite3; con=sqlite3.connect('file:/opt/grist/grist-docs/7x5V8ANAPJ8gXBWEiM2Dfe.grist?mode=ro',uri=True); print(con.execute('PRAGMA journal_mode').fetchone())"
('wal',)

4.2 GRIST_DATA_DIR:文档存储目录

  • 作用:.grist 文档文件与 grist-service.log 的落点;
  • 实测资产:/opt/grist/grist-docs/ 下 7x5V8ANAPJ8gXBWEiM2Dfe.grist(167936 B)等文档文件 + grist-service.log。注意元数据不在这里——它在工作目录的 landing.db(GRIST_INST_DIR 未设时随服务工作目录),两者备份都要覆盖。

五、可观测性参数

5.1 GRIST_PROMCLIENT_PORT:Prometheus 指标端口

  • 实测设 GRIST_PROMCLIENT_PORT=29090:
$ curl -s -o /dev/null -w '%{http_code} %{size_download}\n' http://127.0.0.1:29090/metrics
200 8782

返回 Prometheus 文本格式(process_cpu_user_seconds_total 等进程级指标),可直接被 Prometheus 抓取。

5.2 GRIST_LOG_AS_JSON:结构化日志

  • 实测设 GRIST_LOG_AS_JSON=true,日志行变为 JSON:
{"level":"info","message":"FlexServer is ready","timestamp":"2026-10-28 08:01:28.163"}
  • 边界:仅经日志框架输出的行受控;个别 console.log 直出的行(如 Grist is available at http://localhost:3000)仍是纯文本。接入日志采集时按"JSON 行 + 少量文本行"设计解析。

六、认证与访问类参数

6.1 GRIST_FORCE_LOGIN:强制登录

  • 实测:设 true 后,匿名 GET /o/docs 返回 302 回跳同 URL(不带 cookie 时 curl 会反复 302)——所有请求必须先过登录回跳;
  • 与 minimal 模式的叠加表现:默认 minimal 自动登录本就"人人有会话",GRIST_FORCE_LOGIN 的真实差异在对接 OIDC/ForwardAuth 时显现(未认证请求不再透传页面,而是被拦到登录入口)。

6.2 GRIST_DEFAULT_EMAIL 与 minimal 模式

回顾 《Grist 1.7.21 安装部署指南》 4.3 节的结论:minimal 模式下所有访客自动以该邮箱身份进入,没有密码校验——它决定了 admin@example.com 在本系列实测中的"超级用户"地位;生产环境替换为 OIDC/SAML/ForwardAuth 后,此变量仅作兜底。

七、元数据库切换 PostgreSQL:全链路实测

Grist 的元数据库(用户/组织/工作区/文档目录)默认 SQLite(landing.db),通过 TypeORM 一组变量切换 PostgreSQL:

TYPEORM_TYPE=postgres
TYPEORM_HOST=10.89.70.20
TYPEORM_PORT=5432
TYPEORM_USERNAME=postgres
TYPEORM_PASSWORD=q1w2e3r4
TYPEORM_DATABASE=grist

实测全链路(2026-10-28):

  1. 追加上述变量后 systemctl restart grist,匿名访问 / 出现 302 → /boot——因为站点激活状态存在 home DB 里,切库等于全新安装态,需要重新走 /boot 引导(新 boot key 由日志自动打印:4596ed3a65652db940e6ab38);
  2. 重走 /boot/verify-boot-key → /boot/login(204)→ PATCH /api/install/prefs(200)后,GET / 恢复 302 → /o/docs/;
  3. PostgreSQL 侧自动建表 22 张:acl_rules / activations / aliases / billing_* / configs / doc_prefs / docs / group_* / groups / limits / logins / migrations / oauth_* / orgs / prefs / products / proposals / secrets / service_accounts / users / workspaces 等;
  4. 数据核对:
SELECT l.email, u.name FROM logins l JOIN users u ON u.id = l.user_id;
--  anon@getgrist.com / thumbnail@ / everyone@ / support@ / admin@example.com (You)

两条关键迁移结论(实测确认):

  • SQLite 时代的文档元数据不会自动出现在新库:.grist 文件仍在 GRIST_DATA_DIR,但新 docs 表为空、原 docId 不可见;需要迁移时应整体规划(先在 SQLite 导出再导入,或维持 SQLite 元数据不动、仅把新装站点直接落在 PostgreSQL);
  • 回滚简单:从 /etc/grist.env 去掉 TYPEORM_* 重启即回到 SQLite,但切库期间的增量元数据各自独立,不可双向自动同步。

八、参数速查总表

变量默认本篇实测值作用与验证点
GRIST_PAGE_TITLE_SUFFIX空 · 数据实验室标签页后缀;gristConfig.pageTitleSuffix
GRIST_SINGLE_ORGdocsgristlab单组织 URL 收口;GET / 不再 302 到 /o/docs/
GRIST_ORG_IN_PATH-trueorg 走 /o/<org> 路径段(无 IN_HOST 变量)
GRIST_HIDE_UI_ELEMENTS空templates,helpCenter特性黑名单;页面 features 数组消失对应项
GRIST_UI_FEATURES空未启用特性白名单(反向),代码点 sendAppPage.ts
GRIST_SUPPORT_ANONtrue观测 supportAnon:false匿名入口 UI
GRIST_MAX_UPLOAD_IMPORT_MB∞1导入上限;超限 413 Imported files must not exceed 1.0MB
GRIST_SQLITE_MODEnosyncwal文档 journal 模式;出现 -wal/-shm,PRAGMA journal_mode→wal
GRIST_DATA_DIR-/opt/grist/grist-docs.grist 文档与 grist-service.log 落点
GRIST_PROMCLIENT_PORT关29090/metrics 200,Prometheus 文本格式
GRIST_LOG_AS_JSONfalsetrue日志 JSON 行化(console 直出行除外)
GRIST_FORCE_LOGINfalsetrue匿名请求强制登录回跳
GRIST_DEFAULT_EMAIL-admin@example.comminimal 自动登录身份
TYPEORM_TYPE/HOST/PORT/USERNAME/PASSWORD/DATABASEsqlitepostgres 组元数据库切 PG;22 张表自动建,/boot 重现需重引导

九、系列导航