InvenioRDM 14.0.6 配置参数详解

InvenioRDM 14.0.6 实例配置 invenio.cfg 逐段详解(Flask 基座/安全响应头/账户认证/存单表单/DOI 与 OAI/检索前缀/资产构建/日志统计约 40 个配置键),实测验证 INVENIO_* 环境变量三层覆盖机制与配置生效路径,附生产配置模板与 8 条配置类 FAQ。

InvenioRDMInvenioRDMPythonPostgreSQLRedis知识库2026/11/01

InvenioRDM 14.0.6 配置参数详解

目标:逐段讲透 InvenioRDM 14.0.6 实例项目核心配置文件 invenio.cfg 的每一个参数(Flask 基座、安全响应头、账户认证、存单表单、DOI/OAI、检索前缀、资产构建、日志统计),并实测验证 INVENIO_* 环境变量覆盖机制与配置生效路径。全部结论基于 《InvenioRDM Docker Compose 部署指南》 部署的 14.0.6 实栈(Ubuntu 26.04.1 LTS / Docker 29.9.2,项目目录 /opt/invenio-rdm/my-site,访问入口 https://127.0.0.1:8138/),命令与回显均为实测。

一、环境信息

项目实测值
InvenioRDMinvenio-app-rdm 14.0.6(容器内 python -c "import invenio_app_rdm" 核实),记录模块 invenio-rdm-records 32.2.2
应用运行时Python 3.14.10 / Flask 3.1.3 / Werkzeug 3.1.9
配置文件(项目源)/opt/invenio-rdm/my-site/invenio.cfg(8426 字节)
配置文件(容器内生效副本)/opt/invenio/var/instance/invenio.cfg(构建期 COPY 进镜像)
实例目录/opt/invenio/var/instance(INVENIO_INSTANCE_PATH 实测值)
环境变量注入docker-services.yml app 段 14 项 INVENIO_*,容器内实测共 16 项(另 2 项由镜像/基础环境提供)
配置相关服务web-api / web-ui / worker / scheduler 四服务共用同一镜像与同一份 cfg
验证入口https://127.0.0.1:8138/(自签证书,curl 加 -k)

InvenioRDM 的配置模型是标准 Flask 应用模型:invenio.cfg 是一个 Python 模块(不是 INI/YAML),每个大写下划线标识符就是一个 Flask 配置键;各 invenio-* 模块在启动时读取自己命名空间前缀的键(如 APP_RDM_*、SECURITY_*、OAISERVER_*)。因此 cfg 里可以出现 from 导入、lambda、函数调用等合法 Python 代码——实测本实例的 cfg 就含 from invenio_i18n import lazy_gettext as _ 与 "publication_date": lambda: datetime.now().strftime("%Y-%m-%d")。

二、前置条件

  1. 已按 《InvenioRDM Docker Compose 部署指南》 完成 14.0.6 全栈部署与初始化(10 服务 Up、DB/索引/fixtures 就绪);
  2. 能进入应用服务执行命令:
cd /opt/invenio-rdm/my-site
docker compose -f docker-compose.full.yml exec web-api bash
# 容器内工作目录 /opt/invenio/src,实例目录 /opt/invenio/var/instance
  1. 验证配置文件确已随镜像构建进容器(实测回显,尺寸与项目源文件一致):
$ ls -l /opt/invenio/var/instance/invenio.cfg
-rw-r--r-- 1 root root 8426 Nov  1 13:15 /opt/invenio/var/instance/invenio.cfg

三、参数查看与修改方式

3.1 三层配置来源与优先级

层载体位置优先级
1invenio.cfg项目源文件 → 构建期 COPY 进镜像 → 容器内 /opt/invenio/var/instance/invenio.cfg基线
2INVENIO_<键名> 环境变量docker-services.yml app 段 environment(compose 注入)覆盖 cfg 同名键
3site 包 Python 代码项目 site/my_site/(views/webpack 等扩展点)定制逻辑

优先级机制实测佐证:cfg 第 150 行写 SITE_UI_URL = "https://127.0.0.1:5000",而容器内实际生效值是 https://127.0.0.1——来自环境变量 INVENIO_SITE_UI_URL(实测 env 回显,见 3.2)。cfg 文件内注释也明说了这一点:"The containerized setup overwrites these values in docker-services.yml."

3.2 查看当前生效值

方式一:看环境变量层(实测全量回显,docker compose -f docker-compose.full.yml exec web-api env | grep INVENIO_ 排序后 16 项):

INVENIO_ACCOUNTS_SESSION_REDIS_URL=redis://cache:6379/1
INVENIO_BROKER_URL=amqp://guest:guest@mq:5672/
INVENIO_CACHE_REDIS_URL=redis://cache:6379/0
INVENIO_CACHE_TYPE=RedisCache
INVENIO_CELERY_BROKER_URL=amqp://guest:guest@mq:5672/
INVENIO_CELERY_RESULT_BACKEND=redis://cache:6379/2
INVENIO_COMMUNITIES_IDENTITIES_CACHE_REDIS_URL=redis://cache:6379/4
INVENIO_INSTANCE_PATH=/opt/invenio/var/instance
INVENIO_PROXYFIX_CONFIG={'x_for': 1, 'x_proto': 1}
INVENIO_RATELIMIT_STORAGE_URL=redis://cache:6379/3
INVENIO_SEARCH_HOSTS=['search:9200']
INVENIO_SECRET_KEY=CHANGE_ME
INVENIO_SITE_API_URL=https://127.0.0.1/api
INVENIO_SITE_UI_URL=https://127.0.0.1
INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://my-site:my-site@db/my-site
INVENIO_USER_ID=1000

方式二:看 cfg 源文件——项目里 /opt/invenio-rdm/my-site/invenio.cfg 与容器内副本同源,直接阅读即可(全文逐段详解见第五、六章)。

方式三:看行为反证——配置是否生效以外部行为为准,实测两例:OAISERVER_ID_PREFIX="my-site.com" 生效后,发布记录的响应里 pids.oai.identifier = "oai:my-site.com:x3kgj-3rt46"(API 实测);SEARCH_INDEX_PREFIX="my-site-" 生效后,invenio index list 只见带前缀的别名。

3.3 修改与生效路径

改动对象生效操作实测说明
invenio.cfginvenio-cli containers build → docker compose -f docker-compose.full.yml up -d web-api web-ui worker scheduler配置烧在镜像里,改文件必须重建镜像(B2 篇 8.3 实测流程)
INVENIO_* 环境变量改 docker-services.yml 后 up -d 重建应用服务即可,无需重 buildcompose 层变更,镜像不动
数据库类配置(location、角色、令牌)走 invenio CLI 而非 cfg实测:文件 location 存 DB,cfg 无法声明(见 7.4)

⚠️ 注意:改了 cfg 但没重建镜像、或同名键被 INVENIO_* 环境变量压住,是"配置不生效"两大高频原因,排查顺序见第七章。

四、参数总览

invenio.cfg 实测共 246 行、约 40 个配置键,按所属模块分组总览("当前值"即本实例实测值,"默认/出厂"指 invenio-cli 模板生成值):

分组配置键当前值作用一句话
Flask 基座SECRET_KEYCHANGE_ME(被 env 覆盖)会话/令牌签名密钥,生产必改
Flask 基座TRUSTED_HOSTS['0.0.0.0','localhost','127.0.0.1']可信 Host 白名单
Flask 基座SEND_FILE_MAX_AGE_DEFAULT300静态文件浏览器缓存秒数
数据库SQLALCHEMY_DATABASE_URIpostgresql+psycopg2://my-site:my-site@localhost/my-site(被 env 覆盖为 @db/)关系库连接串
安全头APP_DEFAULT_SECURE_HEADERS14 子键(CSP/HSTS/HTTPS 强制等)nginx 之外的应用层安全响应头
国际化BABEL_DEFAULT_LOCALE / BABEL_DEFAULT_TIMEZONEen / Europe/Zurich默认语言与时区
国际化I18N_LANGUAGES[](模板注释示例 de/tr)附加界面语言
主题THEME_SITENAME / THEME_FRONTPAGE_TITLE / THEME_LOGOMy Site / My Site / images/invenio-rdm.svg站名、首页标题、Logo
主题INSTANCE_THEME_FILE./less/theme.less主题覆盖入口(相对 assets/)
RDM 表单APP_RDM_DEPOSIT_FORM_DEFAULTSpublication_date=当天、rights=cc-by-4.0、publisher=My Site存单表单默认值
RDM 表单APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES'search'作者姓名自动补全模式
RDM 邮件APP_RDM_ADMIN_EMAIL_RECIPIENTinfo@my-site.com管理告警收件人(校验和告警等)
站点 URLSITE_UI_URL / SITE_API_URLhttps://127.0.0.1:5000(被 env 覆盖为无端口版)绝对链接生成基址
DOIDATACITE_ENABLED 等 5 键全关/空(TEST_MODE=True)DataCite DOI 注册
认证ACCOUNTS_LOCAL_LOGIN_ENABLED / SECURITY_* 5 键全 True,LOGIN_WITHOUT_CONFIRMATION=False本地登录/注册/找回/改密/邮箱确认
认证OAUTHCLIENT_REMOTE_APPS / ACCOUNTS_LOGIN_VIEW_FUNCTION / OAUTHCLIENT_AUTO_REDIRECT_TO_EXTERNAL_LOGIN{} / auto_redirect_login / False外部身份源接入
用户档案USERPROFILES_READ_ONLYFalse允许用户自改档案
用户资源USERS_RESOURCES_GROUPS_ENABLEDFalse关闭需额外配置的 groups 资源
OAIOAISERVER_ID_PREFIX / OAISERVER_ADMIN_EMAILSmy-site.com / [info@my-site.com]OAI-PMH 标识前缀与管理邮箱
检索SEARCH_INDEX_PREFIXmy-site-索引名前缀隔离
管理后台ADMINISTRATION_DISPLAY_VERSIONSinvenio-app-rdm v14.0.6 + my-site v1.0.0后台展示版本串
资产构建WEBPACKEXT_PROJECT / WEBPACKEXT_NPM_PKG_CLSrspack_project / pynpm:PNPMPackage前端打包器与包管理器
统计STATS_EVENTS_UTC_DATETIME_ENABLEDTrue访问统计事件用时区感知 UTC
日志LOGGING_CONSOLE_LEVELDEBUG控制台日志级别

💡 说明:表中"被 env 覆盖"的键(SECRET_KEY、SQLALCHEMY_DATABASE_URI、SITE_UI_URL/SITE_API_URL)在 cfg 与 compose 中并存,生效的是环境变量层——这是官方容器化模板的刻意设计:cfg 面向本地开发(localhost:5000),容器栈用 INVENIO_* 一键改指向服务名。

五、核心参数分类详解

5.1 Flask 基座与安全密钥

SEND_FILE_MAX_AGE_DEFAULT = 300
SECRET_KEY="CHANGE_ME"
TRUSTED_HOSTS = ['0.0.0.0', 'localhost', '127.0.0.1']
  • SEND_FILE_MAX_AGE_DEFAULT = 300:静态文件响应 Cache-Control: max-age 秒数(cfg 注释指向 Flask 文档对应键)。nginx 已对 /static 直接 alias 服务,该值主要影响应用侧 send_file 场景;
  • SECRET_KEY:Flask 会话 cookie、CSRF token、API 令牌摘要签名的根密钥。模板出厂 CHANGE_ME 是故意的占位(cfg 注释原文:"Do not commit it to a source code repository"),实测容器内生效值同样是 INVENIO_SECRET_KEY=CHANGE_ME——生产必须注入随机强密钥:宿主 openssl rand -hex 32 生成后填入 docker-services.yml 的 INVENIO_SECRET_KEY=(注入方式见 5.1 末)。⚠️ 该值变更后所有已登录会话失效、已签发个人令牌按实现可能失效,变更窗口需公告;
  • TRUSTED_HOSTS:Flask-Werkzeug 层 Host 头白名单。compose 模板注释原文说明:因 nginx/HAProxy 不按 Host 分流,默认放行了 0.0.0.0/localhost/127.0.0.1;生产应收敛为真实域名并只路由正确 Host。

5.2 数据库与检索连接

SQLALCHEMY_DATABASE_URI="postgresql+psycopg2://my-site:my-site@localhost/my-site"
SEARCH_INDEX_PREFIX = "my-site-"
  • SQLALCHEMY_DATABASE_URI:连接串格式 postgresql+psycopg2://<用户>:<密码>@<主机>/<库名>。本地开发默认 @localhost;容器栈被 INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://my-site:my-site@db/my-site 覆盖指向 compose 服务名 db(实测 env 回显见 3.2)。改密码需同步 db 服务的 POSTGRES_PASSWORD 三件套(B2 篇 6.2);
  • SEARCH_INDEX_PREFIX:所有 OpenSearch 索引/别名加 my-site- 前缀,实现一库多实例共栈隔离。实测 invenio index list 仅见前缀别名(users-user-v3.0.0 等在 my-site- 前缀下)。⚠️ 该值建立后不可随手改:改名等于换索引命名空间,需 invenio index init 重建并全量重索引(旧索引不自动迁移);
  • 检索主机 SEARCH_HOSTS 不在 cfg 中,由 env INVENIO_SEARCH_HOSTS=['search:9200'] 注入——注意其值是 Python 列表字面量字符串,多节点写 ['s1:9200','s2:9200']。

5.3 站点 URL 与反向代理信任

SITE_UI_URL = "https://127.0.0.1:5000"
SITE_API_URL = "https://127.0.0.1:5000/api"
# env 覆盖:INVENIO_SITE_UI_URL=https://127.0.0.1
#           INVENIO_SITE_API_URL=https://127.0.0.1/api
#           INVENIO_PROXYFIX_CONFIG={'x_for': 1, 'x_proto': 1}
  • SITE_UI_URL / SITE_API_URL:应用生成绝对 URL 的基址——邮件里的链接、登录重定向、API 响应中的 links.self/links.publish、记录预览地址全部由它拼出。实测两例:① 部署在 8138 端口但 env 值不带端口,GET /login 被 308 到 https://127.0.0.1/login/(端口丢失,浏览器经标准 443 反代无感、直连调试必踩,见 7.2);② API 建草稿响应里 preview_html=https://127.0.0.1/records/x3kgj-3rt46?preview=1 同样取自该值;
  • PROXYFIX_CONFIG:Flask-ProxyFix 信任的转发头跳数,{'x_for': 1, 'x_proto': 1} 表示恰好信任 nginx 一跳的 X-Forwarded-For / X-Forwarded-Proto。前置层数变化(如再加一层 CDN/HAProxy)必须同步调整,否则真实客户端 IP 与协议判断出错;nginx 侧对应 uwsgi_param HTTP_X_FORWARDED_FOR/PROTO 传递(B2 篇 nginx 配置实测内容)。

5.4 安全响应头(APP_DEFAULT_SECURE_HEADERS)

实测 cfg 全文 14 个子键:

APP_DEFAULT_SECURE_HEADERS = {
    'content_security_policy': {
        'default-src': ["'self'", 'data:', "'unsafe-inline'", "blob:"],
        'script-src': ["'self'", "blob:", "'wasm-unsafe-eval'"],
    },
    'content_security_policy_report_only': False,
    'content_security_policy_report_uri': None,
    'force_file_save': False,
    'force_https': True,
    'force_https_permanent': False,
    'frame_options': 'sameorigin',
    'frame_options_allow_from': None,
    'session_cookie_http_only': True,
    'session_cookie_secure': True,
    'strict_transport_security': True,
    'strict_transport_security_include_subdomains': True,
    'strict_transport_security_max_age': 31556926,
    'strict_transport_security_preload': False,
}

逐项解读:

子键值含义与实测影响
CSP default-srcself/data:/unsafe-inline/blob:资源默认只允许同源;data: 供字体、blob: 供 PDF 预览、unsafe-inline 放行内联脚本样式(cfg 注释逐项说明)。定制主题加外部资源(如分析脚本)必须在此追加来源,否则被浏览器拦截
CSP script-srcself/blob:/wasm-unsafe-eval多文件上传用 Web Worker 跑 hash-wasm 计算分片 MD5,blob: 与 wasm-unsafe-eval 缺一不可(cfg 注释原文),精简 CSP 会直接打断大文件上传
content_security_policy_report_onlyFalseCSP 违规是拦截而非仅上报;True 可作灰度观察模式
force_httpsTrue非 HTTPS 请求强制跳 https;配合 nginx 80 端口 return 301 https:// 双层兜底
force_https_permanentFalseTrue 则 301 永久跳,False 用临时跳(避免测试期被浏览器永久缓存)
frame_optionssameorigin禁外站 iframe 嵌页(防点击劫持);要在门户里内嵌记录页需改 None 并配 CSP frame-ancestors
session_cookie_http_only / secureTrue / True会话 cookie 禁 JS 读取、仅 HTTPS 传输——实测 http 访问会被 force_https 弹回,cookie 属性与之一致
strict_transport_security 三键True / True / 31556926HSTS 开启、含子域、max-age 一年(cfg 注释:"One year in seconds")。⚠️ 一旦真实域名下发 HSTS,浏览器一年内强制只走 HTTPS,证书到期不续也进不去,上生产前确保证书自动续期就绪
strict_transport_security_preloadFalse不申请 HSTS preload 列表(申请后不可逆,慎开)

💡 技术拓展:HTTPS 与 HSTS 参数常见取值策略——

策略max-agepreload适用
测试观察短(分钟级)否域名刚上 HTTPS
生产标准(本实例口径)≥ 半年(一年)否证书稳定自动续期
激进≥2 年 + includeSubDomains是全站强制 HTTPS 且不可回退

5.5 账户与认证体系

ACCOUNTS_LOCAL_LOGIN_ENABLED = True
SECURITY_REGISTERABLE = True
SECURITY_RECOVERABLE = True
SECURITY_CHANGEABLE = True
SECURITY_CONFIRMABLE = True
SECURITY_LOGIN_WITHOUT_CONFIRMATION = False
OAUTHCLIENT_REMOTE_APPS = {}
ACCOUNTS_LOGIN_VIEW_FUNCTION = auto_redirect_login
OAUTHCLIENT_AUTO_REDIRECT_TO_EXTERNAL_LOGIN = False
USERPROFILES_READ_ONLY = False
USERS_RESOURCES_GROUPS_ENABLED = False
  • SECURITY_* 五连:注册(REGISTERABLE)、找回密码(RECOVERABLE)、改密(CHANGEABLE)、邮箱确认(CONFIRMABLE)全开;LOGIN_WITHOUT_CONFIRMATION = False 表示未确认邮箱的用户不能登录。实测行为:注册 tester@my-site.com 后登录被拦,页面 flash 原文 "Thank you. Confirmation instructions have been sent to tester@my-site.com."——而本实例未配 SMTP,确认邮件实际发不出去,形成"注册即锁死"。生产二选一:配好邮件(MAIL_SERVER/MAIL_PORT/MAIL_USERNAME/MAIL_PASSWORD/MAIL_DEFAULT_SENDER,Flask-Mail 系键,本实例未启用故不实测)或把该键设 True 免确认登录;
  • ACCOUNTS_LOCAL_LOGIN_ENABLED:本地账号总开关,接机构 SSO 后可关;实测本实例本地登录可用(root 登录 302 成功);
  • OAUTHCLIENT_REMOTE_APPS = {}:外部登录提供者注册表(ORCID/Keycloak/Shibboleth 等在此挂配置);空 dict = 只走本地。ACCOUNTS_LOGIN_VIEW_FUNCTION = auto_redirect_login 从 invenio_oauthclient.views.client 导入(cfg 实测 import 行),配合 OAUTHCLIENT_AUTO_REDIRECT_TO_EXTERNAL_LOGIN = False:当前不自动跳外部登录,配好远程应用后改 True 即登录页直跳机构 SSO;
  • USERPROFILES_READ_ONLY = False:允许用户在个人页面改姓名等档案;若机构档案源是权威身份系统应设 True 防互写;
  • USERS_RESOURCES_GROUPS_ENABLED = False:模板注释说明 groups 资源需额外配置故默认关;开启后 /api/users 侧暴露组信息,权限模型需同步审查。

5.6 存单表单、主题与管理面

APP_RDM_ADMIN_EMAIL_RECIPIENT = "info@my-site.com"
APP_RDM_DEPOSIT_FORM_DEFAULTS = {
    "publication_date": lambda: datetime.now().strftime("%Y-%m-%d"),
    "rights": [{"id": "cc-by-4.0", "title": "Creative Commons Attribution 4.0 International", ...(实测节选)}],
    "publisher": "My Site",
}
APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES = 'search'
BABEL_DEFAULT_LOCALE = 'en'
BABEL_DEFAULT_TIMEZONE = 'Europe/Zurich'
I18N_LANGUAGES = []
THEME_SITENAME = "My Site"
THEME_FRONTPAGE_TITLE = "My Site"
THEME_LOGO = 'images/invenio-rdm.svg'
INSTANCE_THEME_FILE = './less/theme.less'
ADMINISTRATION_DISPLAY_VERSIONS = [("invenio-app-rdm", f"v{__version__}"), ("my-site", "v1.0.0")]
  • APP_RDM_DEPOSIT_FORM_DEFAULTS:存单向导预填值。publication_date 用 lambda 每次取当天(%Y-%m-%d),rights 默认 CC-BY 4.0 完整对象,publisher 默认站名——机构库几乎必改 publisher 为本机构;
  • APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES = 'search':作者姓名框走词汇表搜索模式(可选 'search_only' 仅允许选词汇表规范名、'off' 关闭补全)。规范名数据由 invenio rdm fixtures 从 app_data 灌入(B2 篇 4.5(3));
  • APP_RDM_ADMIN_EMAIL_RECIPIENT:文件校验和不一致等系统告警收件人(cfg 注释原文),需与 SMTP 配置配套;
  • BABEL_DEFAULT_TIMEZONE = 'Europe/Zurich':界面时间显示时区(CERN 模板默认),中国机构改 'Asia/Shanghai';注意它只影响展示,统计事件时间戳另有 5.8 的 UTC 开关;
  • THEME_* / INSTANCE_THEME_FILE:站名进 <title>(实测首页 grep title 回显 <title>My Site</title>),Logo 路径相对 static,theme.less 是样式覆盖入口(构建期被 rspack 编译进资产);
  • ADMINISTRATION_DISPLAY_VERSIONS:Web 管理后台"版本"页展示串,第二项把实例自身版本 v1.0.0 也挂上,排障截图时自证版本。

5.7 DOI 注册与 OAI-PMH

DATACITE_ENABLED = False
DATACITE_USERNAME = ""
DATACITE_PASSWORD = ""
DATACITE_PREFIX = ""
DATACITE_TEST_MODE = True
DATACITE_DATACENTER_SYMBOL = ""

OAISERVER_ID_PREFIX = "my-site.com"
OAISERVER_ADMIN_EMAILS = ["info@my-site.com"]
  • DATACITE_* 六键:DOI 注册总开关与凭据。默认关闭(不注册 DOI,记录用内部 PID 如 x3kgj-3rt46)。启用流程:DataCite 会员/测试账号 → 填 USERNAME/PASSWORD/PREFIX(形如 10.5072)→ DATACITE_ENABLED = True;DATACITE_TEST_MODE = True 走 sandbox 前缀 10.5072,验证通过再关。DATACITE_DATACENTER_SYMBOL 供 Crossref 风格数据中心符号;
  • OAISERVER_ID_PREFIX:OAI-PMH 标识命名空间。实测生效证据:发布 x3kgj-3rt46 后 API 响应 pids.oai.identifier = "oai:my-site.com:x3kgj-3rt46"——前缀直接取自该键,格式 oai:<前缀>:<pid>;
  • ⚠️ 实测偏差记录:OAI-PMH HTTP 端点 GET /api/oai2h?verb=Identify 在本实例返回 404(Flask 标准 404 页原文见本专栏 API 使用详解篇),即 oai pid 已生成、收割端点未验证通过(路由或需额外配置/版本差异)。生产对接 Google Scholar/BASE 收割前,务必先按你实例的 invenio-oaiserver 版本实测端点,勿默认开箱可用。

5.8 资产构建、统计与日志

WEBPACKEXT_PROJECT = "invenio_assets.webpack:rspack_project"
WEBPACKEXT_NPM_PKG_CLS = "pynpm:PNPMPackage"
STATS_EVENTS_UTC_DATETIME_ENABLED = True
LOGGING_CONSOLE_LEVEL = "DEBUG"
  • WEBPACKEXT_PROJECT:前端资产打包工程指向 rspack(14.x 新默认,替代旧 webpack 项目串)。改主题/覆盖 React 组件后由 invenio webpack buildall 在镜像构建期编译(B2 篇 4.3 实测日志段);
  • WEBPACKEXT_NPM_PKG_CLS:JS 包管理器用 pnpm(pynpm:PNPMPackage,备选 pynpm:NPMPackage 即 npm)。与 .invenio 文件实测记录 javascript_package_manager = pnpm 一致,两者需匹配,否则构建期装依赖的锁文件类型对不上;
  • STATS_EVENTS_UTC_DATETIME_ENABLED = True:访问统计事件时间戳带时区信息(tz-aware UTC);设 False 则退化为 naive UTC(cfg docstring 原文说明 datetime.replace(tzinfo=None) 行为)。跨时区机构对账统计建议保持 True;
  • LOGGING_CONSOLE_LEVEL = "DEBUG":控制台日志级别。模板默认 DEBUG 便于开发,生产应降为 INFO 或 WARNING——实测本实例该级别下 worker/scheduler 日志滚动量大,排障友好但磁盘与噪音成本高。

六、生产配置模板

适用场景:单机 Docker Compose 全栈、8-16GB 内存、100GB+ 数据盘、机构科研数据仓储(部署流程见 《InvenioRDM Docker Compose 部署指南》)。模板给出"相对出厂值必须改"的最小改动集(cfg 键 + 对应 env 键),未列键保持出厂:

# ===== invenio.cfg 生产改动集(示意值,域名/邮箱按机构替换)=====
SECRET_KEY = "由环境变量注入,cfg 留占位即可"      # 实际生效见下方 env
TRUSTED_HOSTS = ['repo.example.org']               # 只放行真实域名
SITE_UI_URL = "https://repo.example.org"           # 与对外反代一致,含端口则必须带端口
SITE_API_URL = "https://repo.example.org/api"

BABEL_DEFAULT_LOCALE = 'en'                        # 中文界面可加 I18N_LANGUAGES = [('zh', _('Chinese'))]
BABEL_DEFAULT_TIMEZONE = 'Asia/Shanghai'
THEME_SITENAME = "机构科研数据仓储"
THEME_LOGO = 'images/my-logo.svg'

APP_RDM_ADMIN_EMAIL_RECIPIENT = "repo-ops@example.org"
APP_RDM_DEPOSIT_FORM_DEFAULTS = {"publisher": "Example University"}  # rights/publication_date 两键沿用出厂结构(见 5.6)

# 邮箱确认与登录(二选一)
SECURITY_CONFIRMABLE = True
SECURITY_LOGIN_WITHOUT_CONFIRMATION = False        # 保持 False 的前提:SMTP 已配好
MAIL_SERVER = "smtp.example.org"
MAIL_PORT = 465
MAIL_USE_SSL = True
MAIL_USERNAME = "repo@example.org"
MAIL_PASSWORD = "(注入方式:改用 INVENIO_MAIL_PASSWORD 环境变量,勿提交进版本库)"
MAIL_DEFAULT_SENDER = "repo@example.org"

# DOI(有 DataCite 账号再开)
DATACITE_ENABLED = True
DATACITE_PREFIX = "10.12345"                        # 形如 10.x 的四段式前缀,账号开通时由 DataCite 分配
DATACITE_TEST_MODE = False                         # 先 True 走 sandbox 验证再切 False

# 检索与日志
SEARCH_INDEX_PREFIX = "repo-"
LOGGING_CONSOLE_LEVEL = "INFO"
# ===== docker-services.yml app 段环境变量生产改动集 =====
environment:
  - "INVENIO_SECRET_KEY=(宿主 openssl rand -hex 32 生成,经部署密钥管理注入)"
  - "INVENIO_SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://my-site:<强密码>@db/my-site"
  - "INVENIO_SITE_UI_URL=https://repo.example.org"
  - "INVENIO_SITE_API_URL=https://repo.example.org/api"
  - "INVENIO_MAIL_PASSWORD=(同上,敏感值不进 compose 明文)"

配套动作(实测/官方口径):

  1. 证书替换:docker/nginx/ 内 test.crt/test.key 换真实证书后重建 frontend 镜像(出厂自签仅限调试,B2 篇 11.7);
  2. db 服务 POSTGRES_PASSWORD 与连接串同步改强密码;
  3. HSTS(5.4)已默认一年 max-age——确认证书自动续期(如 certbot/acme)就绪后再对真实域名开放;
  4. 改动全部经 invenio-cli containers build + up -d 生效(3.3 表)。

💡 技术拓展:InvenioRDM 敏感值注入渠道对比——

渠道特点适用
compose environment 明文简单,值进版本库风险本地开发(本实测口径)
compose env_file / .env文件隔离,可 gitignore单机生产(推荐起步)
secrets(Swarm/K8s)运行时挂载,不落镜像集群化生产
cfg 硬编码随镜像分发,最不安全禁止

本实例实测走第一种(CHANGE_ME 占位),生产按表中后两种收敛。

七、常见问题

7.1 改了 invenio.cfg 却不生效

按序排查(均为本实例实测过的机制):

  1. 镜像没重建:cfg 是构建期 COPY 进镜像的(3.1 表),只改项目文件不 build 等于没改——容器内 ls -l /opt/invenio/var/instance/invenio.cfg 比对时间戳/尺寸验证;
  2. 被环境变量压住:env | grep INVENIO_ 看是否有同名 INVENIO_<键> 覆盖(实测 SITE_UI_URL 即此情况);
  3. 服务没重建:改 env 后需 up -d web-api web-ui worker scheduler(容器 recreate 才注入新 env),restart 不重读 compose 文件变更。

7.2 登录后跳转丢端口(https://127.0.0.1/login/)

INVENIO_SITE_UI_URL 未含 :8138 所致(实测 308 Location 丢端口,5.3 节)。调试期把 env 两键改为带端口值并 up -d 重建应用服务;生产经标准 443 反代则保持不带端口。

7.3 SECRET_KEY=CHANGE_ME 直接上生产会怎样

会话与令牌用公开占位符签名,等同无保护(5.1)。必须注入随机值;变更后旧会话全部失效属预期现象。

7.4 上传文件报 500,想靠配置一个"存储路径"解决

v14 的文件 location 不是 cfg 配置项,是数据库对象:实测必须执行 invenio files location create local /opt/invenio/var/instance/data --default(回显与原理见 B2 篇 4.5(6))。invenio.cfg 里没有任何键能替代这条 CLI;换 S3 后端走 s3 extra 与对应配置文档,属另一套机制。

7.5 注册用户无法登录(确认邮件发不出去)

SECURITY_CONFIRMABLE=True + SECURITY_LOGIN_WITHOUT_CONFIRMATION=False 且未配 SMTP 的组合(实测 flash 原文见 5.5)。生产配 MAIL_* 五键;测试环境可临时 INVENIO_SECURITY_LOGIN_WITHOUT_CONFIRMATION=true 环境变量覆盖免确认(管理员也可容器内 invenio users activate <邮箱> 激活)。

7.6 改 SEARCH_INDEX_PREFIX 后检索 404 / 空结果

前缀即命名空间(5.2):改前缀后旧数据仍在旧索引名下,应用只认新前缀。需 invenio index init 建新索引并触发记录重索引;多实例共栈时各实例前缀必须互不相同。

7.7 上传大文件被 CSP 或体积限制拦截

两层:应用层 CSP script-src 必须保留 blob: 'wasm-unsafe-eval'(5.4,删了分片哈希 Worker 直接报错);nginx 层文件上传路由单独 client_max_body_size 50G、其余路由 100m(B2 篇 nginx 配置实测内容)。改体积上限改 nginx 配置并重建 frontend 镜像,cfg 无对应键。

7.8 OAI-PMH 端点 404 但记录里有 oai pid

实测状态如实记录:OAISERVER_ID_PREFIX 生效(发布响应含 oai:my-site.com:x3kgj-3rt46),但 /api/oai2h?verb=Identify 返回 404。说明 pid 生成与收割端点是两条独立链路;对接收割前需按实例的 invenio-oaiserver 版本核对路由挂载(端点路径/启用方式),勿以"有 pid"推断"可收割"。

八、参考链接

  1. 官方配置定制文档(cfg 全量键出处):https://inveniordm.docs.cern.ch/operate/customize/configuration/ (查询日期 2026-11-01)
  2. invenio-app-rdm 配置源码(APP_RDM_* 默认值):https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/config.py
  3. invenio-accounts 配置(SECURITY_/ACCOUNTS_):https://github.com/inveniosoftware/invenio-accounts/blob/master/invenio_accounts/config.py
  4. invenio-oauthclient 配置:https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py
  5. invenio-oaiserver 配置:https://github.com/inveniosoftware/invenio-oaiserver/blob/master/invenio_oaiserver/config.py
  6. DOI 定制(DATACITE_*):https://inveniordm.docs.cern.ch/operate/customize/dois/
  7. 认证定制(本地/外部登录):https://inveniordm.docs.cern.ch/operate/customize/authentication/
  8. flask-webpackext 配置(WEBPACKEXT_*):https://github.com/inveniosoftware/flask-webpackext/blob/master/flask_webpackext/config.py
  9. Flask 配置(SECRET_KEY/TRUSTED_HOSTS/SEND_FILE_MAX_AGE_DEFAULT):https://flask.palletsprojects.com/en/2.1.x/config/
  10. 站内姊妹篇:《InvenioRDM 介绍与选型指南》、《InvenioRDM Docker Compose 部署指南》
InvenioRDM 14.0.6 配置参数详解 - Quzuo