Saltar al contenido
ES EN

Run Audiobookshelf Behind Caddy with HTTPS on Docker Compose

Lab · Self-hosting

45 min intermediate level validated configuration

Lab architectureComponents: Browser / app, Caddy, Audiobookshelf, Library, RSS feeds.HTTPSHTTP + websocketread/writedownloads episodesBrowser / app: step 5Browser / appHTTPS clientCaddy: step 4Caddycontainer :80 and :443Audiobookshelf: step 2Audiobookshelf127.0.0.1:13378Library: step 1Librarybind-mounted directoriesRSS feeds: step 6RSS feedsexternal podcasts
  1. Browser / app · step 5 HTTPS client
  2. Caddy · step 4 container :80 and :443
  3. Audiobookshelf · step 2 127.0.0.1:13378
  4. Library · step 1 bind-mounted directories
  5. RSS feeds · step 6 external podcasts

Deploy Audiobookshelf v2.37.1 with Docker Compose and Caddy 2.11.7 as an HTTPS reverse proxy, with users, podcast RSS subscriptions and scheduled backups.

What you will build and why

You will set up your own audiobook and podcast server with Audiobookshelf: a multi-user library with per-user progress synced across devices, automatic podcast episode downloads through RSS subscriptions, and scheduled backups. It is meant for legal content: your own audiobooks, podcasts and music you already have.

In front of it goes Caddy as a reverse proxy with automatic HTTPS. Audiobookshelf requires a websocket connection, so the proxy is something to verify, not decoration. Everything lives in a single compose.yaml with pinned versions, and the app listens only on 127.0.0.1: Caddy is the only way in from outside.

These are instructions, not a run report: the output blocks are illustrative and may differ on your machine.

Lab: Run Audiobookshelf Behind Caddy with HTTPS on Docker Compose

Requirements

SystemLinux (Debian 12 / Ubuntu 24.04) with Docker Engine
Docker Engine28.5.2
Docker Compose5.6.0
Audiobookshelf2.37.1
Caddy2.11.7
RAM2 GB
Disk20 GB + your library

Step by step

  1. Prepare the data directories

    Keep the library separate from the configuration. That way you can copy or move each part independently, and the container can be recreated without losing anything. Audiobookshelf cares about folder structure, so it pays to use one directory per content type.

    mkdir -p ~/abs/{audiobooks,podcasts,music,config,metadata,caddy-data,caddy-config}
    cd ~/abs
  2. Write the complete Compose file

    The file defines both services with exact tags. Audiobookshelf is published only on 127.0.0.1:13378 so nobody reaches it without going through Caddy. Caddy mounts ./Caddyfile as a file, which is why that file must exist before Caddy starts: otherwise Docker would create a directory with that name and Caddy would fail. We create it in step 4, and until then we only bring up Audiobookshelf.

    Replace CHANGE_ME_ZONA with your time zone, for example Europe/Madrid. Inside the container, the app uses /config for the database and /metadata for covers, cache and backups.

    File compose.yaml

    services:
      audiobookshelf:
        image: ghcr.io/advplyr/audiobookshelf:2.37.1
        restart: unless-stopped
        ports:
          - "127.0.0.1:13378:80"
        environment:
          - TZ=CHANGE_ME_ZONA
        volumes:
          - ./audiobooks:/audiobooks
          - ./podcasts:/podcasts
          - ./music:/music
          - ./config:/config
          - ./metadata:/metadata
    
      caddy:
        image: caddy:2.11.7
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./Caddyfile:/etc/caddy/Caddyfile:ro
          - ./caddy-data:/data
          - ./caddy-config:/config
        depends_on:
          - audiobookshelf

    Replace every CHANGE_ME_… value with your own before starting: never keep example passwords or keys.

  3. Start only Audiobookshelf and create the root user

    We start only the application service because the Caddyfile does not exist yet. Pulling the image first shows right away whether the tag resolves, before anything gets created.

    Open http://127.0.0.1:13378 from the machine itself (or through an SSH tunnel if it is remote). The first time, it asks you to create the administrator user: pick a long, unique password rather than a default one.

    docker compose pull audiobookshelf
    docker compose up -d audiobookshelf
    docker compose ps
    docker compose logs --tail 20 audiobookshelf

    Expected output

    # Salida ilustrativa: el formato exacto puede variar
    NAME                     IMAGE                                   SERVICE          STATUS
    abs-audiobookshelf-1     ghcr.io/advplyr/audiobookshelf:2.37.1   audiobookshelf   Up
  4. Add Caddy with HTTPS

    Caddy obtains and renews certificates automatically for a public domain name that points to your server, with ports 80 and 443 reachable from the Internet. Replace CHANGE_ME_DOMINIO with your real domain.

    The minimal Caddyfile uses reverse_proxy to the service by its Compose name. Audiobookshelf needs websockets, so do not consider this step done until you pass the verification below (login and live progress depend on it). If your setup does not work with the minimal configuration, check the project's reverse proxy documentation, which is the reference for this point.

    With the file in place, start Caddy.

    File Caddyfile

    CHANGE_ME_DOMINIO {
    	reverse_proxy audiobookshelf:80
    }

    Replace every CHANGE_ME_… value with your own before starting: never keep example passwords or keys.

    docker compose up -d
    docker compose ps
    docker compose logs --tail 30 caddy
  5. Create the libraries and users

    Go to https://CHANGE_ME_DOMINIO and sign in as root. In the settings, create one library per content type, pointing to the paths inside the container (/audiobooks, /podcasts, /music), not the host paths.

    Then create one user per person with custom permissions. It is better not to use the root account for everyday listening: that way listening progress is kept per user and you limit the damage if a session is compromised.

    Lay out your audiobooks as audiobooks/Author/Title/*.m4b. The folder structure affects how metadata is detected; see the project's library documentation.

  6. Subscribe to podcasts via RSS

    In the podcast-type library, use search to add a podcast or paste its RSS feed URL. Enable automatic episode downloads so the server fetches them without intervention. Downloading to the server means you no longer depend on the original feed staying available, and it lets you listen offline from the companion app.

    Audiobookshelf can also open its own RSS feeds for audiobooks and episodes, which is handy for listening in a podcast player. Protect those feeds like any other access point: anyone with the URL can listen.

  7. Set up backups

    In the app settings, enable the scheduled backup: it stores the database and metadata in /metadata/backups. Mind the scope: this protects the configuration, users and progress, not your audio library.

    A backup that lives on the same machine is not a complete backup. Copy ~/abs/metadata/backups and your content folders to another disk or machine with whatever tool you already use.

    ls -lh ~/abs/metadata/backups

Check that it works

  1. Containers are running

    Both services should show as up.

    docker compose ps
  2. HTTPS responds

    Check that the domain answers over HTTPS. The exact response depends on the version and session state: a 200 or a redirect (301/302) at the root is reasonable; what you must not see is a certificate or connection error.

    curl -sI https://CHANGE_ME_DOMINIO
  3. The app listens only locally

    Verify that port 13378 is bound to 127.0.0.1 and not to all interfaces. The exact output varies by system; look for the 127.0.0.1 address.

    ss -tln | grep 13378
  4. Websocket and playback

    Sign in from the browser through your domain, play an audio file and check that progress is saved and updates in a second session. If login works but state does not sync, check the proxy.

If something fails

Caddy will not start or a directory named Caddyfile appears

Caddy was started before the file was created and Docker created a directory instead. Stop everything, remove that directory, create the Caddyfile and start again.

docker compose down
rm -rf ./Caddyfile
# re-create the Caddyfile from step 4
docker compose up -d

Caddy cannot get the certificate

Check that the domain's DNS points to the server's public IP and that ports 80 and 443 reach the host (firewall and router forwarding). Read Caddy's logs to see the exact reason.

docker compose logs --tail 50 caddy

Login works but the interface does not update or live playback fails

Audiobookshelf requires a websocket connection. If you use a different proxy or an intermediate layer (CDN, another proxy in front), check that it allows websockets. See the project's reverse proxy documentation.

The library shows up empty

Check that the library paths are the container ones (/audiobooks, etc.), that the files exist on the host and that the container user can read them. Review the application logs.

docker compose logs --tail 50 audiobookshelf
Harden the setup

Keep the app on loopback only

The 127.0.0.1:13378:80 mapping stops anyone from reaching the app and bypassing HTTPS. Do not change it to 0.0.0.0.

Least-privilege users

Use root only for administration. Create regular accounts with custom permissions and unique passwords (replace any example value with your own).

Update with pinned tags and read the notes

Upgrade by changing the tag in compose.yaml after reading the release notes: v2.26.0 introduced a new authentication system and v2.37.0 updated Node.js to 24. Take a backup before every change.

docker compose pull
docker compose up -d

Backups off the machine

Replicate the backups in metadata/backups and your library to another disk or machine.

Clean-up: undo the lab

Remove the lab

This deletes the containers, and the last command also deletes your data and library. Copy anything you want to keep first.

cd ~/abs
docker compose down
cd ~
rm -rf ~/abs

What is verified

  • compose.yaml syntax (YAML parser and Compose structure)
  • Caddyfile: no automatic validator, review it by hand
  • Syntax of 12 command block(s) (bash -n in an isolated container, not executed)
  • Versions (4), options (1) and config keys (8) checked against 17 official documentation pages
  • Running the whole lab end to end: not executed

Automatic checks run on 10 October 2026. Items marked "·" were not executed: check them in your own environment.

Sources

Produced with AI support and reviewed by the newsroom

Byline

· Chief editor · English edition · London

“A padlock proves the certificate works; only a second session proves the proxy does.”

Comentarios

Publicar un comentario