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.
9.5 KiB
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.