Audiobookshelf 2.37.2 配置参数详解
Audiobookshelf 2.37.2 配置三层体系详解:PORT/ROUTER_BASE_PATH/CONFIG_PATH 等环境变量源码级默认值、SSRF 白名单精确匹配、令牌三件套与登录限速、serverSettings 全量字段实测对照(备份/扫描/播客调度/认证/反代)、用户权限体系与 isActive 默认未激活双坑排障实录(2026-10-27 实测)。
Audiobookshelf 2.37.2 配置参数详解
目标:把 Audiobookshelf 2.37.2 的全部配置面讲清楚——从服务启动时读取的环境变量(端口、路径、SSRF 策略、令牌有效期、登录限速),到存在数据库中的 serverSettings(扫描、备份、元数据存储、登录页、权限),再到 Web 管理端与两者的映射关系。本文环境变量默认值与行为均取自 2.37.2 服务端程序源码取证(
index.js与server/Server.js等,2026-10-27),serverSettings 取自运行实例的真实回显,并附两处实测踩到的「新建对象默认未激活」类配置坑。部署过程见《Audiobookshelf 2.37.2 Docker Compose 部署实战》,API 调用细节见《Audiobookshelf 2.37.2 常用 API 与运维实战》。
一、环境信息
本篇为实测 + 源码取证篇:
| 项目 | 值 |
|---|---|
| 取证日期 | 2026-10-27 |
| 服务版本 | 2.37.2(官方最新稳定版) |
| 部署形态 | 官方 Compose 编排(详见部署篇),单实例 |
| 源码取证位置 | 服务端程序 index.js(启动参数)、server/Server.js(SSRF/超时)、server/auth/TokenManager.js(令牌)、server/utils/rateLimiterFactory.js(限速)、server/objects/settings/ServerSettings.js(设置模型) |
| 运行实例 | 已完成初始化:root 账号、有声书库 + 播客库、已产生播放会话与一份备份 |
| 实测回显来源 | PATCH /api/settings(修改备份策略)、GET /api/settings(经授权接口读取)、用户与 API Key 的创建/激活接口 |
二、配置体系总览
Audiobookshelf 的配置分三层,改动方式与生效机制各不相同:
| 层 | 载体 | 改动方式 | 生效机制 |
|---|---|---|---|
| 环境变量 | 服务启动进程环境 | 部署清单(Compose 的 environment)或 Debian 包的配置文件 | 重启服务后生效,运行期不可改 |
| 服务器设置 | SQLite 库 settings 表(serverSettings 对象) | Web 管理端各设置页;API PATCH /api/settings | 即时生效,无需重启(部分项如端口类本就不在此层) |
| 库/用户级 | 各库、各用户记录 | Web 管理端库设置/用户管理;对应 API | 即时生效 |
💡 技术拓展:把「运行期可变配置」放数据库、「部署期固定配置」放环境变量,是自托管服务的常见分层。主要选项对比——
方案 原理/特点 适用场景 环境变量(12-Factor) 部署即固化,改值需重启,便于编排声明式管理 端口、路径、密钥等基础项 数据库存储(运行时可变) 管理界面即改即生效,随数据一起备份 业务策略类(调度、限速、展示) 配置文件(YAML/JSON) 可版本化、可评审,改后一般需重载 复杂结构化配置、GitOps 流程 Audiobookshelf 的取舍:环境变量只留「无它无法启动」的项(端口/路径/二进制/密钥),其余全部进数据库层由管理端管理——因此本文重点是「环境变量清单 + serverSettings 字段对照」两条线。
三、环境变量详解
3.1 启动与路径类
| 变量 | 默认值(2.37.2 实测源码) | 说明 |
|---|---|---|
PORT | 3333(index.js:options.port || process.env.PORT || 3333) | 服务监听端口。官方文档约定 13378,用 Compose 时必须显式设置,否则映射 13378 会落空(部署篇案例 1) |
HOST | 不绑定(监听全部接口) | 绑定特定网卡地址时设置 |
CONFIG_PATH | ./config | 业务数据目录:SQLite 库 absdatabase.sqlite 与 migrations/。Compose 形态挂载为 /config,必须持久化 |
METADATA_PATH | ./metadata | 元数据目录:logs/、items/、authors/、cache/、streams/(转码临时)、backups/(备份产物)。Compose 形态挂载为 /metadata,必须持久化 |
ROUTER_BASE_PATH | /audiobookshelf(index.js:process.env.ROUTER_BASE_PATH ?? '/audiobookshelf') | URL 基础路径。v2.37.2 起自动规范化(补前导斜杠、去尾斜杠);反代子路径场景与它对齐 |
SOURCE | debian(Debian 包)/ 发行镜像内置值 | 标识安装来源,仅用于展示与日志 |
BACKUP_PATH | 默认在 METADATA_PATH 下 backups/ | 备份产物落盘目录的显式覆盖;也可在管理端改(backupPath) |
启动日志会打印全部生效值,是核对配置的第一现场(部署篇实测回显):
[2026-10-27 23:47:07.885] INFO: [Server] Serving from base path "/audiobookshelf"
[2026-10-27 23:47:07.910] INFO: Listening on port :13378
3.2 SSRF 出网防护类
Audiobookshelf 对「服务端发起的 HTTP 请求」(播客订阅源、封面抓取等)内置 SSRF 过滤器,默认拦截解析到私网/环回地址的目标。2.37.2 源码(server/Server.js)给出两档放行:
| 变量 | 默认 | 说明 |
|---|---|---|
SSRF_REQUEST_FILTER_WHITELIST | 空(全拦截私网) | 逗号分隔的主机名白名单。匹配逻辑为主机名精确相等:源码 whitelistedUrls.includes(new URL(url).hostname),所以填 podcast-source 只放行 URL 主机名恰好是 podcast-source 的请求,带端口、协议、路径都不参与匹配 |
DISABLE_SSRF_REQUEST_FILTER | 未设 | 设为 1 整体关闭过滤器。仅建议在完全可信的内网隔离环境使用 |
生效时启动日志会打印确认行(部署篇实测回显):
[2026-10-27 23:47:07.726] INFO: [Server] SSRF Request Filter Whitelisting: podcast-source
⚠️ 避坑:白名单放行「域名解析到私网」的前提是该主机名能解析。编排内自建源必须先把别名注册进网络(部署篇案例 4,缺失时报
getaddrinfo EAI_AGAIN),白名单本身不解决解析问题。
3.3 播客任务类
| 变量 | 默认值 | 说明 |
|---|---|---|
PODCAST_DOWNLOAD_TIMEOUT | 30000(30 秒,源码 toNumber 读取) | 单集下载/源抓取的超时毫秒数。慢速外网源可适当调大 |
MAX_FAILED_EPISODE_CHECKS | 24 | 源连续失败多少次后自动停用该播客的自动下载(autoDownloadEpisodes 置 false),设为 0 表示永不自动停用 |
3.4 认证与安全类
| 变量 | 默认值 | 说明 |
|---|---|---|
ACCESS_TOKEN_EXPIRY | 3600(1 小时) | 访问令牌有效期(秒)。登录接口返回的 JWT 即此有效期 |
REFRESH_TOKEN_EXPIRY | 2592000(30 天) | 刷新令牌有效期;设为 0 可关闭刷新机制 |
REFRESH_TOKEN_GRACE_PERIOD | 600(10 分钟) | 旧刷新令牌的宽限期(秒),应对刷新瞬间并发请求 |
JWT_SECRET_KEY | 未设时自动生成并入库 | 令牌签名密钥。多实例共享数据库时必须显式设置同一个值,否则各实例签发的令牌互不认账 |
RATE_LIMIT_AUTH_MAX | 40(rateLimiterFactory.js DEFAULT_MAX) | 登录等认证端点的限速次数;设为 0 关闭限速 |
RATE_LIMIT_AUTH_WINDOW | 默认窗口(毫秒) | 限速统计窗口 |
RATE_LIMIT_AUTH_MESSAGE | 默认文案 | 触发限速时返回的提示 |
ALLOW_IFRAME | 未设 | 设为 1 允许页面被 iframe 嵌入(默认响应 X-Frame-Options: DENY 类防护) |
USE_X_ACCEL | 未设 | 反代场景设置为一个路径前缀(如 /internal/),音频/封面等静态文件走 nginx X-Accel-Redirect 内部重定向,避免大文件流经应用层 |
💡 技术拓展:「令牌三件套」(访问令牌短时效 + 刷新令牌长时效 + 宽限期)与「登录限速」是 Web 服务的标准安全配置组合。Audiobookshelf 自 v2.26.0 重构认证体系后完整具备这两组能力,并支持 OpenID Connect 对接(管理端「设置 → 认证」页配置,相关字段见 4.3)。
3.5 二进制与内部路径类
| 变量 | 说明 |
|---|---|
FFMPEG_PATH / FFPROBE_PATH | 音频转码与探测工具路径。官方发行产物内置二进制,通常无需设置;SKIP_BINARIES_CHECK=1 可跳过启动时的二进制自检(自行定制环境时用) |
FLVTOOL2_PATH / FLVMETA_PATH | FLV 处理工具(特殊场景),一般不涉及 |
NUSQLITE3_PATH | SQLite 扩展路径(unaccent/Unicode 折叠能力),发行产物内置 |
QUERY_LOGGING / QUERY_PROFILING | 数据库查询日志/性能剖析开关(排障用) |
四、服务器设置(serverSettings)与管理端对照
4.1 实测全量字段
对运行实例执行修改备份策略的操作(PATCH /api/settings),返回的 serverSettings 实测字段全集如下(2.37.2):
id, scannerFindCovers, scannerCoverProvider, scannerParseSubtitle, scannerPreferMatchedMetadata,
scannerDisableWatcher, storeCoverWithItem, storeMetadataWithItem, metadataFileFormat,
rateLimitLoginRequests, rateLimitLoginWindow, allowIframe,
backupPath, backupSchedule, backupsToKeep, maxBackupSize,
loggerDailyLogsToKeep, loggerScannerLogsToKeep,
homeBookshelfView, bookshelfView, podcastEpisodeSchedule, sortingIgnorePrefix, sortingPrefixes,
chromecastEnabled, dateFormat, timeFormat, language, allowedOrigins, logLevel,
version, buildNumber, authLoginCustomMessage, authActiveAuthMethods,
authOpenIDIssuerURL, authOpenIDAuthorizationURL, authOpenIDTokenURL, authOpenIDUserInfoURL,
authOpenIDJwksURL, authOpenIDLogoutURL, authOpenIDTokenSigningAlgorithm, authOpenIDButtonText,
authOpenIDAutoLaunch, authOpenIDAutoRegister, authOpenIDMatchExistingBy, timeZone
关键字段的实测值(修改后回显):
backupSchedule = 0 2 * * *
backupsToKeep = 14
language = zh-cn
scannerPreferMatchedMetadata = False
scannerFindCovers = False
scannerCoverProvider = google
scannerDisableWatcher = False
storeCoverWithItem = False
storeMetadataWithItem = False
metadataFileFormat = json
logLevel = 2
rateLimitLoginRequests = 10
rateLimitLoginWindow = 600000
sortingPrefixes = ['the', 'a']
podcastEpisodeSchedule = 0 * * * *
4.2 按功能域对照(Web 管理端 ↔ 字段)
| 功能域 | Web 管理端位置 | 关键字段 | 说明 |
|---|---|---|---|
| 扫描策略 | 设置 → 扫描 | scannerPreferAudioMetadata / scannerPreferOpfMetadata / scannerPreferMatchedMetadata | 三档元数据优先级:文件内嵌标签 > OPF > 在线匹配,实测默认关(按文件名/内嵌标签) |
| 封面抓取 | 设置 → 扫描 | scannerFindCovers、scannerCoverProvider | 默认关闭;提供方实测默认 google,可换 |
| 实时监听 | 设置 → 扫描 | scannerDisableWatcher | 默认 false 即开启文件监听——媒体目录有新文件时自动扫描,不需要手动触发 |
| 备份策略 | 设置 → 备份 | backupSchedule(cron)、backupsToKeep、maxBackupSize、backupPath | 默认关闭自动备份(实测初始日志 Auto Backups are disabled);本篇实测改为 0 2 * * *(每天 02:00)+ 保留 14 份 |
| 播客检查 | 设置 → 播客 | podcastEpisodeSchedule | 订阅源新单集检查周期,实测默认每小时(0 * * * *);注意只抓「上次检查之后发布」的单集(见第六节) |
| 日志保留 | 设置 → 日志 | loggerDailyLogsToKeep、loggerScannerLogsToKeep | 日志滚动保留份数,落盘于 METADATA_PATH/logs/ |
| 界面与格式 | 设置 → 通用 | language、dateFormat、timeFormat、homeBookshelfView、bookshelfView | 实测语言已切 zh-cn 即时生效 |
| 排序前缀 | 设置 → 通用 | sortingIgnorePrefix、sortingPrefixes | 排序时忽略的前缀(默认 the、a),中文环境一般用不到 |
| 反向代理 | 部署层 + 设置 | ROUTER_BASE_PATH(环境变量)、allowedOrigins、USE_X_ACCEL(环境变量) | 子路径反代对齐基础路径;allowedOrigins 控制跨域白名单;大文件下载走 X-Accel 内部重定向 |
| 认证方式 | 设置 → 认证 | authActiveAuthMethods、authLoginCustomMessage、authOpenID* 全家桶 | 默认 ["local"](实测 /status 回显 authMethods:["local"]);OIDC 各 URL 由服务端自动发现填充 |
| 其他开关 | — | chromecastEnabled(投屏)、storeCoverWithItem/storeMetadataWithItem(元数据随媒体文件存放)、allowIframe | 按需开启 |
4.3 用户权限体系
用户模型 = 类型(type)+ 权限对象(permissions)+ 激活状态(isActive)。实测两份真实记录:
root | type: root | isActive: True
permissions: {"download": true, "update": true, "delete": true, "upload": true,
"createEreader": true, "accessAllLibraries": true, "accessAllTags": true,
"accessExplicitContent": true, "selectedTagsNotAccessible": false}
family | type: user | isActive: True
permissions: {"download": true, "update": false, "delete": false, "upload": false,
"createEreader": false, "accessAllLibraries": false, "accessAllTags": true,
"accessExplicitContent": false, "selectedTagsNotAccessible": false}
设计要点:
- 类型四档:root(全部权力,唯一)、admin(库管理)、user(普通使用者)、guest(只读浏览)。
- 权限按位拆分:下载/上传/改/删、是否可见全部库(
accessAllLibraries=false时按selectedLibraries限定)、敏感内容(accessExplicitContent)、标签可见性。 isActive是独立开关:可「封禁」一个账号而不删除(保留其播放进度与书签)。
⚠️ 避坑:新建用户与新建 API Key 默认
isActive=false(创建后需显式激活才能登录/调用)。本篇实测中,新建用户未激活时登录返回 401,PATCH 激活后同一凭据立即登录成功——这是「密码没错却登不上」的头号排查项。API Key 的同名坑见第六节。
五、配置修改实测
管理端改配置的 API 等效操作是 PATCH /api/settings。实测把备份策略从关闭改为「每天 02:00、保留 14 份」:
curl -s -X PATCH http://127.0.0.1:8137/api/settings \
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
-d '{"backupSchedule":"0 2 * * *","backupsToKeep":14,"serverTimeZone":"Asia/Shanghai","language":"zh-cn"}' \
-o /tmp/patch_settings.out -w 'HTTP %{http_code}\n'
实测回显:HTTP 200,响应体携带更新后的完整 serverSettings(其中 backupSchedule=0 2 * * *、backupsToKeep=14 已生效)。注意两点:
- 读取设置的通道是
POST /api/authorize(返回当前用户 + 全量 serverSettings,Web 端加载设置页即用此接口);PATCH /api/settings只写不读,GET /api/settings在 2.37.2 不存在(实测 404)。 - 时区字段在 serverSettings 里叫
timeZone(不是 serverTimeZone),与直觉不同,脚本化改配置时容易踩。
六、排障实录
案例 1:新建用户密码正确却 401(isActive 默认未激活)
- 现象:
POST /api/users创建用户family(响应体明确显示"isActive":false),用其凭据调/login返回 401。 - 定位:2.37.2 的用户创建逻辑对
isActive取!!req.body.isActive——创建请求不显式传 true 就是不激活。 - 处置:
PATCH /api/users/<id>传{"isActive":true}激活。实测激活后同一凭据登录立即返回 200 与令牌。 - 教训:自动化创建账号的脚本必须在创建或激活步骤显式处理
isActive,否则产出一批「死号」。
案例 2:API Key 创建成功却 401(同款 isActive 坑 + 旧 userId)
- 现象:
POST /api/api-keys两次失败两次成功——先因 body 缺userId返回 400;改用记忆中的 userId 又报User not found(那是重建数据目录前旧实例的 id,用户表里已不存在);最终从/api/me取当前真实 id 才创建成功,但调用仍 401,因为响应里isActive:false。 - 根因:API Key 与用户一样,创建时默认未激活(
isActive: !!req.body.isActive)。另外 API Key 的name与expiresIn被写进签发的 JWT,创建后改名与改有效期都不可行(源码注释明示仅isActive和userId可更新)。 - 处置:创建请求直接带
"isActive":true(或事后 PATCH)。实测激活后的 Key 以Authorization: Bearer <apiKey>调用/api/libraries返回 200 与库列表。 - 教训:涉及「新建即用」的对象,先看响应体里的
isActive再发请求;跨重建的 id 不能凭记忆引用,一律实时查询。
案例 3:SSRF 白名单写了却不放行(精确匹配)
- 现象:已设
SSRF_REQUEST_FILTER_WHITELIST,订阅私网源仍被拦。 - 定位:源码匹配逻辑是
new URL(url).hostname与白名单项全等比较——白名单填http://podcast-source:8000这类「URL 形式」反而永不匹配。 - 处置:白名单只写主机名本身(
podcast-source),多个用逗号分隔。实测修正后预检通过(HTTP 200,返回源标题与单集列表)。 - 教训:环境变量的语义要看实现——「白名单」的主语是主机名而非 URL。
案例 4:自动备份以为开着,实际初始是关的
- 现象:以为内置备份默认可用,首次查看服务日志发现
INFO: [BackupManager] Auto Backups are disabled。 - 根因:
backupSchedule默认为空(不调度),POST /api/backups的手动备份随时可用,但定时备份需要显式配置。 - 处置:按第五节实测改
backupSchedule+backupsToKeep;配置后核对响应字段确认生效。 - 教训:「有备份功能」不等于「备份在跑」,部署收尾动作里应包含备份策略配置 + 首份手动备份验证(部署篇第六节)。
七、常见问题 FAQ
Q1:改了环境变量为什么没生效?
环境变量是启动期配置,重启服务实例才生效;改完重启后看启动日志的 Serving from base path 与 Listening on port 两行核对实际值。
Q2:管理端设置和 API 改的是同一份吗?
是。Web 管理端各设置页最终都落到同一 serverSettings 对象;PATCH /api/settings 是它的 API 等效。修改即时生效,随 /config 一起被备份。
Q3:库扫描计划在哪里配?
扫描本身由「文件监听(Watcher)」驱动(scannerDisableWatcher=false 时新文件自动入库),无需 cron;播客单集检查才用 cron 字段 podcastEpisodeSchedule(默认每小时)。
Q4:OpenID Connect 怎么开?
管理端「设置 → 认证」填 Issuer URL 后服务端自动发现各端点(authOpenID* 字段回显),可选自动注册(authOpenIDAutoRegister)与自动跳转(authOpenIDAutoLaunch);启用后 authActiveAuthMethods 会加入 openid。
Q5:多实例/迁移时 JWT 密钥要注意什么?
未设置 JWT_SECRET_KEY 时密钥自动生成存在 serverSettings 里——单实例没问题;共享库或迁移后要求旧令牌继续有效,就显式设置同一个 JWT_SECRET_KEY。
八、本篇小结
- 配置三层:环境变量(启动期,重启生效)→ serverSettings(数据库层,即改即生效)→ 库/用户级。
- 环境变量必会项:
PORT(默认 3333,务必显式)、ROUTER_BASE_PATH(默认 /audiobookshelf)、CONFIG_PATH/METADATA_PATH(必须持久化)、SSRF 白名单(主机名精确匹配)。 - 安全四件套:令牌三件套(1h/30d/10min)+ 登录限速(40 次/窗口,可 0 关闭)。
- serverSettings 高频字段:备份(backupSchedule/backupsToKeep/maxBackupSize)、扫描(scanner*)、播客(podcastEpisodeSchedule)、认证(authActiveAuthMethods/authOpenID*)。
- 实测双坑:新建用户与 API Key 默认
isActive=false;时区字段名是timeZone。
九、参考链接
- 官方文档(配置与指南):https://www.audiobookshelf.org/docs
- v2.37.2 发行说明(ROUTER_BASE_PATH 规范化):https://github.com/advplyr/audiobookshelf/releases/tag/v2.37.2
- 认证体系变更说明(v2.26.0):https://github.com/advplyr/audiobookshelf/discussions/4460
- 站内系列:《Audiobookshelf 2.37.2 Docker Compose 部署实战》《Audiobookshelf 2.37.2 常用 API 与运维实战》