Shelfmark
repository·main·Indexed 25 days ago
https://github.com/calibrain/shelfmarkA self-hosted web interface for searching and requesting books and audiobooks across multiple sources, including torrents, usenet, and IRC. It integrates with digital library tools like Calibre and Audiobookshelf, offering features such as OIDC authentication, WireGuard and Tor routing options, and support for both direct and universal search modes via metadata providers like Google Books and Open Library.
What's inside Shelfmark
- Shelfmark is a self-hosted interface for searching, requesting, and delivering books and audiobooks using your own configured sources and services. To begin using Shelfmark, you should follow the installation, volume setup, and environment variable configuration guides.
Configure Multi-User Roles and Permissions
mainWhen authentication is enabled, Shelfmark supports two roles:
- Admins: Can configure request policies per source (direct download, request required, or blocked) and manage users.
- Users: Can manage per-user settings for download destinations, email recipients, and notification preferences. Users only see their own downloads and must submit requests for admin review if policies require it.
Configure Custom Scripts in Shelfmark
mainShelfmark can execute a custom script after a download task completes successfully (e.g., after transferring to a folder or uploading to Booklore).
Setup Steps
- Place your script on the machine running Shelfmark.
- Make the script executable (e.g.,
chmod +x /path/to/script.sh). - In the Shelfmark UI, navigate to Settings -> Advanced -> Custom Script Path and provide the path to your executable.
Docker Configuration
If running Shelfmark in Docker, the script must exist inside the container. It is recommended to mount a local directory containing your scripts as a volume:
services: shelfmark: image: ghcr.io/calibrain/shelfmark:latest volumes: - /path/to/your/scripts:/scripts:roThen, set the Custom Script Path in the UI to the container path (e.g.,
/scripts/post_process.sh).Alternatively, you can configure this via environment variables:
services: shelfmark: environment: - CUSTOM_SCRIPT=/scripts/post_process.sh - CUSTOM_SCRIPT_PATH_MODE=absolute - CUSTOM_SCRIPT_JSON_PAYLOAD=truechmod +x /path/to/your/scripts/post_process.shInstall Frontend Dependencies
mainInstall the necessary Node.js dependencies for the frontend application using eithermakefrom the root ornpmfrom thesrc/frontenddirectory.Implement a Release Source plugin
mainTo create a release source, extend the
ReleaseSourceclass and use@register_sourceto register it. If the source requires specific download logic, implement aDownloadHandlerand register it using@register_handler.Use
@register_settingsto define the UI for the source. You can use theshow_whenparameter on fields to implement conditional visibility (e.g., only showing a URL field if an 'Enabled' checkbox is checked).from shelfmark.release_sources.base import ReleaseSource, DownloadHandler, register_source, register_handler from shelfmark.core.settings_registry import register_settings, CheckboxField, TextField, SelectField from shelfmark.core.config import config @register_settings( name="my_source", display_name="My Source", group="direct_download", ) def my_source_settings(): return [ CheckboxField(key="MY_SOURCE_ENABLED", label="Enable", default=True), TextField( key="MY_SOURCE_URL", label="URL", show_when={"field": "MY_SOURCE_ENABLED", "value": True} ), SelectField( key="MY_SOURCE_PRIORITY", label="Priority", options=[{"value": "high", "label": "High"}, {"value": "normal", "label": "Normal"}], show_when={"field": "MY_SOURCE_ENABLED", "value": True} ), ] @register_source("my_source") class MySource(ReleaseSource): name = "my_source" def __init__(self): self.enabled = config.get("MY_SOURCE_ENABLED", True) @register_handler("my_source") class MySourceHandler(DownloadHandler): name = "my_source" def download(self, release, output_path): passUse multiple values for a single parameter
mainTo filter by multiple values for the same category (such as multiple languages or file formats), repeat the parameter in the URL string.
/?lang=en&lang=de&lang=fr /?format=epub&format=mobi&format=azw3Install Shelfmark with WireGuard VPN Routing
mainTo route all external egress through a WireGuard VPN tunnel with a fail-closed kill-switch, use the WireGuard compose file.
Requirements:
- Requires root startup.
- Requires
NET_ADMINandNET_RAWcapabilities. - Configuration: Mount a standard
wg-quickconfig at theWIREGUARD_CONFIGpath (default is/config/wg0.conf). - Kill-switch: All non-LAN egress is forced through the tunnel. If the tunnel drops, external traffic fails closed, but LAN ranges (WebUI, Prowlarr, etc.) remain reachable via
LAN_NETWORK. - DNS: Use
WIREGUARD_DNSto pin a trusted resolver. If using Docker's embedded resolver, you must pin its upstream via the composedns:list. - IPv6: If your kernel lacks
ip6tables, you may need to disable IPv6 via sysctls to prevent leaks.
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.wireguard.yml # place your wg-quick config where the compose mounts /config, as wg0.conf docker compose -f docker-compose.wireguard.yml up -dDevelop Shelfmark Locally
mainThe project provides a
Makefileto manage development workflows for the Python backend and Vite frontend.Backend (Docker)
make up: Start backend viadocker-compose.dev.ymlmake down: Stop servicesmake refresh: Rebuild and restartmake restart: Restart container
Frontend Development
make install: Install dependenciesmake dev: Start Vite dev server (running onlocalhost:5173)make build: Production buildmake frontend-typecheck: TypeScript checks
Note: The frontend dev server proxies to the backend on port 8084.
Python/Quality Checks
make checks: Run all static analysis (frontend + Python)make python-checks: Run Ruff, BasedPyright, and Vulturemake install-python-dev: Sync Python runtime + dev tools withuv
Quick Start with Shelfmark via Docker Compose
mainTo get Shelfmark running quickly, use Docker and Docker Compose. This method uses the standard image which includes all network capabilities.
- Download the
docker-compose.ymlfile:curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml - Start the service in detached mode:
docker compose up -d - Access the web interface at
http://localhost:8084to configure your sources and settings.
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml docker compose up -d- Download the
Build Frontend for Production
mainGenerate an optimized and minified production build. The output files will be located insrc/frontend/dist/.Important Installation Notes
mainWhen setting up Shelfmark, keep the following defaults and requirements in mind:
- Search Mode: Universal search is enabled by default for new installations.
- Direct Download: This feature is optional. You must explicitly enable and configure it before it becomes functional.
- Torrent and Usenet: If using these methods, ensure that the download paths are identical (matching) between the Shelfmark container/service and your download client.
Install Shelfmark Lite
mainThe Lite image is a lightweight version without built-in browser automation. It is ideal for:
- Using external services (e.g., already running FlareSolverr).
- Using alternative sources like Prowlarr, IRC, or configured sources.
- Using Shelfmark primarily for audiobooks.
Note: If you need browser-based access with the Lite image, you must configure an external resolver in the Web UI Settings.
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.lite.yml docker compose -f docker-compose.lite.yml up -d