SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 更新于 2026-08-27

VPS 自托管 Chaptarr:管理有声书和电子书

Readarr 已于 2025 年 6 月 27 日停止维护。本教程用 Docker Compose 部署 Chaptarr,配置 PUID、PGID、下载客户端,并修复元数据问题。

Chaptarr 是什么,以及 Readarr 用户为什么需要它

Chaptarr 是 Readarr 的一个分支,可在同一个实例中管理有声书和电子书。它会监控新版本,将其发送到下载客户端,然后重命名下载结果并整理到媒体库中。它不负责播放内容,因此需要搭配 Audiobookshelf 等播放器使用。

Readarr 已于 27 June 2025 停止维护。Servarr 团队发布的公告说明了原因:该项目的元数据已无法使用,社区迁移到 Open Library 的工作也陷入停滞。其代码仓库已归档。书籍和有声书收藏因此失去了持续维护的管理工具,Chaptarr 接手了这项工作。它延续了您在 Sonarr 和 Radarr 中已经熟悉的结构(索引器、下载客户端、质量配置文件、根文件夹),并增加了有声书处理功能:按叙述者整理、管理同一作品的多个版本、支持 M4B 和分章 MP3,以及将 MP3 转换为 M4B。

本教程使用了镜像标签 chaptarr/chaptarr:0.9.925,该标签在 9 August 2026 是最新版本。Chaptarr 将自身称为 beta 软件。在将它指向无法替代的媒体库之前,请先阅读文末附近的维护部分。

开始前的准备

一台运行 Docker 和 Compose 插件的 VPS,以及足够存放媒体库的磁盘空间。有声读物文件通常很大。如果导入过程无法使用硬链接,某个文件会暂时保留两份副本,下面的卷部分会对此进行说明。如果服务器上还没有安装 Docker,请先阅读在 VPS 上安装并运行 Docker,然后返回此处。

Chaptarr 目前仅提供 Docker 镜像。原生 Windows 构建版本标记为开发中,且没有发行版软件包。容器默认将数据库以 SQLite 格式存储在 /config 中。如果您已经运行 PostgreSQL 服务器,也可以通过 Chaptarr__Postgres__* 环境变量使用外部 PostgreSQL 服务器。对于单用户单服务器场景,SQLite 是合适的选择。

Chaptarr 的 Compose 服务

此服务可接入现有服务栈。它固定使用已发布的标签,仅通过 loopback 发布 Web UI,并加入下载客户端已经使用的网络。

services:
  chaptarr:
    image: chaptarr/chaptarr:0.9.925
    container_name: chaptarr
    environment:
      - PUID=1000
      - PGID=1000
      - UMASK=002
      - TZ=Europe/Berlin
    volumes:
      - ./config:/config
      - /srv/media/audiobooks:/audiobooks
      - /srv/media/ebooks:/ebooks
      - /srv/media/downloads:/downloads
    ports:
      - 127.0.0.1:8789:8789
    restart: unless-stopped
    networks:
      - arr

networks:
  arr:
    external: true

external: true 行表示“该网络已存在,将服务连接到此网络”。如果 Prowlarr 和 torrent 客户端来自不同的 Compose 项目,请使用此配置。否则,第二个 Compose 文件会创建自己的隔离网络,Chaptarr 将无法按名称解析 qbittorrent。通过 docker network ls 获取实际名称。如果您的服务栈已经位于同一个文件中,请将 chaptarr: 服务添加到该文件,并删除整个 networks: 块。更完整的布局参见 Docker Compose 下的完整 arr 服务栈,命名规则参见 Compose 网络和服务名称的解析方式

自行创建配置目录,然后启动服务。

mkdir -p ./config
sudo chown 1000:1000 ./config
docker compose up -d
docker compose ps
docker compose logs -f chaptarr

docker compose ps 应显示容器状态为 Up。如果容器状态显示为 Restarting,表示启动失败并正在重试,原因几乎总是配置目录导致的。应用开始监听 8789 端口后,日志输出会停止滚动。

PUID、PGID 以及 Docker 以 root 创建的目录

如果未设置,Chaptarr 默认使用 PUID=99PGID=100。这两个值属于 unRAID,在普通 Ubuntu VPS 上通常对应无用的 nobody,因此创建的文件会归属于您的登录账户无法写入的用户。使用 id -uid -g 读取您自己的数值,并将其填入文件。

所有操作同一批文件的容器都必须使用相同的一对值。下载客户端将文件写入 /srv/media/downloads,Chaptarr 将文件移动到 /srv/media/audiobooks,播放器在该位置读取文件。如果下载客户端以 1000:1000 写入,而 Chaptarr 以 99:100 运行,导入会失败,因为 Chaptarr 无法删除或移动不属于它的文件。UMASK=002 会让新文件对组成员可写;当多个容器共享同一个媒体组时,这正是所需设置。完整映射请参阅PUID 和 PGID 如何将容器用户映射到主机文件

README 特别警告了一个容易踩到的问题,这里值得重申。如果运行 docker compose up./config 不存在,Docker 会自动创建该目录,并将其所有者设为 root:root。随后容器以 UID 1000 运行,但无法写入自己的数据库,因此会退出并无限重启。使用 ls -ln ./config 检查;该命令显示数字形式的所有者,而不是名称。两个 0 表示目录由 root 所有。使用 sudo chown -R 1000:1000 ./config 修复所有权,然后重新启动容器。

为何将有声书和电子书分开存储会导致硬链接失效

上面的布局将 /audiobooks/ebooks/downloads 挂载为独立的绑定挂载,与项目自身的运行命令一致。这样便于阅读,但有一个实际代价:硬链接会失效。

硬链接是磁盘上同一份数据的第二个名称。它不占用额外空间,而且创建后立即生效,因此 arr 系列更倾向于使用硬链接,而不是复制。硬链接只能在同一个文件系统内工作。在容器中,这三个路径是独立的挂载点,因此即使宿主机路径位于同一块磁盘上,内核也会拒绝创建链接。请自行测试。

docker exec chaptarr sh -c 'touch /downloads/linktest && ln /downloads/linktest /audiobooks/linktest'

命令会失败,并显示以 Invalid cross-device link 结尾的错误。内核拒绝跨挂载点创建链接,这正是 Chaptarr 回退到复制文件的原因。复制结果正确,但速度更慢;在删除 torrent 之前,有声书会同时存在两份,而只要仍在做种,您就不会删除它。之后删除 /srv/media/downloads/linktest

若要保留硬链接,请改为挂载一个父目录:

    volumes:
      - ./config:/config
      - /srv/media:/data

然后将 Chaptarr 中的根文件夹设置为 /data/audiobooks/data/ebooks,并为下载客户端提供相同的 /srv/media:/data 挂载,使两个容器看到完全相同的路径。先确认宿主机端使用的是同一个文件系统:df -h /srv/media/downloads /srv/media/audiobooks 输出的 Filesystem 列中,两者必须显示相同的值。值不同表示它们位于不同磁盘上,任何挂载布局都无法跨文件系统创建硬链接。关于这种方式与命名存储之间的取舍,请参阅 用于媒体文件的绑定挂载与命名卷

不暴露端口访问 Web UI

端口配置绑定到 127.0.0.1 是有原因的。ufw deny 8789 无法保护已发布的 Docker 端口,因为 Docker 会将自己的 NAT(网络地址转换)规则写入内核优先处理的链中,流量会在检查 ufw 规则之前就被转发。这种行为经常导致误解,详见为什么已发布的 Docker 端口会忽略 ufw 规则。绑定到 loopback 可完全绕过这一问题。

从您自己的计算机通过 SSH 隧道访问 UI:

ssh -N -L 8789:127.0.0.1:8789 you@your-server

保持该隧道运行,然后在浏览器中打开 http://127.0.0.1:8789。首次运行时设置身份验证。完成这些步骤后,再考虑在前面配置带 TLS(传输层安全)的反向代理。当您需要通过隧道访问三四个此类工具,并且每个工具都使用不同密码时,更整洁的方案是将代理置于自托管的单点登录服务器(例如 Authentik)之后。这样一次登录即可访问所有应用,撤销一次授权即可关闭所有访问。

连接索引器和下载客户端

Chaptarr 支持标准的 arr 索引器和下载客户端协议,因此 Prowlarr 会像为 Sonarr 配置一样,将索引器推送到 Chaptarr;常用的 torrent 和 usenet 客户端也无需特殊处理即可连接。

有一个设置几乎会让所有人遇到问题。当 Chaptarr 要求填写下载客户端主机时,不要输入 localhost127.0.0.1。在容器内部,该地址指向容器自身,因此 Chaptarr 会尝试连接自己的 8080 端口,并报告无法连接。请使用容器名称 qbittorrent,端口填写 8080。使用 docker network inspect arr 确认两个容器位于同一网络中;该命令会按名称列出所有已连接的容器。

如果下载客户端通过 VPN 容器运行,并使用 network_mode: "service:gluetun",它在网络中没有自己的名称,因为它共享 Gluetun 的网络命名空间。请通过 Gluetun 暴露的端口,将其地址设置为 gluetun。相关配置及其路由方式请参阅通过 Gluetun 路由下载客户端

Readarr 中断:迁移的实际成本

Chaptarr 与 Readarr 的元数据源不兼容。它通过自己的处理流程,从多个提供商解析标题、作者和版本,因此 Readarr 保存的标识符在这里没有意义。没有数据库导入功能,也没有直接升级路径。

对于现有媒体库,这意味着文件安全,但设置无法保留。此过程不会修改磁盘上已有的任何内容。您需要添加根文件夹,运行媒体库导入,让 Chaptarr 根据自己的元数据匹配找到的文件。以下内容需要手动重建:质量配置文件、命名格式、索引器和下载客户端设置,以及 Chaptarr 匹配错误的所有项目。大型媒体库需要手动修正,应该预留一个晚上的时间,而不是十分钟。

请按以下顺序操作。停止 Readarr 容器,但保留其配置卷,以便在重新输入设置时仍能查看旧配置。先让 Chaptarr 扫描一个较小的文件夹,并在导入全部内容前检查匹配结果。确认结果满意后,再删除旧容器。

在扫描整个媒体库前,还需要了解一个隐私细节:元数据查询会发送到 api2.chaptarr.com。README 说明,这些请求可能包含提供商 ID、搜索文本、媒体类型、标签和文件名,但不包含完整路径、用户身份和凭据。文件名会离开您的服务器。这对于元数据服务来说很正常,但您仍应有意识地决定是否接受。

将有声书交给播放器

Chaptarr 负责整理文件。播放文件是其他程序的工作。Audiobookshelf 是常用的搭配,因为它可以跨设备跟踪播放进度,并提供手机应用。其官方镜像为 ghcr.io/advplyr/audiobookshelf:latest,官方记录的 Compose 示例会将主机端口 13378 映射到容器端口 80。

  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf
    ports:
      - 127.0.0.1:13378:80
    volumes:
      - ./abs/config:/config
      - ./abs/metadata:/metadata
      - /srv/media/audiobooks:/audiobooks
    environment:
      - TZ=Europe/Berlin
    restart: unless-stopped

挂载 Chaptarr 写入文件的同一主机路径,然后在 Web UI 中将 /audiobooks 添加为媒体库。下一次扫描后,新导入的内容就会出现。

如果您已经运行 Jellyfin,可以在那里将该文件夹添加为媒体库并播放文件。不过,对于单个较长的有声书文件,其断点续播体验不如专用的有声书服务器。相关设置请参阅在 VPS 上运行 Jellyfin 作为媒体服务器。对于电子书部分,将 /srv/media/ebooks 交给阅读器应用即可;文件完成命名和归档后,Chaptarr 的工作就结束了。

维护风险:许可证、运行时和快速变化的标签

Chaptarr 使用 GPL-3.0 许可证,版权归 Chaptarr 贡献者所有,其中部分代码来自 Servarr 团队。因此,即使当前维护者停止维护,代码仍保持开放,任何人都可以再次创建 fork。截至 August 2026,它基于 .NET 10,这是该运行时当前的长期支持版本。这意味着底层运行时支持期以年计,而不是以月计。如果要判断这个项目明年是否仍会存在,这两点都很重要。

版本号变化很快。发布版本采用预发布形式,0.9.925 在本教程发布当天推出。请固定到准确的标签。使用 latest 意味着无人值守的 docker compose pull 可能在一周内将版本升级多个版本。这样年轻的 fork 可能在不同版本之间更改 API,从而导致针对它编写的脚本或仪表板失效。对于自行托管的年轻项目,固定版本是值得坚持的习惯。因此,本教程中 运行 openGym 作为自行托管的训练记录器 也出于完全相同的原因,从固定的 git 标签进行部署。

每次升级前都要备份,然后按计划执行升级。

docker compose stop chaptarr
sudo tar czf chaptarr-config-backup.tgz ./config
docker compose start chaptarr
docker compose pull chaptarr
docker compose up -d chaptarr

该项目报告称,在大约 6 个月内、覆盖超过 11000 名用户,未发生数据丢失事件。但它仍建议保留备份,并且不要让它访问无法承受丢失的库。请认真对待这两点。

将配置归档复制到服务器之外。与受保护数据位于同一磁盘上的备份不是真正的备份。只有在 Chaptarr 将状态保存在 /config 下的一个 SQLite 文件中时,单个 tarball 才足够。位于独立数据库服务器上的数据还需要单独导出数据库。与 Postgres 数据和上传文件一起在 VPS 上 自行托管 Chatwoot 时,备份步骤就是这种形式。

故障模式及其对应提示

容器反复重启。 docker compose ps 显示 Restarting。运行 ls -ln ./config。所有者列中的两个 0 表示 Docker 以 root 身份创建了该目录,容器用户无法写入其数据库。运行 sudo chown -R 1000:1000 ./config

导入始终无法完成,文件一直留在下载目录中。 Chaptarr 可以读取下载目录,但无法写入媒体库。将 ls -ln /srv/media/audiobooks 与你的 PUIDPGID 进行比较。目录由其他 UID 所有,或由你的组所有但未启用组写入权限,都会导致文件无法移动。对于新文件,UMASK=002 可以避免第二种情况。

每次导入后磁盘使用量翻倍。 未创建硬链接,因此文件被复制了。运行卷部分中的 ln 测试。以 Invalid cross-device link 结尾的错误表示硬链接创建失败;使用单一父目录挂载即可修复。

下载客户端无法连接。 你将 localhost 填为主机名。在容器内,这指向 Chaptarr 自身。使用容器名称,并检查 docker network inspect arr 是否列出了两个容器。

Compose 拒绝启动服务。 Bind for 127.0.0.1:8789 failed: port is already allocated 表示该端口已被其他进程占用。使用 sudo ss -lntp | grep 8789 查找占用进程。

浏览器完全没有显示内容。 当端口绑定到 127.0.0.1 时,笔记本电脑无法通过互联网连接到该端口。这是预期行为。先打开 SSH 隧道。

FAQ

我可以将 Readarr 媒体库迁移到 Chaptarr 吗?

不能通过导入迁移。Chaptarr 不兼容 Readarr 的元数据源,并使用自己的提供程序流水线,因此 Readarr 存储的标识符没有意义,也不存在数据库转换。磁盘上的文件不会受到影响。将相同路径添加为根文件夹,运行媒体库导入,让 Chaptarr 自行匹配文件即可。质量配置、命名格式、索引器设置以及错误匹配都需要手动处理,因此应先导入一个较小的文件夹,再导入全部内容。

为什么 Chaptarr 无法写入我的有声读物文件夹?

容器用户不拥有这些文件。未设置这些变量时,Chaptarr 会回退到 PUID=99PGID=100,但这两个值是 unRAID 的值,在普通 Ubuntu VPS 上不正确。将它们设置为您自己的 id -uid -g,并在下载客户端中使用相同的一对值;同时设置 UMASK=002,使新文件保持组可写。在媒体库目录上使用 ls -ln 检查所有权,因为它会输出数字而不是名称,便于进行比较。

为什么导入后磁盘使用量翻倍?

Chaptarr 无法创建硬链接,因此复制了文件。将 /downloads/audiobooks 作为独立绑定挂载后,它们在容器内会成为独立的挂载点,内核会使用 Invalid cross-device link 拒绝跨挂载点创建硬链接。挂载一个父目录,例如 /srv/media:/data,然后在应用中使用其中的 /data/downloads/data/audiobooks。这两个路径还必须位于同一个主机文件系统上,df -h 可以确认这一点。

Chaptarr 可以播放我的有声读物吗?

不能。它负责查找、下载、重命名和整理文件,播放由独立程序负责。Audiobookshelf 是常见的搭配,因为它可以跨设备记住播放位置;使用官方镜像 ghcr.io/advplyr/audiobookshelf:latest,并挂载相同的主机有声读物路径即可。如果将该文件夹添加为媒体库,Jellyfin 也可以播放这些文件,但对于较长的单文件有声读物,其续播行为较弱。

在重要的媒体库上运行 Chaptarr 安全吗?

Chaptarr 是来自一个年轻分支的 beta 软件,项目本身也明确说明了这一点;同时,项目报告称在约六个月内、超过一万一千名用户中没有发生数据丢失事件。值得放心的是 GPL-3.0 许可证,它使代码可以继续创建分支;此外还有 .NET 10 基础运行时,截至 2026 年 8 月它属于长期支持运行时。请固定使用确切的镜像标签,例如 0.9.925,不要使用 latest;每次升级前备份 /config,并将该归档保存在服务器之外。