SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor

在 VPS 上自架 Chaptarr 管理有聲書與電子書

Readarr 已於 2025 年停止維護。本教學示範在 VPS 以 Compose 部署 Chaptarr,設定 PUID、PGID,並處理中繼資料失效問題。

Chaptarr 是什麼,以及 Readarr 使用者為何需要它

Chaptarr 是 Readarr 的分支,可在單一執行個體中管理有聲書和電子書。它會監控新版本,將其傳送給下載用戶端,接著重新命名下載結果,並整理至媒體庫。它不會播放任何內容,因此需要搭配 Audiobookshelf 等播放器使用。

Readarr 已於 2025 年 6 月 27 日停止維護。Servarr 團隊發布的公告說明了原因:該專案的中繼資料已無法使用,而社群遷移至 Open Library 的工作也陷入停滯。其儲存庫已封存。這使書籍與有聲書收藏失去仍在維護的管理工具,Chaptarr 因此接手了這項工作。它保留了 Sonarr 和 Radarr 使用者熟悉的架構(索引器、下載用戶端、品質設定檔、根目錄),並加入有聲書處理功能:依旁白者整理、管理同一作品的多個版本、支援 M4B 和分章 MP3,以及將 MP3 轉換為 M4B。

本教學使用的映像標籤為 chaptarr/chaptarr:0.9.925,這是 2026 年 8 月 9 日當時的最新版本。截至 2026 年 10 月 11 日,最新版本為 0.9.965,發布於 2026 年 9 月 27 日。以下步驟僅在 0.9.925 上測試,因此檔案仍使用該標籤;升級至較新版本前,請先閱讀版本說明。Chaptarr 將自己定位為 beta 軟體。若要讓它管理無法替代的媒體庫,請先閱讀文末附近的維護一節。

開始前需要準備的項目

需要一台執行 Docker 與 Compose plugin 的 VPS,並準備足夠的磁碟空間存放媒體庫。有聲書通常很大。如果匯入程序無法使用 hardlink,檔案會暫時保留兩份;下方的 volume 章節會說明這點。如果該 VPS 尚未安裝 Docker,請先閱讀 在 VPS 上安裝並執行 Docker,完成後再返回本節。

Chaptarr 目前僅提供 Docker image。原生支援仍在開發中,預計提供實驗性的 Windows build,且目前沒有 distribution package。容器預設會將資料庫以 SQLite 儲存在 /config;如果你已經執行 PostgreSQL server,也可以透過 Chaptarr__Postgres__* 環境變數使用外部 PostgreSQL server。對於單一使用者在單一 VPS 上的部署,SQLite 是適當的選擇。

Compose 中的 Chaptarr 服務

此服務可加入現有的服務堆疊。它會固定使用已發布的標籤,只在 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,表示啟動失敗並正在重試,原因幾乎總是設定目錄有問題。應用程式開始監聽 port 8789 後,日誌就會停止持續捲動。

PUID、PGID,以及 Docker 以 root 建立的目錄

Chaptarr 在未設定 PUID=99 與 PGID=100 時,預設會使用這兩個值。這些是 unRAID 的值;在一般 Ubuntu VPS 上,它們對應到沒有實際用途的 nobody,因此檔案會由你的登入帳號無法寫入的使用者擁有。使用 id -u 和 id -g 讀取你自己的數值,並將它們填入檔案。

所有會存取同一批檔案的容器都必須使用相同的一組數值。下載用戶端會將檔案寫入 /srv/media/downloads,Chaptarr 會將檔案移至 /srv/media/audiobooks,播放器則會在該處讀取檔案。如果下載用戶端以 1000:1000 身分寫入,而 Chaptarr 以 99:100 身分執行,匯入就會失敗。檔案的擁有者不是決定因素:建立、重新命名或刪除檔案,需要的是存放該檔案的目錄具備寫入權限。由使用者 1000 建立、採用常見 755 模式的目錄,不會讓 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 分別作為獨立 bind mount 掛載,與專案本身的執行命令一致。這種配置容易理解,但有一項實際代價:硬連結會失效。

硬連結是磁碟上同一份資料的另一個名稱。它不會占用額外空間,而且建立速度快,因此 arr 系列通常偏好硬連結,而不是複製。硬連結只能在同一個檔案系統內運作。容器內的這些路徑是 3 個獨立的掛載點,因此即使主機路徑位於同一顆磁碟上,核心仍會拒絕建立連結。請自行測試。

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

命令會失敗,錯誤訊息最後會顯示 Invalid cross-device link。這表示核心拒絕跨越掛載點建立連結,也是 Chaptarr 改為複製檔案的確切原因。複製結果正確,但速度較慢;在移除 torrent 前,有聲書會暫時存在 2 份,而在仍持續做種時,你不會移除它。完成後刪除 /srv/media/downloads/linktest。

若要保留硬連結,請改為掛載一個父目錄:

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

接著將 Chaptarr 內的根資料夾設定為 /data/audiobooks 和 /data/ebooks,並為下載用戶端掛載相同的 /srv/media:/data,讓 2 個容器看到完全相同的路徑。請先確認主機端使用的是單一檔案系統:df -h /srv/media/downloads /srv/media/audiobooks 的 Filesystem 欄位對 2 個路徑必須顯示相同值。不同值表示使用不同磁碟,任何掛載配置都無法跨越不同檔案系統建立硬連結。這項配置與具名儲存空間之間的取捨,請參閱 媒體檔案的 bind mount 與具名磁碟區。

不公開 UI 也能存取

連接埠那一行發布到 127.0.0.1 是有原因的。ufw deny 8789 無法保護已發布的 Docker 連接埠,因為 Docker 會將自己的 NAT(網路位址轉譯)規則寫入一個核心會在 ufw 規則之前處理的鏈。因此,流量會先被轉送,根本不會查核你的規則。這種行為經常讓人誤判,詳見為什麼已發布的 Docker 連接埠會忽略 ufw 規則。繫結至 loopback 即可完全避開這個問題。

從你自己的電腦透過 SSH tunnel 存取 UI:

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

讓該連線保持執行,然後在瀏覽器中開啟 http://127.0.0.1:8789。首次執行時設定驗證。完成這項設定後,才應考慮在前方加入搭配 TLS(傳輸層安全性)的反向代理。當你需要透過 tunnel 存取三或四個這類工具,而且每個工具都使用不同密碼時,較整齊的做法是將代理放在自架的單一登入伺服器,例如 Authentik後方,讓一次登入涵蓋所有應用程式,撤銷一次即可全部停用。

連接索引器與下載用戶端

Chaptarr 支援標準的 arr 索引器與下載用戶端通訊協定,因此 Prowlarr 會以與 Sonarr 相同的方式將索引器推送至 Chaptarr,一般 torrent 與 usenet 用戶端也可直接連接,不需特殊處理。

有一項設定幾乎人人都會遇到問題。Chaptarr 要求輸入下載用戶端主機時,不要填入 localhost 或 127.0.0.1。在容器內,該位址指向容器本身,因此 Chaptarr 會嘗試連線到自己的 8080 埠,並回報無法連線。請改用容器名稱 qbittorrent,以及連接埠 8080。使用 docker network inspect arr 確認兩個容器位於同一個 network;此指令會依名稱列出所有已連接的容器。

如果下載用戶端透過具備 network_mode: "service:gluetun" 的 VPN 容器執行,該用戶端在 network 上沒有自己的名稱,因為它共用 Gluetun 的 network namespace。請使用 Gluetun 對外提供的連接埠,並以 gluetun 作為位址。這種配置及其搭配的路由方式,請參閱透過 Gluetun 路由下載用戶端。

Readarr 的中斷:實際遷移成本

Chaptarr 不相容於 Readarr 的中繼資料來源。它會透過自己的管線,從多個提供者解析標題、作者與版本,因此 Readarr 儲存的識別碼在這裡沒有意義。沒有資料庫匯入功能,也沒有可直接升級的路徑。

對現有媒體庫而言,這表示檔案安全,但設定不會保留。這個程序不會修改磁碟上現有的內容。您需要新增根資料夾、執行媒體庫匯入,讓 Chaptarr 使用自己的中繼資料比對找到的檔案。需要手動重建的項目包括:品質設定檔、命名格式、索引器與用戶端設定,以及 Chaptarr 判斷錯誤的每一筆比對結果。大型媒體庫需要逐一手動修正,因此應預留一個晚上的時間,不要以為 10 分鐘就能完成。

請依照以下順序操作。停止 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,可以在其中將該資料夾新增為媒體庫,Jellyfin 便能播放檔案。不過,對於單一且很長的有聲書檔案,其續播行為不如專用的有聲書伺服器。相關設定請參閱在 VPS 上將 Jellyfin 作為媒體伺服器執行。至於電子書部分,請將 /srv/media/ebooks 交給閱讀器應用程式;Chaptarr 在檔案完成命名與歸檔後,工作就結束了。

維護風險:授權條款、執行環境與快速變動的標籤

Chaptarr 採用 GPL-3.0 授權,著作權屬於 Chaptarr 貢獻者,部分程式碼則來自 Servarr 團隊。因此,即使目前的維護者停止維護,程式碼仍會保持開放,任何人都能再次建立 fork。Chaptarr 以 .NET 10 為基礎;截至 August 2026,這是該執行環境目前的長期支援版本。這表示基礎環境可獲得多年的支援,而不是只有數個月。如果你要判斷這個專案明年是否仍會存在,這兩點都很重要。

版本號碼變動很快。0.9.925 於 9 August 2026 發布,接下來七週又發布了 5 個版本。直到 0.9.958 為止的所有版本,都以預先發行版本發布;27 September 2026 發布的 0.9.965,則是第一個標示為正式版本的版本。請固定使用確切的標籤。使用 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 與你的 PUID 及 PGID。如果目錄由不同的 UID 擁有,或由你的群組擁有但群組沒有寫入權限,檔案就無法移動。UMASK=002 可讓新檔案避免第二種情況。

每次匯入後磁碟使用量都增加一倍。 系統未建立 hardlink,因此檔案被複製了。執行 volumes 區段中的 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 tunnel。

FAQ

我可以將 Readarr 媒體庫遷移至 Chaptarr 嗎?

不能以匯入方式遷移。Chaptarr 不相容於 Readarr 的中繼資料來源,並使用自己的提供者流程,因此 Readarr 儲存的識別碼沒有作用,也沒有資料庫轉換功能。磁碟上的檔案不會受到影響。請將相同路徑新增為根資料夾,執行媒體庫匯入,讓 Chaptarr 自行比對檔案。品質設定檔、命名格式、索引器設定及錯誤比對都必須手動處理,因此請先使用一個小型資料夾測試,再匯入全部內容。

為什麼 Chaptarr 無法寫入我的有聲書資料夾?

容器使用者沒有該目錄的寫入權限,通常是因為容器使用的 UID 與目錄擁有者不同。若未設定這些變數,Chaptarr 會使用 PUID=99 和 PGID=100,但這是 unRAID 的值,在一般 Ubuntu VPS 上不正確。請將它們設為自己的 id -u 和 id -g,並在下載用戶端使用相同的一組值;同時設定 UMASK=002,讓新檔案維持群組可寫入。請在媒體庫目錄上使用 ls -ln 檢查擁有權,因為它會顯示數字而非名稱,方便進行比對。

為什麼匯入後磁碟使用量增加一倍?

Chaptarr 無法建立硬連結,因此複製了檔案。將 /downloads 和 /audiobooks 作為個別 bind mount 掛載後,它們會在容器內成為不同的掛載點,而核心會以 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 在 August 2026 時是長期支援執行環境。請固定使用確切的映像標籤,例如 0.9.925,不要使用 latest;每次升級前備份 /config,並將該備份封存檔保存於伺服器以外。