Skip to content

How to Deploy Audiobookshelf on a VPS

Updated Sep 2026

verified on Ubuntu 26.04 · Sep 2026
We earn commissions when you shop through the links below. Full disclosure →

Self-host Audiobookshelf on a small VPS with Docker Compose and HTTPS — your own audiobook and podcast server with listening progress synced across devices.

Before you start
  • A small VPS — 1 vCPU / 512 MB–1 GB RAM is enough for the server itself
  • Enough disk for your audiobook and podcast files
  • A fresh Ubuntu 24.04 or 26.04 server with root/sudo SSH access
  • A domain you can point at the server
  • Docker Engine + Compose installed (see the base guide below)
Need a box for this guide? Kamatera's free tier lets you spin one up now.Start free on Kamatera → (opens in new tab)

What Audiobookshelf is

Audiobookshelf is a self-hosted audiobook and podcast server. You give it folders of audiobooks (and ebooks), or podcast feeds to subscribe to, and it builds a library with covers and metadata that you can stream from a web player or the Audiobookshelf mobile apps. The feature people move to it for is progress sync: stop a chapter on your phone and the web player picks up at the same second.

It is a Node.js app under GPL-3.0, rated 2 / 5 to deploy. In practice it is a single container with four folders, and the only step with any subtlety is the reverse proxy, because the apps rely on a WebSocket connection. If what you want to replace is an Audible-style library of files you already own, this is the tool; it does not sell or download books for you.

Server sizing

Audiobookshelf is one of the lightest servers in the catalog. On our test box (a GCP e2-standard-2 on Ubuntu 26.04), the idle container used about 37 MB of RAM and 447 MB of disk. The catalog's floor is 512 MB of RAM, which leaves room for the OS and a reverse proxy.

  • 512 MB – 1 GB RAM / 1 vCPU — a personal or family library.
  • 2 GB RAM — if the same box also runs other services.

CPU matters briefly during a library scan or when the server has to transcode a file for a client that can't play the original format. Disk is what grows: audiobooks are large, and podcast episodes accumulate. Size the disk (or attached block storage) for the library, not for the app.

Prepare the server

This guide assumes Docker Engine and the Compose plugin are installed, along with a non-root user and a ufw firewall. If not, work through Docker & Compose on Ubuntu first.

Open SSH and the reverse proxy ports only — Audiobookshelf's port stays on loopback:

sudo ufw allow OpenSSH
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable
sudo ufw status verbose
Where to host itaffiliate disclosure
Hetzner Cloudrun it on
2 vCPU · 4 GB RAM · 80 GB SSD · $23.59/mo
Get Hetzner Cloud (opens in new tab)
Contaboalso works on
4 vCPU · 8 GB RAM · 100 GB SSD · $4.95/mo
Get Contabo (opens in new tab)
Kamaterafree trial
1 vCPU · 1 GB RAM · 20 GB SSD · $4.00/mo
Start free on Kamatera → (opens in new tab)

Paid link — we earn a commission if you shop through it.

Install Audiobookshelf (Docker Compose)

Upstream's compose file maps four folders, and they have distinct jobs:

  • /config — the SQLite database: users, libraries, listening progress, settings. Upstream requires it to be on the same machine as the server; don't put it on a network share.
  • /metadata — covers, cache, streams, downloads, logs, and the built-in backups.
  • /audiobooks and /podcasts — your media. Upstream asks that these be separate directories, not nested inside each other or inside config.

Create the project directory and the folders:

mkdir -p ~/audiobookshelf && cd ~/audiobookshelf
mkdir -p config metadata audiobooks podcasts

Write the compose file. It is upstream's example with the port bound to loopback so only the reverse proxy can reach it:

cd ~/audiobookshelf
cat > docker-compose.yml <<'YAML'
services:
  audiobookshelf:
    image: ghcr.io/advplyr/audiobookshelf:latest
    container_name: audiobookshelf
    ports:
      # Loopback only — Caddy is the sole route in from outside.
      - "127.0.0.1:13378:80"
    volumes:
      - ./audiobooks:/audiobooks
      - ./podcasts:/podcasts
      - ./metadata:/metadata
      - ./config:/config
    environment:
      - TZ=Etc/UTC
    restart: unless-stopped
YAML
docker compose up -d

The container listens on port 80 internally; 13378 is only the host-side port, and upstream's advice is to change only that side if you need a different one. Set TZ to your own timezone so scheduled tasks (podcast checks, backups) run when you expect.

Check it answers:

cd ~/audiobookshelf
for i in $(seq 1 30); do curl -fsS -o /dev/null http://127.0.0.1:13378/ && break; sleep 2; done
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:13378/
docker compose ps

HTTPS + domain

Point an A record for books.example.com at the server's public IP and wait for it to resolve. Then terminate TLS with Caddy — the full setup is in Automatic HTTPS with Caddy:

books.example.com {
    reverse_proxy 127.0.0.1:13378
}

Upstream is explicit that Audiobookshelf requires a WebSocket connection through the proxy. Caddy's reverse_proxy forwards WebSocket upgrades on its own, so the block above is complete. If you use nginx instead, you must add the Upgrade and Connection headers yourself — a missing upgrade is the usual reason the web player works but progress doesn't sync.

Serving it under a path instead of a subdomain is supported, but only at /audiobookshelf — upstream doesn't allow a different subfolder name. A dedicated subdomain is simpler.

If Caddy runs as a container, 127.0.0.1 is the proxy's own loopback; put both services in one compose file and use reverse_proxy audiobookshelf:80.

First run

Open https://books.example.com. On first launch Audiobookshelf asks you to create the root user — the administrator account. Do it immediately; until then, whoever loads the page first sets that password.

Then create a library: choose Books or Podcasts and add the folder path as the container sees it — /audiobooks or /podcasts, not the host path. Audiobookshelf reads a folder per book, so Author/Book Title/files is the layout that scans cleanly.

To get files onto the server, either upload through the web UI or copy them from your computer with rsync into ~/audiobookshelf/audiobooks, then run a library scan.

Securing it

  • Create a user per listener. Progress is tracked per user, so a shared login mixes everyone's position in the same book.
  • Keep the root account for administration and use a normal account in the apps.
  • Keep the port on loopback. The compose file never publishes 13378 to the internet; everything arrives over HTTPS.

Backups

The database is in ./config; covers and the built-in backups are in ./metadata. The media folders you should back up the way you back up any other files. For a consistent copy of the database, stop the container briefly:

cd ~/audiobookshelf
docker compose stop
tar czf audiobookshelf-$(date +%F).tar.gz config metadata docker-compose.yml
docker compose start

Audiobookshelf can also make scheduled backups itself (Settings → Backups); they are written to metadata/backups. Those are useful for rolling back a bad upgrade, but they live on the same disk — copy archives off the box. Upstream's restore procedure for current versions is: stop the server, unzip the backup from metadata/backups, copy its audiobookshelf.sqlite over config/audiobookshelf.sqlite, restore the authors and items metadata folders, and start the server again.

Upgrades

Upstream's upgrade for a compose install:

cd ~/audiobookshelf
docker compose pull
docker compose down
docker compose up --detach

The latest tag moves to each new release. To stay on a specific version, replace latest with that version number. Back up config and metadata first: database migrations run at startup.

Troubleshooting

The web player works, but progress doesn't sync and the apps can't connect. The WebSocket isn't getting through the proxy. With Caddy that usually means the request isn't reaching Caddy at all (check DNS); with nginx it means the upgrade headers are missing.

A library scan finds nothing. The library points at a host path. Inside the container the folders are /audiobooks and /podcasts. Also check that the files are readable:

cd ~/audiobookshelf
ls -la audiobooks podcasts
docker compose logs --tail 50 audiobookshelf

The server won't start after an upgrade, and the log mentions the database. config is on a network filesystem, or a migration failed. Move config to local disk; if a migration failed, restore the pre-upgrade backup.

Books split into many single-file entries. The folder layout is flat. Put each book in its own folder, then rescan.

Verification + next steps

You're done when you can load https://books.example.com over a valid certificate, sign in as a non-root user, play a chapter in the browser, then open the same book in the mobile app and find it at the same position.

From there, put the rest of your media library next to it: Jellyfin for films and TV, and Navidrome for music.

Next steps

How to self-host Audiobookshelf →More self-hosted media server tools →Best VPS for Jellyfin →Automatic HTTPS with Caddy →Run Claude Code with Ollama on Your Own VPS →Deploy Coolify on a VPS →How to Deploy Actual Budget on a VPS →How to Deploy AnythingLLM on a VPS →How to Deploy Appwrite on a VPS →How to Deploy Authelia on a VPS →How to Deploy authentik on a VPS →How to Deploy Baserow on a VPS →How to Deploy Beszel on a VPS →How to Deploy Bitwarden on a VPS →How to Deploy BookStack on a VPS →How to Deploy CapRover on a VPS →How to Deploy Checkmate on a VPS →How to Deploy Directus on a VPS →How to Deploy docker-mailserver on a VPS →How to Deploy Docmost on a VPS →How to Deploy Dokku on a VPS →How to Deploy Dokploy on a VPS →How to Deploy Firefly III on a VPS →How to Deploy Forgejo on a VPS →How to Deploy Gatus on a VPS →How to Deploy Ghostfolio on a VPS →How to Deploy Gitea on a VPS →How to Deploy GitLab on a VPS →How to Deploy GlitchTip on a VPS →How to Deploy Grafana on a VPS →How to Deploy Graylog on a VPS →How to Deploy Headscale on a VPS →How to Deploy Healthchecks on a VPS →How to Deploy Home Assistant on a VPS →How to Deploy Immich on a VPS →How to Deploy Jan on a VPS →How to Deploy Jellyfin on a VPS →How to Deploy Karakeep on a VPS →How to Deploy Keycloak on a VPS →How to Deploy Leantime on a VPS →How to Deploy LibreChat on a VPS →How to Deploy Linkwarden on a VPS →How to Deploy LocalAI on a VPS →How to Deploy Mailcow on a VPS →How to Deploy Mailu on a VPS →How to Deploy Matomo on a VPS →How to Deploy Mattermost on a VPS →How to Deploy Meilisearch on a VPS →How to Deploy Memos on a VPS →How to Deploy n8n on a VPS →How to Deploy Navidrome on a VPS →How to Deploy NetBird on a VPS →How to Deploy Netdata on a VPS →How to Deploy Nextcloud on a VPS →How to Deploy Next.js to a VPS →How to Deploy Nginx Proxy Manager on a VPS →How to Deploy NocoDB on a VPS →How to Deploy ntfy on a VPS →How to Deploy Ollama on a VPS →How to Deploy Open WebUI on a VPS →How to Deploy OpenHands on a VPS →How to Deploy OpenObserve on a VPS →How to Deploy OpenProject on a VPS →How to Deploy Outline on a VPS →How to Deploy Pangolin on a VPS →How to Deploy Paperless-ngx on a VPS →How to Deploy Passbolt on a VPS →How to Deploy Plane on a VPS →How to Deploy Plausible Analytics on a VPS →How to Deploy Pocket ID on a VPS →How to Deploy PocketBase on a VPS →How to Deploy Prometheus on a VPS →How to Deploy Psono on a VPS →How to Deploy Radarr on a VPS →How to Deploy Rocket.Chat on a VPS →How to Deploy SigNoz on a VPS →How to Deploy Sonarr on a VPS →How to Deploy Stalwart on a VPS →How to Deploy Stirling-PDF on a VPS →How to Deploy Supabase on a VPS →How to Deploy Synapse on a VPS →How to Deploy Taiga on a VPS →How to Deploy TeamPass on a VPS →How to Deploy Tinyauth on a VPS →How to Deploy Traefik on a VPS →How to Deploy Trilium on a VPS →How to Deploy Twenty CRM on a VPS →How to Deploy Umami on a VPS →How to Deploy Uptime Kuma on a VPS →How to Deploy Vaultwarden on a VPS →How to Deploy Vikunja on a VPS →How to Deploy wg-easy on a VPS →How to Deploy Wiki.js on a VPS →How to Deploy Zabbix on a VPS →How to Deploy Zitadel on a VPS →How to Deploy Zulip on a VPS →Docker & Compose on Ubuntu 26.04 →Building AI Workflows with n8n →Install Open WebUI with Ollama →Adding AI-Powered Insights to Plausible Analytics →Building AI-Powered Apps with Supabase and pgvector →

We use analytics cookies (Google Analytics, PostHog) to see which guides are useful. No ad networks, no cross-site tracking. See our privacy policy.