Audiobookshelf 2.37.2 配置参数详解

Audiobookshelf 2.37.2 配置三层体系详解:PORT/ROUTER_BASE_PATH/CONFIG_PATH 等环境变量源码级默认值、SSRF 白名单精确匹配、令牌三件套与登录限速、serverSettings 全量字段实测对照(备份/扫描/播客调度/认证/反代)、用户权限体系与 isActive 默认未激活双坑排障实录(2026-10-27 实测)。

AudiobookshelfDockerNode.jsAudiobookshelf自托管2026/10/28

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 实测源码)说明
PORT3333(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 起自动规范化(补前导斜杠、去尾斜杠);反代子路径场景与它对齐
SOURCEdebian(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_TIMEOUT30000(30 秒,源码 toNumber 读取)单集下载/源抓取的超时毫秒数。慢速外网源可适当调大
MAX_FAILED_EPISODE_CHECKS24源连续失败多少次后自动停用该播客的自动下载(autoDownloadEpisodes 置 false),设为 0 表示永不自动停用

3.4 认证与安全类

变量默认值说明
ACCESS_TOKEN_EXPIRY3600(1 小时)访问令牌有效期(秒)。登录接口返回的 JWT 即此有效期
REFRESH_TOKEN_EXPIRY2592000(30 天)刷新令牌有效期;设为 0 可关闭刷新机制
REFRESH_TOKEN_GRACE_PERIOD600(10 分钟)旧刷新令牌的宽限期(秒),应对刷新瞬间并发请求
JWT_SECRET_KEY未设时自动生成并入库令牌签名密钥。多实例共享数据库时必须显式设置同一个值,否则各实例签发的令牌互不认账
RATE_LIMIT_AUTH_MAX40(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_PATHFLV 处理工具(特殊场景),一般不涉及
NUSQLITE3_PATHSQLite 扩展路径(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 已生效)。注意两点:

  1. 读取设置的通道是 POST /api/authorize(返回当前用户 + 全量 serverSettings,Web 端加载设置页即用此接口);PATCH /api/settings 只写不读,GET /api/settings 在 2.37.2 不存在(实测 404)。
  2. 时区字段在 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。

九、参考链接