Skip to content

Install Aldus

Aldus ships as one container that serves the API and the exported web app together. Every tagged release publishes a ready-to-run image to GitHub Container Registry — there is nothing to build, and no Go toolchain or Node install required on the host.

Docker with Compose

Any recent Docker Engine with the compose plugin. Podman with a Compose shim works too, but isn’t tested as thoroughly.

A persistent data directory

Aldus keeps its SQLite database, managed downloads, covers, and alignment artifacts in one Docker volume. Losing it loses your library metadata.

A folder of media you own

A directory of EPUB and audiobook files Aldus can read. Aldus never renames, moves, or rewrites anything inside it.

Allow at least 8 GB of free disk space for the standard image and persistent data. The optional CUDA image needs substantially more; 15 GB free is a practical minimum before importing media.

The standard image supports Linux AMD64 and ARM64, including Linux containers under Docker Desktop on macOS and Windows. NVIDIA acceleration is limited to x86-64 Linux hosts with an NVIDIA GPU and Container Toolkit.

  1. Create an Aldus folder and download the small, versioned Compose manifest:

    Terminal window
    ALDUS_VERSION=0.1.0-beta.22
    mkdir -p aldus/library-media aldus/downloads && cd aldus
    curl -fL "https://github.com/Mahcks/Aldus/releases/download/v${ALDUS_VERSION}/compose.yml" -o compose.yml
    printf 'ALDUS_VERSION=%s\n' "$ALDUS_VERSION" > .env

    This downloads configuration only. The application itself is pulled from GHCR; no source checkout or local build is involved.

  2. The defaults use ./library-media for books and ./downloads for completed acquisitions. Add ALDUS_SOURCE_PATH or any other setting from the table below to .env only when you need to override a default.

  3. Start Aldus:

    Terminal window
    docker compose up -d --pull always
    docker compose ps
  4. Wait for docker compose ps to report healthy, then open http://localhost:8080 (or whatever ALDUS_PORT you set). The first account you create becomes the server administrator — there is no default password to change. Create it before changing ALDUS_BIND_HOST to expose Aldus to another machine.

Compose still uses the exact pinned GHCR image. It exists here only to keep the restart policy, persistent data and backup volumes, health check, media mounts, and safe localhost port mapping in one readable file. It never clones or builds Aldus.

Run the same setup from PowerShell 7:

Terminal window
$AldusVersion = "0.1.0-beta.22"
New-Item -ItemType Directory -Force aldus/library-media, aldus/downloads | Out-Null
Set-Location aldus
Invoke-WebRequest "https://github.com/Mahcks/Aldus/releases/download/v$AldusVersion/compose.yml" -OutFile compose.yml
"ALDUS_VERSION=$AldusVersion" | Set-Content .env
docker compose up -d --pull always
docker compose ps

Keep the first-account setup private by opening an SSH tunnel from your computer:

Terminal window
ssh -L 8080:127.0.0.1:8080 user@your-server

While that SSH session stays open, visit http://localhost:8080 on your computer and create the administrator. You do not need to expose the setup page to your LAN.

Copy an EPUB, M4B, or audiobook folder into library-media/. In Aldus, create a library under More → Libraries, then add /library/media under More → Sources and start a scan. The host path and container path intentionally differ: ./library-media is mounted read-only as /library/media, so Aldus can index your files without modifying them.

.env controls the handful of values Compose may need to know about the host; compose.yml then forwards most of them into the container under their real ALDUS_* names. Only ALDUS_VERSION is required because every other setting has a safe local default.

Variable Default What it does
ALDUS_VERSION 0.1.0-beta.22 Exact published image tag to run. Compose stops with an error when this is missing.
ALDUS_BIND_HOST 127.0.0.1 Host interface that publishes Aldus. The default is reachable only from the Docker host. Use 0.0.0.0 only after the first administrator exists and HTTPS or trusted-LAN controls are ready.
ALDUS_PORT 8080 The host port Aldus listens on. Change it if 8080 is already taken on your machine.
ALDUS_SOURCE_PATH ./library-media Host folder mounted read-only into the container at /library/media. This becomes the one path you’re allowed to add Sources under — see Media sources.
ALDUS_DOWNLOAD_PATH ./downloads Host folder mounted read-only into the container at /downloads. Only needed for automatic requests — it must be the same folder your qBittorrent container writes completed downloads to.
ALDUS_SECURE_COOKIES false Marks the session cookie Secure, so browsers only send it over HTTPS. Set true when a reverse proxy terminates HTTPS. Setting it without HTTPS breaks sign-in.
ALDUS_ALLOW_INSECURE_HTTP false Explicit acknowledgement required when production binds beyond loopback without secure cookies. Use only on a trusted private LAN where native clients need private-IP HTTP; never expose that configuration to the internet.
ALDUS_MAX_UPLOAD_BYTES 2147483648 (2 GiB) The largest file Aldus will accept, both for direct uploads and while scanning a Source. Raise it if you have single audiobook files larger than 2 GiB.

Inside the container, compose.yml sets three more variables directly rather than exposing them as .env values, because they’re implementation details of the mounts above rather than choices you make independently:

  • ALDUS_ENV=production — selects production logging and disables the developer fixture library.
  • ALDUS_SOURCE_ROOTS=/library/media — the container-side path Aldus is allowed to scan Sources under. This is what actually enforces the read-only mount; a Source pointed anywhere else is rejected.
  • ALDUS_DOWNLOAD_INGRESS=/downloads — the container-side path Aldus expects completed qBittorrent downloads to appear under. This only matters if you configure automatic requests.

The default 127.0.0.1 mapping is intentionally safe for first-account setup. For normal access from other devices, put Aldus behind an HTTPS reverse proxy and set:

ALDUS_BIND_HOST=0.0.0.0
ALDUS_SECURE_COOKIES=true

If a native client must connect directly to a private IP on a trusted home LAN, plain HTTP is supported only as an informed opt-in:

ALDUS_BIND_HOST=0.0.0.0
ALDUS_SECURE_COOKIES=false
ALDUS_ALLOW_INSECURE_HTTP=true

That mode exposes credentials and sessions to anyone able to observe the LAN. Do not port-forward it or use it over public Wi-Fi.

The standard Aldus image includes the alignment runtime and required models. New read/listen alignments run on CPU automatically with no separate service or setup. Models are copied into Aldus’s existing data volume on first start, so recreating or upgrading the container does not download them again. A full audiobook can take hours on CPU, so supported NVIDIA hosts can opt into acceleration below.

Alignment jobs have an eight-hour timeout by default. To override it, set ALDUS_ALIGNMENT_TIMEOUT_SECONDS in the Aldus container’s environment. For example:

services:
aldus:
environment:
ALDUS_ALIGNMENT_TIMEOUT_SECONDS: "28800"

Recreate the container to apply environment changes. A longer timeout gives a job more time; it does not speed up alignment. See Preparing a book for what to do if matching stops.

On an x86-64 Linux host, install a current NVIDIA driver and the NVIDIA Container Toolkit. Docker Compose 2.30 or newer is required. Then start GPU alignment:

Terminal window
curl -fL https://github.com/Mahcks/Aldus/releases/download/v0.1.0-beta.22/compose.gpu.yml -o compose.gpu.yml
docker compose -f compose.yml -f compose.gpu.yml up -d --pull always

The override recreates the existing aldus container with the CUDA image, requests one GPU through Compose, and uses the same data and model cache. New worker builds select a GPU-supported precision and a conservative batch size internally; beta.20 uses FP16. If PyTorch cannot use the GPU, only the alignment job fails with a focused diagnostic; reading, listening, and administration remain available.

Check startup with docker compose -f compose.yml -f compose.gpu.yml logs aldus. Docker Desktop on macOS cannot pass an NVIDIA GPU through; use CPU there.

Return to normal CPU processing with:

Terminal window
docker compose up -d --pull always

Use the same Aldus release version for whichever image you choose. Replace <version> below with that version, such as 0.1.0-beta.22.

Your server Image
No NVIDIA GPU, or you are unsure ghcr.io/mahcks/aldus:<version>
GTX 16-series, RTX 20-series or newer ghcr.io/mahcks/aldus:<version>-cuda
Older NVIDIA cards: GTX 900/10-series ghcr.io/mahcks/aldus:<version>-cuda-legacy

The legacy option is available only in releases that include compose.gpu-legacy.yml; beta.20 does not include it. Until you install a release with that file, use CPU processing on those older cards.

For Quadro, Tesla, and other NVIDIA models, check the card’s architecture: Maxwell, Pascal, and Volta use the legacy option; Turing and newer use -cuda. Older architectures are not supported by these GPU images. The GTX 16-series uses Turing, so it belongs with the newer cards despite its GTX name.

To use the legacy option, download compose.gpu-legacy.yml from the release you installed. In your server’s Aldus folder, run:

Terminal window
docker compose -f compose.yml -f compose.gpu-legacy.yml up -d --pull always

Use only one GPU override. Both options keep your books, accounts, and saved positions. Processing settings are chosen automatically in releases containing the legacy option. Speed depends on your card and the audiobook.

Newer GPU software drops support for some older cards. The legacy image keeps an older, tested set of dependencies so those cards can still prepare books. Aldus itself can continue receiving fixes in both images.

The current build uses PyTorch 2.8 with CUDA 12.8 for -cuda, and CUDA 12.6 for -cuda-legacy. These versions are chosen to work with Aldus’s speech software; they are not settings you need to change. Future dependency upgrades must preserve compatibility with the cards each image supports.

AMD and Intel GPU acceleration are not currently supported. Use the standard CPU image on those servers. Vulkan is not currently an available Aldus backend.

Most installations should not set any alignment variables. Aldus deliberately owns device and compute-type selection. If a supported GPU still runs out of memory, ALDUS_ALIGNMENT_BATCH_SIZE is the one advanced override retained: set it to 2 or 1 under the service’s environment in compose.gpu.yml, then rerun the GPU command. New worker builds default to 1 on GPUs with 4 GB or less and 4 on larger GPUs; larger values may improve throughput but are not part of the supported baseline.

Start with one snapshot of the container state and recent logs:

Terminal window
docker compose ps
docker compose logs --tail=200 aldus

Pulling the image returns 401 Unauthorized. Public Aldus images do not require a GitHub login or personal access token. A 401 means the release package is not publicly available; check the release page rather than creating Docker credentials.

Aldus exits immediately after docker compose up -d. Run docker compose logs aldus. Two startup checks fail loudly and exit the process rather than limping along:

  • An invalid ALDUS_LOG_LEVEL (only debug, info, warn, and error are accepted) stops configuration loading before anything else runs.
  • A source root that doesn’t exist, isn’t a directory, is a symlink, or overlaps Aldus’s own managed storage fails with a specific message naming the bad path — this is the most common cause of a container that starts and then immediately stops.

The data directory won’t create. Aldus calls mkdir on its data directory at startup and exits if that fails — almost always a host-side permissions problem on the named Docker volume or a bind mount owned by a different UID. Check docker compose logs aldus for create data directory.

Port already in use. ALDUS_ADDR isn’t validated ahead of time — Aldus only discovers a port conflict when it actually tries to bind, which shows up as a bind error in the logs at the moment of startup rather than a clean pre-flight message. Change ALDUS_PORT in .env and restart.

Sign-in silently does nothing. This is almost always ALDUS_SECURE_COOKIES=true without HTTPS in front of Aldus — the browser drops the session cookie rather than showing an error. Use the documented trusted-LAN opt-in for private-IP HTTP, or put a TLS-terminating proxy in front of Aldus and keep secure cookies enabled.

/api/v1/health and /api/v1/ready both matter. /api/v1/health only confirms the process is running. /api/v1/ready additionally checks that SQLite is reachable and that Aldus can still write to its data directory — useful for catching a volume that went read-only after a host reboot.