SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-27

How to Run Chaptarr for Audiobooks on VPS

Readarr retire on 27 June 2025. Learn how to run Chaptarr with Docker Compose, set PUID and PGID, and fix the metadata break for audiobooks and ebooks.

Wetin be Chaptarr, and why Readarr users need am

Chaptarr na fork of Readarr wey dey manage audiobooks and ebooks from one instance. E dey watch for new releases, send dem go your download client, then rename the results and file dem inside your library. E no dey play anything, so pair am with player like Audiobookshelf.

Readarr retire on 27 June 2025. The Servarr team own notice talk the reason: the project metadata don become unusable, and the community effort to move go Open Library stop halfway. The repository dey archived. This leave book and audiobook collections without maintained manager, and Chaptarr take over the work. E keep the structure wey you already know from Sonarr and Radarr (indexers, download clients, quality profiles, root folders) and add audiobook handling: narrator-aware organisation, multiple editions of one title, M4B and chaptered MP3 support, and MP3 to M4B conversion.

This walkthrough use image tag chaptarr/chaptarr:0.9.925, wey be the newest release on 9 August 2026. Chaptarr call itself beta software. Read the maintenance section near the end before you point am to library wey you no fit replace.

Wetin you need before you start

One VPS wey dey run Docker and the Compose plugin, plus enough disk space for the library. Audiobooks dey large, and import wey no fit use hardlinks go keep two copies of one file for some time. The volume section below explain this. If Docker never dey for the box, start with Docker installed and running on a VPS then come back.

For now, na Docker image only Chaptarr dey provide. Native Windows build dey listed as work in progress, and no distribution package dey available. By default, the container dey store its database for /config as SQLite. E fit use external PostgreSQL server through Chaptarr__Postgres__* environment variables if you already dey run one. SQLite na the correct choice for one user on one box.

Compose service for Chaptarr

This service dey join an existing stack. E pin a released tag, publish the web UI for loopback only, and join the network wey your download client dey already use.

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

The external: true line mean say “this network don already exist; attach to am”. Use am when Prowlarr and your torrent client come from another Compose project, because second Compose file go otherwise create its own isolated network. Chaptarr no go fit resolve qbittorrent by name then. Get the real name from docker network ls. If your stack dey inside one file already, add the chaptarr: service to that file and delete the complete networks: block instead. A full arr stack under Docker Compose cover the wider layout, while How Compose networks and service names resolve explain the naming rules.

Create the config directory yourself, then start am.

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

docker compose ps suppose show the container as Up. If container dey listed as Restarting, e don fail to start and e dey retry. The cause almost always na the config directory. The log go stop scrolling once the app dey listen on port 8789.

PUID, PGID, and directory wey Docker create as root

Chaptarr dey use PUID=99 and PGID=100 by default if you leave dem unset. Na unRAID values be those ones, and for plain Ubuntu VPS dem no belong to any useful user. So files go land with owner wey your login no fit write. Read your own numbers with id -u and id -g, then put dem for the file.

Every container wey dey touch the same files need the same pair. Download client dey write to /srv/media/downloads, Chaptarr dey move the file go /srv/media/audiobooks, and player dey read am there. If download client dey write as 1000:1000 and Chaptarr dey run as 99:100, import go fail because Chaptarr no fit delete or move file wey no belong to am. UMASK=002 dey make new files writable by the group, and na this you want when multiple containers share one media group. You fit see the complete mapping for how PUID and PGID dey map container user to host files.

README warn about one specific trap, and e good make we repeat am. If ./config no dey exist when you run docker compose up, Docker go create am for you, and root:root go own am. Container go then run as UID 1000 but e no fit write its own database, so e go exit and restart forever. Check with ls -ln ./config; e go print numeric owners instead of names. Two zeros mean say root own am. Fix am with sudo chown -R 1000:1000 ./config, then start the container again.

The layout above mount /audiobooks, /ebooks and /downloads as separate binds, just as the project own run command specify. E easy to read, but e get one real cost: hardlinks no go work.

Hardlink na second name for the same data wey dey disk. E no use extra space and e happen immediately, na why the arr family prefer am instead of copying. Hardlink fit work only inside one filesystem. Inside the container, these na three separate mount points, so the kernel go reject the link even when the host paths dey on the same disk. Test am yourself.

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

The command fail with error wey end for Invalid cross-device link. Na the kernel dey refuse to link across mount points, and na the exact reason Chaptarr dey fall back to copying the file. The copy correct, but e slow pass, and the audiobook go then dey exist twice until you remove the torrent, wey you no go do while you still dey seed am. Delete /srv/media/downloads/linktest afterwards.

To keep hardlinks, mount one parent directory instead:

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

Then set the root folders inside Chaptarr to /data/audiobooks and /data/ebooks, and give the download client the same /srv/media:/data mount so both containers go see one identical path. First confirm say the host side na one filesystem: df -h /srv/media/downloads /srv/media/audiobooks must print the same value for the Filesystem column for both. Different values mean different disks, and no mount layout fit create hardlinks across dem. The trade-off between this and named storage dey covered for bind mounts against named volumes for media.

UI dey reach without exposing am

The port line publish for 127.0.0.1 for a reason. ufw deny 8789 no protect published Docker port, because Docker dey write im own NAT (network address translation) rules inside a chain wey kernel reach before ufw own chain. So traffic go forward before e even check your rule. This behaviour dey catch people regularly, and why published Docker port dey ignore your ufw rules explain am. If you bind am to loopback, you bypass the problem completely.

Use SSH tunnel from your own machine to reach the UI:

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

Leave the tunnel running, then open http://127.0.0.1:8789 for your browser. Set up authentication the first time you run am. Na only after that you suppose consider putting reverse proxy with TLS (transport layer security) in front of am. If you dey tunnel into three or four of these tools and each one get separate password, the cleaner solution na to put the proxy behind self-hosted single sign-on server like Authentik, so one login cover every app and one revocation fit close all of dem.

Connect indexers and the download client

Chaptarr dey speak standard arr indexer and download client protocols, so Prowlarr dey push indexers enter am the same way e dey do for Sonarr. The normal torrent and usenet clients fit connect without any special setup.

One setting dey confuse almost everybody. When Chaptarr ask for the download client host, no type localhost or 127.0.0.1. Inside container, that address na the container itself. So Chaptarr go try talk to im own port 8080 and report say e no fit connect. Use the container name, qbittorrent, with port 8080. Confirm say both containers dey for one network with docker network inspect arr. E go list every container wey join the network by name.

If your download client dey run through VPN container with network_mode: "service:gluetun", e no get im own name for the network because e dey share Gluetun network namespace. Address am as gluetun for the port wey Gluetun expose. That setup, and the routing wey come with am, dey for routing a download client through Gluetun.

The Readarr break: migration really cost wetin

Chaptarr no compatible with Readarr metadata sources. E dey resolve titles, authors and editions through e own pipeline across several providers, so the identifiers wey Readarr store no mean anything here. No database import dey, and no drop-in upgrade path dey.

For library wey already dey exist, this mean say the files safe but the settings no safe. Nothing for this process go touch wetin already dey disk. You go add root folder, run library import, and Chaptarr go match the files wey e find against e own metadata. The things wey you go rebuild by hand na quality profiles, naming format, indexer and client settings, plus every match wey Chaptarr guess wrong. Big library go need manual corrections, so plan for one evening instead of ten minutes.

Do am for this order. Stop the Readarr container but keep e config volume, so you fit still read your old settings while you dey type dem again. Point Chaptarr to one small folder first and check the matches before you import everything. Only remove the old container after you don happy with the result.

One privacy detail wey you suppose know before you scan the whole library: metadata lookups dey go to api2.chaptarr.com. The README talk say those requests fit carry provider IDs, search text, media type, tags and filenames, and say dem no include full paths, user identity or credentials. Filenames dey leave your server. This normal for metadata service, but you still need decide am deliberately.

Hand over the audiobooks to a player

Chaptarr dey organise files. Another program dey play dem, and Audiobookshelf na the usual partner because e dey track where you stop listening across devices and e get phone apps. The official image na ghcr.io/advplyr/audiobookshelf:latest, and the documented Compose example publish host port 13378 to container port 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

Mount the same host path wey Chaptarr dey write to, then add /audiobooks as a library inside the web UI. New import go show after the next scan.

If you already dey run Jellyfin, you fit add the folder as a library there and e go play the files. But resume behaviour for one long audiobook file no strong like purpose-built audiobook server. Running Jellyfin as media server for VPS cover how to set up that side. For the ebook part, hand /srv/media/ebooks to a reader application. Chaptarr job don finish once e name and file the file.

Maintenance risk: licence, runtime, and fast-moving tag

Chaptarr get GPL-3.0 licence. Copyright na dey with Chaptarr contributors, and some parts come from Servarr team. So the code remain open, and anybody fit fork am again if this maintainer stop. E dey build on .NET 10, wey be the current long term support release of the runtime as of August 2026. This mean say the base get support for years, no be only months. Both facts matter if you dey judge whether this project go still dey next year.

The version numbers dey change fast. Dem dey publish releases as pre-releases, and 0.9.925 land the same day with this walkthrough. Pin one exact tag. If you use latest, unattended docker compose pull fit move you several versions within one week. A fork wey still young fit change its API between releases. This fit break any script or dashboard wey you write against am.

Back up before every upgrade, then upgrade intentionally.

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

The project talk say e no record any data loss event for about six months and more than eleven thousand users, but e still advise make you keep backups and no point am to any library wey you no fit afford to lose. Take both sides seriously. Copy the config archive comot from the server, because backup wey dey for the same disk with the thing wey e suppose protect no be backup. That single tarball dey enough only because Chaptarr dey keep im state inside one SQLite file under /config; anything wey dey on separate database server need database dump too. Na this form the backup step take when you dey self-host Chatwoot on a VPS together with im Postgres data and uploaded files.

Failure modes, with the strings you will see

The container dey restart for loop. docker compose ps dey show Restarting. Run ls -ln ./config. Two zeros for the owner columns mean say Docker create the directory as root, and the container user no fit write its database. Run sudo chown -R 1000:1000 ./config.

Imports no dey complete and files dey remain for downloads. Chaptarr fit read the download but e no fit write inside the library. Compare ls -ln /srv/media/audiobooks with your PUID and PGID. Directory wey get another UID ownership, or wey your group own without group write permission, go stop the move. UMASK=002 dey prevent the second case for new files.

Disk usage dey double after every import. No hardlink dey made, so the file dey copy. Run the ln test from the volumes section. Error wey end with Invalid cross-device link confirm am, and the single-parent mount na the fix.

The download client no go connect. You enter localhost as the host. Inside the container, na Chaptarr itself be that. Use the container name and check say docker network inspect arr list both containers.

Compose refuse to start the service. Bind for 127.0.0.1:8789 failed: port is already allocated mean say another thing dey hold the port. Find am with sudo ss -lntp | grep 8789.

The browser no show anything at all. When the port bind to 127.0.0.1, nothing dey for your laptop to connect to across the internet. Na the intended behaviour be that. Open the SSH tunnel first.

FAQ

I fit migrate my Readarr library go Chaptarr?

No be as import. Chaptarr no compatible with Readarr metadata sources and e dey use im own provider pipeline, so identifiers wey Readarr store no get meaning and no database conversion dey available. Your files for disk no go change. Add the same paths as root folders, run library import, and allow Chaptarr match the files by itself. Quality profiles, naming format, indexer settings, and any wrong matches na manual work, so start with one small folder before you import everything.

Why Chaptarr no fit write to my audiobook folder?

The container user no own the files. Chaptarr dey fall back to PUID=99 and PGID=100 when those variables no set, and those na unRAID values wey wrong for normal Ubuntu VPS. Set them to your own id -u and id -g, use the same pair for the download client, and set UMASK=002 so new files remain group-writable. Check ownership with ls -ln for the library directory, because e dey print the numbers instead of names wey you no fit compare.

Why disk usage double after import?

Chaptarr copy the file because e no fit create hardlink. Mounting /downloads and /audiobooks as separate binds makes them separate mount points inside the container, and kernel dey reject hardlink across mount points with Invalid cross-device link. Mount one parent directory like /srv/media:/data and use /data/downloads and /data/audiobooks inside the app. Both paths must also dey on one host filesystem, and df -h go confirm this.

Chaptarr fit play my audiobooks?

No. E dey find, download, rename, and file them, while playback na work for separate program. Audiobookshelf na the common pairing because e dey remember your position across devices, using official image ghcr.io/advplyr/audiobookshelf:latest with the same host audiobook path mounted. Jellyfin go also play the files if you add the folder as library, but resume behaviour dey weaker for long single-file audiobooks.

Chaptarr safe to run for library wey matter to me?

Na beta software from young fork, and the project talk so by itself while reporting no data loss events for about six months and more than eleven thousand users. The reassuring parts na the GPL-3.0 licence, wey keep the code forkable, and the .NET 10 base, wey be long term support runtime as of August 2026. Pin exact image tag like 0.9.925 instead of latest, back up /config before every upgrade, and keep that archive outside the server.