Shelfmark

repository·main·Indexed 25 days ago

https://github.com/calibrain/shelfmark

A 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.

Tokens
40.6K
Snippets
65
Records
203
Agent score
84%

What's inside Shelfmark

  1. Get started with Shelfmark

    main
    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.
  2. Configure Multi-User Roles and Permissions

    main

    When 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.
  3. Configure Custom Scripts in Shelfmark

    main

    Shelfmark can execute a custom script after a download task completes successfully (e.g., after transferring to a folder or uploading to Booklore).

    Setup Steps

    1. Place your script on the machine running Shelfmark.
    2. Make the script executable (e.g., chmod +x /path/to/script.sh).
    3. 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:ro

    Then, 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=true
    chmod +x /path/to/your/scripts/post_process.sh
  4. Implement a Release Source plugin

    main

    To create a release source, extend the ReleaseSource class and use @register_source to register it. If the source requires specific download logic, implement a DownloadHandler and register it using @register_handler.

    Use @register_settings to define the UI for the source. You can use the show_when parameter 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):
            pass
  5. Install Shelfmark with WireGuard VPN Routing

    main

    To 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_ADMIN and NET_RAW capabilities.
    • Configuration: Mount a standard wg-quick config at the WIREGUARD_CONFIG path (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_DNS to pin a trusted resolver. If using Docker's embedded resolver, you must pin its upstream via the compose dns: 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 -d
  6. Develop Shelfmark Locally

    main

    The project provides a Makefile to manage development workflows for the Python backend and Vite frontend.

    Backend (Docker)

    • make up: Start backend via docker-compose.dev.yml
    • make down: Stop services
    • make refresh: Rebuild and restart
    • make restart: Restart container

    Frontend Development

    • make install: Install dependencies
    • make dev: Start Vite dev server (running on localhost:5173)
    • make build: Production build
    • make 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 Vulture
    • make install-python-dev: Sync Python runtime + dev tools with uv
  7. Quick Start with Shelfmark via Docker Compose

    main

    To get Shelfmark running quickly, use Docker and Docker Compose. This method uses the standard image which includes all network capabilities.

    1. Download the docker-compose.yml file:
      curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml
    2. Start the service in detached mode:
      docker compose up -d
    3. Access the web interface at http://localhost:8084 to configure your sources and settings.
    curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml
    docker compose up -d
  8. Important Installation Notes

    main

    When 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.
  9. Install Shelfmark Lite

    main

    The 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