InvenioRDM 14.0.6 配置参数详解
InvenioRDM 14.0.6 实例配置 invenio.cfg 逐段详解(Flask 基座/安全响应头/账户认证/存单表单/DOI 与 OAI/检索前缀/资产构建/日志统计约 40 个配置键),实测验证 INVENIO_* 环境变量三层覆盖机制与配置生效路径,附生产配置模板与 8 条配置类 FAQ。
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/),命令与回显均为实测。
一、环境信息
| 项目 | 实测值 |
|---|---|
| InvenioRDM | invenio-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")。
二、前置条件
- 已按 《InvenioRDM Docker Compose 部署指南》 完成 14.0.6 全栈部署与初始化(10 服务 Up、DB/索引/fixtures 就绪);
- 能进入应用服务执行命令:
cd /opt/invenio-rdm/my-site
docker compose -f docker-compose.full.yml exec web-api bash
# 容器内工作目录 /opt/invenio/src,实例目录 /opt/invenio/var/instance
- 验证配置文件确已随镜像构建进容器(实测回显,尺寸与项目源文件一致):
$ 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 三层配置来源与优先级
| 层 | 载体 | 位置 | 优先级 |
|---|---|---|---|
| 1 | invenio.cfg | 项目源文件 → 构建期 COPY 进镜像 → 容器内 /opt/invenio/var/instance/invenio.cfg | 基线 |
| 2 | INVENIO_<键名> 环境变量 | docker-services.yml app 段 environment(compose 注入) | 覆盖 cfg 同名键 |
| 3 | site 包 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.cfg | invenio-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 重建应用服务即可,无需重 build | compose 层变更,镜像不动 |
| 数据库类配置(location、角色、令牌) | 走 invenio CLI 而非 cfg | 实测:文件 location 存 DB,cfg 无法声明(见 7.4) |
⚠️ 注意:改了 cfg 但没重建镜像、或同名键被
INVENIO_*环境变量压住,是"配置不生效"两大高频原因,排查顺序见第七章。
四、参数总览
invenio.cfg 实测共 246 行、约 40 个配置键,按所属模块分组总览("当前值"即本实例实测值,"默认/出厂"指 invenio-cli 模板生成值):
| 分组 | 配置键 | 当前值 | 作用一句话 |
|---|---|---|---|
| Flask 基座 | SECRET_KEY | CHANGE_ME(被 env 覆盖) | 会话/令牌签名密钥,生产必改 |
| Flask 基座 | TRUSTED_HOSTS | ['0.0.0.0','localhost','127.0.0.1'] | 可信 Host 白名单 |
| Flask 基座 | SEND_FILE_MAX_AGE_DEFAULT | 300 | 静态文件浏览器缓存秒数 |
| 数据库 | SQLALCHEMY_DATABASE_URI | postgresql+psycopg2://my-site:my-site@localhost/my-site(被 env 覆盖为 @db/) | 关系库连接串 |
| 安全头 | APP_DEFAULT_SECURE_HEADERS | 14 子键(CSP/HSTS/HTTPS 强制等) | nginx 之外的应用层安全响应头 |
| 国际化 | BABEL_DEFAULT_LOCALE / BABEL_DEFAULT_TIMEZONE | en / Europe/Zurich | 默认语言与时区 |
| 国际化 | I18N_LANGUAGES | [](模板注释示例 de/tr) | 附加界面语言 |
| 主题 | THEME_SITENAME / THEME_FRONTPAGE_TITLE / THEME_LOGO | My Site / My Site / images/invenio-rdm.svg | 站名、首页标题、Logo |
| 主题 | INSTANCE_THEME_FILE | ./less/theme.less | 主题覆盖入口(相对 assets/) |
| RDM 表单 | APP_RDM_DEPOSIT_FORM_DEFAULTS | publication_date=当天、rights=cc-by-4.0、publisher=My Site | 存单表单默认值 |
| RDM 表单 | APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES | 'search' | 作者姓名自动补全模式 |
| RDM 邮件 | APP_RDM_ADMIN_EMAIL_RECIPIENT | info@my-site.com | 管理告警收件人(校验和告警等) |
| 站点 URL | SITE_UI_URL / SITE_API_URL | https://127.0.0.1:5000(被 env 覆盖为无端口版) | 绝对链接生成基址 |
| DOI | DATACITE_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_ONLY | False | 允许用户自改档案 |
| 用户资源 | USERS_RESOURCES_GROUPS_ENABLED | False | 关闭需额外配置的 groups 资源 |
| OAI | OAISERVER_ID_PREFIX / OAISERVER_ADMIN_EMAILS | my-site.com / [info@my-site.com] | OAI-PMH 标识前缀与管理邮箱 |
| 检索 | SEARCH_INDEX_PREFIX | my-site- | 索引名前缀隔离 |
| 管理后台 | ADMINISTRATION_DISPLAY_VERSIONS | invenio-app-rdm v14.0.6 + my-site v1.0.0 | 后台展示版本串 |
| 资产构建 | WEBPACKEXT_PROJECT / WEBPACKEXT_NPM_PKG_CLS | rspack_project / pynpm:PNPMPackage | 前端打包器与包管理器 |
| 统计 | STATS_EVENTS_UTC_DATETIME_ENABLED | True | 访问统计事件用时区感知 UTC |
| 日志 | LOGGING_CONSOLE_LEVEL | DEBUG | 控制台日志级别 |
💡 说明:表中"被 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 中,由 envINVENIO_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-src | self/data:/unsafe-inline/blob: | 资源默认只允许同源;data: 供字体、blob: 供 PDF 预览、unsafe-inline 放行内联脚本样式(cfg 注释逐项说明)。定制主题加外部资源(如分析脚本)必须在此追加来源,否则被浏览器拦截 |
| CSP script-src | self/blob:/wasm-unsafe-eval | 多文件上传用 Web Worker 跑 hash-wasm 计算分片 MD5,blob: 与 wasm-unsafe-eval 缺一不可(cfg 注释原文),精简 CSP 会直接打断大文件上传 |
| content_security_policy_report_only | False | CSP 违规是拦截而非仅上报;True 可作灰度观察模式 |
| force_https | True | 非 HTTPS 请求强制跳 https;配合 nginx 80 端口 return 301 https:// 双层兜底 |
| force_https_permanent | False | True 则 301 永久跳,False 用临时跳(避免测试期被浏览器永久缓存) |
| frame_options | sameorigin | 禁外站 iframe 嵌页(防点击劫持);要在门户里内嵌记录页需改 None 并配 CSP frame-ancestors |
| session_cookie_http_only / secure | True / True | 会话 cookie 禁 JS 读取、仅 HTTPS 传输——实测 http 访问会被 force_https 弹回,cookie 属性与之一致 |
| strict_transport_security 三键 | True / True / 31556926 | HSTS 开启、含子域、max-age 一年(cfg 注释:"One year in seconds")。⚠️ 一旦真实域名下发 HSTS,浏览器一年内强制只走 HTTPS,证书到期不续也进不去,上生产前确保证书自动续期就绪 |
| strict_transport_security_preload | False | 不申请 HSTS preload 列表(申请后不可逆,慎开) |
💡 技术拓展:HTTPS 与 HSTS 参数常见取值策略——
策略 max-age preload 适用 测试观察 短(分钟级) 否 域名刚上 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 明文)"
配套动作(实测/官方口径):
- 证书替换:
docker/nginx/内 test.crt/test.key 换真实证书后重建 frontend 镜像(出厂自签仅限调试,B2 篇 11.7); - db 服务
POSTGRES_PASSWORD与连接串同步改强密码; - HSTS(5.4)已默认一年 max-age——确认证书自动续期(如 certbot/acme)就绪后再对真实域名开放;
- 改动全部经
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 却不生效
按序排查(均为本实例实测过的机制):
- 镜像没重建:cfg 是构建期 COPY 进镜像的(3.1 表),只改项目文件不 build 等于没改——容器内
ls -l /opt/invenio/var/instance/invenio.cfg比对时间戳/尺寸验证; - 被环境变量压住:
env | grep INVENIO_看是否有同名INVENIO_<键>覆盖(实测 SITE_UI_URL 即此情况); - 服务没重建:改 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"推断"可收割"。
八、参考链接
- 官方配置定制文档(cfg 全量键出处):https://inveniordm.docs.cern.ch/operate/customize/configuration/ (查询日期 2026-11-01)
- invenio-app-rdm 配置源码(APP_RDM_* 默认值):https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/config.py
- invenio-accounts 配置(SECURITY_/ACCOUNTS_):https://github.com/inveniosoftware/invenio-accounts/blob/master/invenio_accounts/config.py
- invenio-oauthclient 配置:https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py
- invenio-oaiserver 配置:https://github.com/inveniosoftware/invenio-oaiserver/blob/master/invenio_oaiserver/config.py
- DOI 定制(DATACITE_*):https://inveniordm.docs.cern.ch/operate/customize/dois/
- 认证定制(本地/外部登录):https://inveniordm.docs.cern.ch/operate/customize/authentication/
- flask-webpackext 配置(WEBPACKEXT_*):https://github.com/inveniosoftware/flask-webpackext/blob/master/flask_webpackext/config.py
- Flask 配置(SECRET_KEY/TRUSTED_HOSTS/SEND_FILE_MAX_AGE_DEFAULT):https://flask.palletsprojects.com/en/2.1.x/config/
- 站内姊妹篇:《InvenioRDM 介绍与选型指南》、《InvenioRDM Docker Compose 部署指南》