Configuration

The server is configured by a plain text file named server.config at the repository root. All settings live here — there is no admin UI for these values. Every key also has an environment-variable fallback (listed below); the config file always wins when both are set.

File location

By default the server reads ./server.config (relative to the working directory the server is launched from). To point at a different file, set the OPERALIBRE_SERVER_CONFIG environment variable:

OPERALIBRE_SERVER_CONFIG=/etc/operalibre/server.config \
  ./apps/server/target/release/operalibre-server

Relative paths inside the config (like data_dir = data) are resolved against the directory containing the config file, not the current working directory. This means you can drop a config file anywhere and its data paths follow it.

File format

A simple key = value format. One key per line. Blank lines and # comments are ignored.

# This is a comment.
deployment_mode = local
host =
port = 4920
max_upload_gib = 20
max_book_download_gib = 25
max_concurrent_book_downloads = 1
download_temp_dir = data/download-temp
min_download_free_gib = 2
library_root = /path/to/audiobooks

Whitespace around keys and values is trimmed, and a value wrapped in matching single or double quotes has the quotes stripped. Keys are case-insensitive and accept - in place of _ (max-upload-gib works). An empty value is treated as unset, so host = falls back to the profile default.

An unknown key is a startup error, not a warning — a typo or a setting from a different version stops the server with a message naming the line.

Full example

# Deployment profile and optional advanced bind override.
deployment_mode = local
host =
port = 4920

# Transfer resource limits.
max_upload_gib = 20
max_book_download_gib = 25
max_concurrent_book_downloads = 1
download_temp_dir = data/download-temp
min_download_free_gib = 2

# Extra trusted cross-origin frontends (comma-separated).
allowed_origins =

# Folder containing your audiobook files.
library_root = /Users/you/Audiobooks

# Server data directory and legacy JSON import paths.
data_dir = data
progress_file = data/progress.json
users_file = data/users.json

# Serve the web app and API from the same address after `npm run build`.
web_dist_dir = apps/web/dist

# Optional Libation / Audible import.
libation_cli_path =
libation_files_dir =
libation_auto_refresh_hours = 24
libation_reader_refreshes_per_hour = 3

# Optional EPUB narration alignment.
alignment_cli_path =

# Optional MP4 faststart conversion.
ffmpeg_path =
ffprobe_path =

Reference

Network

Key Default Description
deployment_mode local local binds to loopback with HTTPS-grade cookies; lan listens on all interfaces and permits plain-HTTP cookies for a trusted LAN/VPN; proxy binds to loopback and expects a same-machine HTTPS reverse proxy.
host chosen by profile Optional advanced bind override. Must be a numeric IP address, not a hostname. local and proxy require a loopback address; lan defaults to 0.0.0.0. When upgrading an older config without deployment_mode, a non-loopback host is inferred as lan for compatibility.
port 4920 TCP port the API listens on.
allowed_origins (empty) Comma-separated list of trusted custom frontend origins, e.g. https://reader.example.com. These origins receive credentialed CORS access and may make cookie-authenticated changes, so do not list sites you do not control. Same-origin requests and the official app origins need no configuration.

Transfer limits

Key Default Description
max_upload_gib 20 Maximum total size of one web-uploaded audiobook or Libation title (including its temporary files). Set to 0 only to delegate storage-exhaustion control to another trusted layer.
max_book_download_gib 25 Maximum source size that may be assembled into a temporary ZIP download. Set to 0 only when disk usage is constrained externally.
max_concurrent_book_downloads 1 Simultaneous ZIP preparations/downloads. Accepted range: 1–32. Each active archive can consume temporary disk space up to its book size.
download_temp_dir data/download-temp Private staging directory for ZIP downloads. Put this on a data volume rather than a small operating-system temporary filesystem. Incomplete and completed archives are removed when their response ends.
min_download_free_gib 2 Free space that must remain on the staging volume after a new archive is prepared; also protects the library volume during Libation imports. Set to 0 only when the volume is constrained and monitored elsewhere.

When nginx is used, its client_max_body_size is an additional upload ceiling. Increase both that directive and max_upload_gib when deliberately supporting larger uploads.

Library

Key Default Description
library_root library Path to the folder containing your audiobook files; a relative path resolves against the folder holding server.config, and the default is a library folder in the server’s working directory. Set it explicitly in any real installation. The scanner reads from this folder; the web uploader writes new books into it. See Library Layout. The key audiobook_library is accepted as a legacy alias.

Data directory

The server keeps its state — accounts, sessions, listening progress, the reading log, completions, the work index, metadata overrides, and Libation requests — in one SQLite database, operalibre.db, inside data_dir. The directory also holds generated sync maps (sync/), cached cover art (covers/), the server log and PID file written by the launcher, and update-backups/ from in-app updates. The release launchers and the installer read data_dir from server.config too, so moving it relocates all of those files together. On Unix, everything in it is kept readable only by the account running the server.

Key Default Description
data_dir data Directory holding the database and the server’s working files. Created if missing.
progress_file data/progress.json Legacy JSON path for playback positions, used once to import an older installation.
users_file data/users.json Legacy JSON path for accounts, used once to import an older installation.
activity_file data/activity.json Legacy JSON path for daily listening totals, used once to import an older installation.
metadata_overrides_file data/metadata-overrides.json Legacy JSON path for saved metadata edits, used once to import an older installation.

The three *_file keys and their siblings matter only when upgrading an installation that predates the database: on first start the server copies the JSON files into data/backup-pre-sqlite/, imports them into operalibre.db in a single transaction, and never reads them again. The originals are left in place as the rollback path. Running the binary with --export-json writes the database contents back out in the original JSON layout and exits, which is also the supported way to inspect or hand-edit server state: export, remove operalibre.db, edit the JSON, and restart to re-import.

Back up data_dir to preserve progress, reading history, and accounts. The completion records in the database are the only history of a book that has since been deleted from the library.

Web app

Key Default Description
web_dist_dir (empty) Path to a built web bundle (the apps/web/dist folder produced by npm run build). When set, the server serves the frontend itself: any path that is not an /api/... route returns the bundle’s files, with unknown paths falling back to index.html for client-side routing. This gives a single-origin deployment with no reverse proxy and no CORS concerns.

Optional Libation integration

Leave both blank to disable. See Libation / Audible Import for the full integration guide.

Key Default Description
libation_cli_path (empty) Absolute path to the Libation CLI binary (libationcli, LibationCli, or libationcli.exe). If blank, the server searches PATH.
libation_files_dir (empty) Optional legacy Libation files directory containing AccountsSettings.json and Settings.json. Accounts added by an administrator in OperaLibre are stored as isolated profiles under data_dir/libation-accounts.
libation_auto_refresh_hours 24 How often the server asks Libation to scan Audible automatically. The first scan runs at startup when no previous successful scan is recorded. Set to 0 to disable scheduled scans.
libation_reader_refreshes_per_hour 3 Maximum reader-triggered Audible scans per account in a rolling hour. Administrators are not limited. Set to 0 to remove the reader rate limit.

Optional readalong alignment

Owners of managed release installations can install and enable the generator under Administration → Experimental features; no configuration entry is needed. Sentence following requires the experiment to be enabled and the reader to press Follow in the ebook, including for user-provided and previously generated .sync.json maps. Disabling it keeps those maps and leaves chapter sync available. Development and manually managed installations can configure an existing echogarden executable here instead; that explicit configuration takes priority over the managed add-on. See Library Layout for the sync-map workflow.

Key Default Description
alignment_cli_path (empty) Optional path to a manually managed echogarden CLI. It is treated as installed and enabled and is not changed from the Administration panel. When blank, OperaLibre uses an enabled managed add-on instead.

Optional MP4 faststart conversion

MP4-family files written without a leading moov index start playing slowly over a network. Administrators can remux them in place from Administration → Downloaded books; the control needs ffmpeg, and uses ffprobe to verify each converted file before it replaces the original. Leave both blank to search PATH; without ffmpeg the control simply reports itself unavailable.

Key Default Description
ffmpeg_path (empty) Path to the ffmpeg binary used for faststart conversion.
ffprobe_path (empty) Path to the ffprobe binary used to verify converted files.

Environment variables

Every config key has an environment-variable fallback. A value in server.config always takes precedence; the variable is read only when the key is absent or empty.

Variable Description
OPERALIBRE_SERVER_CONFIG Path to the config file itself. When set, a missing file is a startup error (the default ./server.config is allowed to be absent).
OPERALIBRE_DEPLOYMENT_MODE Fallback for deployment_mode.
HOST, PORT Fallbacks for host and port.
OPERALIBRE_LIBRARY Fallback for library_root.
OPERALIBRE_DATA_DIR Fallback for data_dir.
OPERALIBRE_PROGRESS_FILE, OPERALIBRE_USERS_FILE, OPERALIBRE_ACTIVITY_FILE, OPERALIBRE_METADATA_OVERRIDES_FILE Fallbacks for the legacy import paths.
OPERALIBRE_DOWNLOAD_TEMP_DIR Fallback for download_temp_dir.
OPERALIBRE_ALLOWED_ORIGINS Fallback for allowed_origins.
OPERALIBRE_WEB_DIST_DIR Fallback for web_dist_dir.
OPERALIBRE_ALIGNMENT_CLI_PATH Fallback for alignment_cli_path.
OPERALIBRE_FFMPEG_PATH, OPERALIBRE_FFPROBE_PATH Fallbacks for ffmpeg_path and ffprobe_path.
LIBATION_CLI_PATH, LIBATION_FILES_DIR Fallbacks for libation_cli_path and libation_files_dir (note: no OPERALIBRE_ prefix).
RUST_LOG Log filter; defaults to operalibre_server=info,tower_http=info.

The web app has one build-time variable:

Variable Description
VITE_API_BASE Base URL the web app uses for API calls when not running behind the Vite dev proxy (e.g., a Capacitor iOS build pointing at a remote server).

VITE_API_BASE is read at build time by Vite. Set it before running npm run build:

VITE_API_BASE=https://books.example.com npm run build

Reloading config

The config is read at server startup. Edit the file, then restart the server. There is no SIGHUP reload yet.