# 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](scanning.md) 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](users.md) 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.