Files
bookhoard/docs/admin/settings.md
T
John O'Keefe 607e5a1708 docs(admin): settings page — every knob, what it does, and its range
The ninth page and the core of the owner's admin-docs brief: all 29
registry settings plus Base URL, documented setting-by-setting to the
admin tier — key, type, default, valid range, live-vs-restart, and
prose for what it does and what it means when that's confusing
(extractor-version as the gradual backfill lever vs. force rescan;
password rules apply at next set, never retroactively; tombstone TTL
as offline-device protection; rate limits as throttling behavior;
worker pool sizing honesty for small servers). Grouped exactly like
the page renders them, with the three save paths explained up front.
Ranges/defaults/flags from SettingDefaults; exclusion of the three
dedicated-UI keys from the tunables verified in the page handler.
Backfills the Settings links into dashboard.md and users.md now that
the target exists. Glossary gains Save Settings, Save Scan Settings,
both Tunable bucket headings, and Default Timezone.
2026-11-02 14:16:04 -05:00

9.5 KiB
Raw Blame History

System Settings

The Settings page is every server-wide knob in one place. Each setting below lists its key (the name shown on the page and stored in the database), its default, its valid range, and whether it applies live or needs a restart.

How saving works

The page has three separate save paths, each with its own button:

  • Save Settings (top card) — commits the Base URL and Default Timezone together.
  • Save Scan Settings — commits the two scanning controls.
  • A per-row Save for each tunable setting — you change one value and save exactly that one.

Live tunables apply immediately. The restart bucket saves your value right away but only takes effect the next time the server restarts — the page marks that bucket in amber so it can't be missed. Invalid values are refused with an error; nothing silently clamps.


Base URL

base_url — string, no default. The public URL of your Bookhoard instance (e.g. https://books.example.com). This is the address Bookhoard hands out to devices and OPDS clients — device sync, OPDS, and API endpoint references are built from it — so it must be the URL your other machines can actually reach, not localhost. The URL Paths card underneath shows the three addresses derived from it (/opds, /api, /api/sync) as a sanity check.

System Defaults

default_timezone — string, default UTC. The timezone used for any user who hasn't picked their own (each user's profile can override it). This governs how the server renders dates and times for that user — history, stats day boundaries, timestamps. The dropdown offers a fixed list of zones.

Scanning

Two of these live in their own card with Save Scan Settings; the last two appear among the Live tunables under a "Scanning" heading. All four are documented together here.

auto_scan_enabled — bool, default on. Auto-Scan in the UI. The system-wide switch for automatic scanning: when on, a filesystem watcher fires scans as files change, a periodic poll runs on the interval below, and a shallow scan runs at startup. When off, libraries only change when you scan them by hand. See Scanning for shallow vs. force.

scan_poll_interval_seconds — int, default 60, range 1–3600. Scan Interval (seconds) in the UI. How often the automatic poll re-checks every library for changes. Lower is more responsive, higher is less background work; every tick is a shallow scan, so unchanged files cost almost nothing.

auto_playlist_collections — bool, default on. Live tunable. When a book's sidecar metadata marks its series as a reading order, Bookhoard automatically creates a collection that gathers the series in reading order. Turn it off to stop creating these during future scans (existing collections stay).

scan_extractor_version — int, default 1, range 1–1000000. Live tunable. The parser version stamped on each book's scan manifest. This is the gradual backfill lever: raise it after a scanner improvement, and books scanned under the older parser get re-extracted a bounded batch per scan until all are caught up — no manual force rescan required. Leave it alone unless you know a parser change shipped; don't set it far ahead of the real version.

Session

session_duration_seconds — int, default 604800 (7 days), range 300 (5 minutes)–31536000 (1 year). How long a login session stays valid. Shorter is safer for shared machines; longer means fewer re-logins on personal devices.

Password Quality

Five settings that together define every new password — set at registration, created by an admin, or changed by a user. Existing passwords are never retroactively invalidated; the rules apply when a password is next set.

password_min_length — int, default 8, range 1–128. Minimum character count.

password_require_upper — bool, default on. At least one uppercase letter (A-Z).

password_require_lower — bool, default on. At least one lowercase letter (a-z).

password_require_number — bool, default on. At least one digit (0-9).

password_require_special — bool, default on. At least one special character.

The Users page's create form and the change-password form build their live requirement checklists from these exact values.

Public Registration

registration_enabled — bool, default on. Whether visitors can create their own accounts from the sign-up page. Off, the instance is invite-by-admin: accounts are created only from the Users page (admins can always create accounts).

OPDS Catalog

Page-size controls for the OPDS catalog (what apps like KOReader use to browse your library over the network).

opds_default_page_size — int, default 50, range 1–500. How many entries a catalog page contains when the client doesn't ask for a specific size.

opds_max_page_size — int, default 200, range 1–1000. The ceiling on what a client may request — a protection against one app asking for enormous pages.

Device Rate Limits

Per-device request ceilings, per minute, by kind of request. These protect the server from a misbehaving or runaway device; a device that hits its limit is throttled until the minute rolls over. Defaults are sized for normal reading — raise them for very large libraries whose initial device sync needs more headroom.

device_rate_sync_per_min — int, default 60, range 1–10000. Sync requests per minute (annotations, bookmarks, reading-state sync).

device_rate_progress_per_min — int, default 120, range 1–10000. Progress updates per minute (position saves as you read).

device_rate_metadata_per_min — int, default 30, range 1–10000. Metadata requests per minute.

Annotation Retention

annotation_tombstone_ttl_days — int, default 30, range 1–3650. When an annotation (highlight, note, bookmark) is deleted, it isn't destroyed instantly — a tombstone records the deletion so every other device learns about it on their next sync. After this many days the tombstone is purged for good. Longer is safer if some of your devices stay offline for weeks; shorter reclaims rows sooner.

Conversion Cache

conversion_cache_ttl_hours — int, default 24, range 1–720. How long converted files (Kobo-optimized KEPUB, for example) are kept cached after conversion. Longer saves repeat conversion work at the cost of disk; the conversion is regenerated when the cache entry expires.

Auth Rate Limiting

Restart required.

auth_rate_limit_per_min — int, default 10, range 1–10000. Global cap on authentication requests per minute — the brute-force damper on the login endpoints, server-wide. Raise it only if legitimate logins are being throttled (many users behind one NAT, for example).

Login Lockout

Restart required. Two settings that work as a pair: after login_max_attempts consecutive failed attempts, that account waits login_lockout_minutes before accepting more tries.

login_max_attempts — int, default 5, range 1–100.

login_lockout_minutes — int, default 15, range 1–10080 (up to one week).

Sync Queue

Restart required. Device-originated sync changes flow through a background queue instead of being written the instant they arrive.

sync_queue_interval_seconds — int, default 5, range 1–3600. How often the queue flushes.

sync_queue_batch_size — int, default 50, range 1–10000. The maximum number of queued items processed per flush.

Worker Pool

Restart required. Background jobs — scans, sync-queue flushes, and other async work — run on a fixed pool of workers.

worker_pool_size — int, default 3, range 1–100. How many jobs run concurrently. More workers chew through queued work faster at the cost of CPU and database load; on a small home server, more is not better.

worker_queue_cap — int, default 100, range 1–10000. How many jobs may wait in line when every worker is busy. Work offered beyond the cap is refused rather than queued — a large force rescan of many libraries wants headroom here.

Podcasts

How often feeds are checked and how downloads behave server-wide.

podcast_poll_interval_seconds — int, default 3600 (one hour), range 300 (5 minutes)–604800 (one week). How often Bookhoard checks feeds for new episodes. Feeds marked complete (podcasts that have ended) back off instead of being checked hourly forever.

podcast_download_concurrency — int, default 4, range 1–16. Episode downloads in flight server-wide; fair-share scheduling spreads them across feeds so one feed can't hog the slots.

podcast_download_speed_mbps — float, default 0 (unlimited), range 0–10000. A shared bandwidth cap, in megabits per second, across all podcast downloads — useful when the server's connection is also serving readers.

About

The version of Bookhoard this server is running. Worth checking before filing a problem — and after an update, to confirm the new build landed.