bindery

module
v1.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 15, 2026 License: MIT

README

Bindery

Bindery

Automated book download manager for Usenet & Torrents
Monitor authors. Search indexers. Download. Organize. Done.

CI codecov Release Docker Go Report Card License Discord


Mobile-friendly

       


Why Bindery?

Readarr is dead. The official project was archived in June 2025 and its metadata backend (api.bookinfo.club) is permanently offline. Community forks rely on fragile Goodreads scrapers that break regularly. There was no reliable, open-source tool for automated book management on Usenet.

Bindery is the clean-room replacement. Built from scratch in Go with a modern React UI, Bindery uses only stable, documented public APIs for book metadata. No scraping. No dead backends. No fragile dependencies.

Features

Library management

  • Author monitoring via OpenLibrary's author-works endpoint, with per-book monitor toggles and a wanted → downloading → downloaded → imported workflow.
  • Dual-format books — each title holds an ebook and an audiobook in independent slots, with separate search, grab, and import pipelines, and the audiobook side moves multi-part .m4b / .mp3 folders as one unit.
  • Series support with position tracking, edition tracking (format / ISBN / publisher / page count), Calendar view of upcoming releases, and multiple library roots.
  • Library scan with four-tier matching: ASIN → title + author → series name + position → fuzzy title. Honours librarian sort-suffix form (Title, The) and series-annotated filenames ([Mistborn, Book 1]).
  • Author aliases (RR Haywood / R.R. Haywood / R R Haywood merge into one canonical row), and metadata re-bind to correct a wrong match without delete-and-re-add.

Search & downloads

  • Newznab + Torznab indexers queried in parallel, deduplicated, then composite-ranked by format quality, edition tags (RETAIL / UNABRIDGED / ABRIDGED), year match, grab count, size, and ISBN exact-match bonus.
  • Smart matching — four-tier query fallback (t=booksurname+titleauthor+title → title), word-boundary keyword matching, contiguous-phrase requirement for multi-word titles, dual-author-anchor for ambiguous short titles, subtitle-aware (Title: Subtitle).
  • SABnzbd, NZBGet, qBittorrent, Transmission, Deluge — with Use SSL and URL Base for reverse-proxy subpaths.
  • Auto-grab sweep every 12h, immediate search on add or wanted flip, plus interactive per-book search and "Search all wanted" per author. Global kill-switch pauses auto-grab without losing your monitored list.
  • Quality profiles (EPUB / MOBI / AZW3 / PDF), language filter, regex-based custom formats, delay profiles, blocklist (consulted on every search; one-click add from History), and failure visibility in Queue and History.

Import & organize

  • Completed downloads matched by NZO ID and placed in the library with configurable naming. Modes: Move (default), Copy (keep source for seeding), Hardlink (zero extra disk; same filesystem required).
  • Naming tokens — {Author}, {SortAuthor}, {Title}, {Year}, {Series}, {SeriesNumber}, {ext} — collapse cleanly for non-series books.
  • Cross-filesystem-safe moves: atomic rename when possible, copy + verify + delete for NFS / separate volumes. Full grab / import / failure history per book.
  • Calibre integration in three modes: calibredb CLI hook on import, Bindery Bridge plugin (cross-container), or direct read of an existing Calibre library's metadata.db as Bindery's catalogue.

Metadata sources — all stable, documented, public APIs. No Goodreads scraping.

Source Auth Used for
OpenLibrary None Primary: authors, books, editions, covers, ISBN
Google Books API key (free) Enrichment: descriptions, ratings
Hardcover.app None (public GraphQL) Enrichment: community ratings, series, wishlist
DNB None (public SRU) German-language descriptions, language, year, publisher; can be promoted to primary
Audnex None Audiobook narrator, duration, cover by ASIN
Audible None Supplemental audiobook author lookup — pulls ASINs OL/Hardcover miss

Cover images are fetched and cached server-side under <dataDir>/image-cache/ (30-day TTL). Every imageURL is rewritten to /api/v1/images?url=... before leaving the server — the browser never contacts third-party image hosts directly.

Discover — personalised recommendations on the Discover page from multiple signals: next-in-series for what you're reading, new releases from monitored authors, genre similarity (≥ 20 books in library), OpenLibrary subject popular picks, and Hardcover wishlist cross-reference. Recency scoring is relative to the median publication year of your library, so backlist readers aren't penalised. Hard-filters owned, dismissed, excluded-author, wrong-language, fewer-than-50-ratings, sub-3.0-rated, and omnibus titles. Dismiss / exclude actions persist.

Migration — upload readarr.db directly (authors re-resolved against OpenLibrary since bookinfo.club is dead; indexers, download clients, and blocklist port structurally), or paste a newline-separated list of author names. CLI: bindery migrate {csv,readarr} <path> for first-time bulk imports without opening the UI.

Operations

  • Authentication — first-run setup creates an admin account (argon2id, signed session cookies). Four modes: Enabled / Local only (bypass for private IPs) / Disabled / Proxy (trust upstream X-Forwarded-User from a configured trusted proxy — drop-in for Authelia / Authentik / oauth2-proxy). Per-account API key, per-IP login rate limiting, CSRF double-submit (API-key clients exempt).
  • OIDC — native Authorization Code + PKCE with multi-provider support. Pre-configured for Google, GitHub (via Dex), Authelia, and Keycloak; identifies users by stable (issuer, sub) so email/username changes don't break logins.
  • Multi-user mode — per-user libraries, monitored authors, profiles, and downloads. Admin role manages indexers / download clients / users; standard users see only their own catalogue. Local, OIDC-provisioned, or forward-auth-mapped.
  • Webhook notifications for grab / import / failure (pipe to Apprise, ntfy, Home Assistant, Discord, Slack via proxies). Tags scope indexers / profiles / notifications to specific authors. On-demand SQLite backups. Persistent log viewer in Settings → Logs with runtime DEBUG toggle.
  • Arr-compatible queue at GET /api/queue for Harpoon and other *arr-aware tools — pagination, sort, live size, status, client, remote ID, protocol.

UI

  • Modern React 19 + TypeScript + Tailwind CSS SPA with deep-linkable routed /book/:id and /author/:id pages.
  • Light / dark themes (respecting prefers-color-scheme first paint), grid / table view toggles, mobile-friendly responsive layout, hamburger nav, agenda-style mobile Calendar.
  • Full pagination, search, filter, and sort on every list page; preferences persist to localStorage.
  • 7 languages — English, French, German, Dutch, Spanish, Filipino (Tagalog), Indonesian — auto-detected from the browser, override in Settings.
  • OPDS 1.2 catalogue at /opds/v1.2/ for KOReader, Moon+ Reader, and other reading apps. HTTP Basic auth with the API key as the password.

Packaging — single Go binary with the React frontend embedded via go:embed. Distroless container (non-root, read-only rootfs, all caps dropped, RuntimeDefault seccomp). Helm chart for ArgoCD / Flux. Pure-Go SQLite via modernc.org/sqlite — no CGO, no external database.

Quick Start

Docker

docker run -d \
  --name bindery \
  -p 8787:8787 \
  -v /path/to/config:/config \
  -v /path/to/books:/books \
  -v /path/to/downloads:/downloads \
  ghcr.io/vavallee/bindery:latest

Open http://localhost:8787, follow the first-run setup to create the admin account, and you're in.

Docker Compose

services:
  bindery:
    image: ghcr.io/vavallee/bindery:latest
    container_name: bindery
    ports:
      - 8787:8787
    volumes:
      - ./config:/config
      - /media/books:/books
      - /media/downloads:/downloads
    environment:
      - BINDERY_LOG_LEVEL=info
    restart: unless-stopped

Other install methods

Pre-built binaries for Linux / macOS / Windows (amd64, arm64, armv7, armv6), Kubernetes (Helm chart at charts/bindery/), and the Unraid Community Applications template are all covered in docs/DEPLOYMENT.md — including UID/GID setup, path remapping for multi-container deployments, the full environment-variable reference, and per-version upgrade notes.

Configuration

Bindery is configured through the web UI under Settings — indexers, download clients, quality profiles, naming, notifications, auth, and everything else runtime-tunable lives there. A small set of bootstrap-only knobs are environment variables:

Variable Default Purpose
BINDERY_PORT 8787 HTTP server port
BINDERY_DB_PATH platform-default SQLite database path
BINDERY_DATA_DIR platform-default Config directory (backups, image cache, secrets)
BINDERY_LIBRARY_DIR /books Imported ebook destination
BINDERY_AUDIOBOOK_DIR inherits library Imported audiobook destination
BINDERY_DOWNLOAD_DIR /downloads Where the download client deposits completed jobs
BINDERY_URL_BASE (empty) Reverse-proxy subpath (e.g. /bindery)
BINDERY_PUID / PGID (unset) Sanity-check assertions for the container UID/GID

The full reference (path remapping, API-key seeding, OIDC, telemetry, rate-limit knobs, cookie-Secure policy) is in docs/DEPLOYMENT.md#environment-variables.

Supported integrations

Category Implementations
Usenet clients SABnzbd, NZBGet
Torrent clients qBittorrent, Transmission, Deluge
Indexers Newznab (NZBGeek, NZBFinder, NZBPlanet, DrunkenSlug, …), Torznab (Prowlarr, Jackett, direct endpoints), with per-indexer category overrides
Notifications Generic webhooks — pipe to Apprise / ntfy / Home Assistant / Slack / Discord
Authentication Local (argon2id), API key, OIDC (Google, GitHub via Dex, Authelia, Keycloak, …), forward-auth proxy
Reading apps OPDS 1.2 catalogue at /opds/v1.2/ (KOReader, Moon+ Reader, Aldiko, …)

All download clients support Use SSL and URL Base for connections through a reverse-proxy subpath.

Architecture

Bindery is a single Go binary (chi router, distroless container) with the React 19 + TypeScript frontend embedded via go:embed, talking to SQLite in WAL mode through the pure-Go modernc.org/sqlite driver — no CGO, no external database, no sidecars.

   Newznab / Torznab
      indexers
         │
         ▼
┌────────────────────────────┐
│         Bindery            │──► SABnzbd / NZBGet / qBittorrent / Transmission / Deluge
│  Go backend + React SPA    │──► /books/ library
│  SQLite (WAL mode)         │──► Webhook notifications
└────────────────────────────┘
    ▲                    ▲
    │                    │
OpenLibrary      Google Books, Hardcover.app, DNB, Audnex, Audible
 (primary)                 (enrichers)

Component breakdown, package layout, concurrency model, and design rationale are in docs/ARCHITECTURE.md.

API

Every feature is exposed under /api/v1/*, with an arr-compatible /api/queue for external tools and an OPDS catalogue at /opds/v1.2/. Quick taste:

# Add an author by OpenLibrary ID and start monitoring
curl -X POST -H "X-Api-Key: $KEY" -H "Content-Type: application/json" \
  -d '{"foreignAuthorId":"OL23919A","monitored":true,"searchOnAdd":true}' \
  http://bindery:8787/api/v1/author

# List wanted books
curl -H "X-Api-Key: $KEY" "http://bindery:8787/api/v1/book?status=wanted"

The full endpoint catalogue, authentication rules (API key, session cookie, local-only, OIDC, proxy), CSRF semantics, and integration examples are in docs/API.md.

Documentation

Topic Where
Quickstart — first author to first grab in 10 minutes Wiki
Deployment — Docker, Compose, k8s/Helm, binary, UID/GID, env vars, upgrades docs/DEPLOYMENT.md
Architecture — components, data flow, dependencies docs/ARCHITECTURE.md
API — REST endpoints, auth, integration patterns docs/API.md
ABS import — setup, path remap, review queue, rollback, matching behavior docs/abs_import.md
Enhanced Hardcover series — token setup, series linking, catalog diffs, missing-book fill docs/Hardcover-Series-Wiki.md
Roadmap — planned work and explicitly-out-of-scope items docs/ROADMAP.md
Contributing & CI checks — dev setup, full quality/security matrix, local check suite CONTRIBUTING.md
Changelog — release notes CHANGELOG.md
Reverse-proxy & SSO setups — Traefik / Caddy / Nginx / Authelia / Authentik recipes Wiki
Troubleshooting — permission-denied, path-remap, import failures Wiki
Indexer & download-client recipes — NZBGeek / DrunkenSlug / Prowlarr / Jackett / SAB / qBit tips Wiki
Migrating from Readarr — step-by-step with known failure modes Wiki

Community

  • Discord — real-time help, setup questions, release chat: discord.gg/RpuYYRM9cZ. The #support channel is the best place to ask; #changelog is updated on every release. The three read-only voice channels at the top of the server show live active-install count, latest release, and GitHub star count, refreshed from the telemetry API every 10 minutes.
  • GitHub Issues — bug reports and feature requests: issues.
  • GitHub Discussions — open-ended design questions, show-and-tell, integration recipes: discussions.

Please keep security reports out of Discord and public issues — see SECURITY.md for the private disclosure channel.

Security

Security scans OpenSSF Scorecard Dependabot Security policy

Bindery holds API keys, reaches LAN services, and writes to disk — we take that seriously. Every push and weekly cron runs gosec, govulncheck, Semgrep, gitleaks, Trivy, Grype, Dockle, Syft, ZAP baseline, and OpenSSF Scorecard, with findings published as SARIF in GitHub's Security tab. Release images ship with SLSA build provenance and Syft SBOMs. In-app: SSRF guards on every outbound URL, hardened response headers (CSP, frame-deny, referrer-policy, auto-HSTS), distroless non-root read-only rootfs container with all caps dropped, and digest-pinned base images.

To report a vulnerability, follow the process in SECURITY.md. The full threat model and verification recipes live on the wiki Security page.

Telemetry

Bindery sends one anonymous ping per day to api.getbindery.dev so the maintainer can count active installs. The payload contains a random install_id (generated on first run), the binary version, os, and arch — no hostnames, IP addresses, library contents, or personal data. The response carries the latest published version, used for in-app update notifications. Opt out with telemetry.enabled: false in Settings → General, or BINDERY_TELEMETRY_DISABLED=true before first run.

Contributing

PRs, issues, and feedback welcome. See CONTRIBUTING.md for the dev setup, the full local check suite, and the PR flow. Tracked feature work lives in docs/ROADMAP.md — open an issue before starting anything substantial.

License

MIT. See LICENSE for details.

Acknowledgments

  • The *arr community for pioneering the monitor-search-download-import pattern
  • OpenLibrary for free, open book metadata
  • The Readarr project for the original vision, even though the implementation couldn't be sustained

Directories

Path Synopsis
cmd
bindery command
discord-stats command
discord-stats is a tiny one-shot binary that updates three Discord voice channel names with live Bindery telemetry numbers and GitHub stars.
discord-stats is a tiny one-shot binary that updates three Discord voice channel names with live Bindery telemetry numbers and GitHub stars.
telemetry-server command
telemetry-server is a tiny HTTP service that counts active Bindery installs.
telemetry-server is a tiny HTTP service that counts active Bindery installs.
internal
abs
Package abs provides Audiobookshelf client, normalization, and import logic.
Package abs provides Audiobookshelf client, normalization, and import logic.
api
Package api contains the HTTP handlers served under /api/v1 by the chi router.
Package api contains the HTTP handlers served under /api/v1 by the chi router.
auth
Package auth implements password hashing, signed session cookies, the composite auth middleware (cookie OR API key OR local-bypass), and the small helpers those require.
Package auth implements password hashing, signed session cookies, the composite auth middleware (cookie OR API key OR local-bypass), and the small helpers those require.
auth/oidc
Package oidc implements OIDC Authorization Code + PKCE for Bindery.
Package oidc implements OIDC Authorization Code + PKCE for Bindery.
calibre
Package calibre wraps Calibre's `calibredb` command-line utility so the importer can mirror Bindery's library into a user-configured Calibre library.
Package calibre wraps Calibre's `calibredb` command-line utility so the importer can mirror Bindery's library into a user-configured Calibre library.
config
Package config loads Bindery's runtime configuration from environment variables with sensible defaults.
Package config loads Bindery's runtime configuration from environment variables with sensible defaults.
db
Package db contains the SQLite connection bootstrap, embedded migrations, and per-resource repository types backing the rest of Bindery.
Package db contains the SQLite connection bootstrap, embedded migrations, and per-resource repository types backing the rest of Bindery.
decision
Package decision implements a specification-based release evaluation engine.
Package decision implements a specification-based release evaluation engine.
downloader
Package downloader provides a unified interface for dispatching download requests to different download clients (SABnzbd, NZBGet, Transmission, qBittorrent, Deluge).
Package downloader provides a unified interface for dispatching download requests to different download clients (SABnzbd, NZBGet, Transmission, qBittorrent, Deluge).
downloader/deluge
Package deluge provides a client for the Deluge Web UI JSON-RPC API, used to submit magnet/torrent URLs and poll status for torrent downloads.
Package deluge provides a client for the Deluge Web UI JSON-RPC API, used to submit magnet/torrent URLs and poll status for torrent downloads.
downloader/nethint
Package nethint classifies network errors and returns a short contextual hint string to append to "could not reach …" messages shown to users.
Package nethint classifies network errors and returns a short contextual hint string to append to "could not reach …" messages shown to users.
downloader/nzbget
Package nzbget provides a client for the NZBGet JSON-RPC API, used to submit NZB URLs and poll queue/history for Usenet downloads.
Package nzbget provides a client for the NZBGet JSON-RPC API, used to submit NZB URLs and poll queue/history for Usenet downloads.
downloader/qbittorrent
Package qbittorrent provides a client for the qBittorrent WebUI API v2, used to submit magnet/torrent URLs and poll status for torrent downloads.
Package qbittorrent provides a client for the qBittorrent WebUI API v2, used to submit magnet/torrent URLs and poll status for torrent downloads.
downloader/sabnzbd
Package sabnzbd provides a client for the SABnzbd JSON API, used to submit NZB URLs and poll queue/history for Usenet downloads.
Package sabnzbd provides a client for the SABnzbd JSON API, used to submit NZB URLs and poll queue/history for Usenet downloads.
downloader/transmission
Package transmission provides a client for the Transmission BitTorrent daemon RPC API, used to submit magnet/torrent URLs and poll status for torrent downloads.
Package transmission provides a client for the Transmission BitTorrent daemon RPC API, used to submit magnet/torrent URLs and poll status for torrent downloads.
downloader/urlbase
Package urlbase normalises user-supplied URL base paths for download-client connections.
Package urlbase normalises user-supplied URL base paths for download-client connections.
grimmory
Package grimmory provides a client for the Grimmory self-hosted digital library API.
Package grimmory provides a client for the Grimmory self-hosted digital library API.
hardcoverlistsyncer
Package hardcoverlistsyncer syncs Hardcover reading lists into Bindery's book catalogue as "wanted" books.
Package hardcoverlistsyncer syncs Hardcover reading lists into Bindery's book catalogue as "wanted" books.
httpsec
Package httpsec provides outbound-URL validation to prevent SSRF attacks.
Package httpsec provides outbound-URL validation to prevent SSRF attacks.
importer
Package importer moves completed downloads into the configured library directory using a configurable naming template, and reconciles pre-existing library files against the tracked book database.
Package importer moves completed downloads into the configured library directory using a configurable naming template, and reconciles pre-existing library files against the tracked book database.
indexer
Package indexer coordinates book searches across multiple Newznab/Torznab indexers, filters and ranks the returned releases, and exposes a release- name parser shared by the filter pipeline and the import path.
Package indexer coordinates book searches across multiple Newznab/Torznab indexers, filters and ranks the returned releases, and exposes a release- name parser shared by the filter pipeline and the import path.
indexer/newznab
Package newznab provides a client for Newznab- and Torznab-compatible indexers used for book search.
Package newznab provides a client for Newznab- and Torznab-compatible indexers used for book search.
isbnutil
Package isbnutil normalizes ISBN inputs for metadata provider lookups.
Package isbnutil normalizes ISBN inputs for metadata provider lookups.
logbuf
Package logbuf provides an in-process ring buffer for slog records so the UI can surface recent log entries without requiring shell access.
Package logbuf provides an in-process ring buffer for slog records so the UI can surface recent log entries without requiring shell access.
metadata
Package metadata aggregates book and author data from multiple public sources (OpenLibrary, Google Books, Hardcover) behind a unified interface.
Package metadata aggregates book and author data from multiple public sources (OpenLibrary, Google Books, Hardcover) behind a unified interface.
metadata/audible
Package audible provides a read-only client for Audible's public catalogue API (api.audible.com).
Package audible provides a read-only client for Audible's public catalogue API (api.audible.com).
metadata/audnex
Package audnex provides a read-only client for api.audnex.us, a public JSON wrapper around Audible's catalogue.
Package audnex provides a read-only client for api.audnex.us, a public JSON wrapper around Audible's catalogue.
metadata/dnb
Package dnb provides a read-only client for the Deutsche Nationalbibliothek (DNB) via its public SRU endpoint.
Package dnb provides a read-only client for the Deutsche Nationalbibliothek (DNB) via its public SRU endpoint.
metadata/googlebooks
Package googlebooks provides a read-only client for the Google Books API, used as a metadata enricher for author and book details.
Package googlebooks provides a read-only client for the Google Books API, used as a metadata enricher for author and book details.
metadata/hardcover
Package hardcover provides a read-only GraphQL client for hardcover.app, used as a metadata enricher for community ratings and series data.
Package hardcover provides a read-only GraphQL client for hardcover.app, used as a metadata enricher for community ratings and series data.
metadata/openlibrary
Package openlibrary provides the primary book metadata client.
Package openlibrary provides the primary book metadata client.
metrics
Package metrics exposes Bindery runtime metrics in Prometheus exposition format.
Package metrics exposes Bindery runtime metrics in Prometheus exposition format.
migrate
Package migrate bulk-imports authors and related records into Bindery from external sources — a Readarr SQLite DB or a plain CSV of names.
Package migrate bulk-imports authors and related records into Bindery from external sources — a Readarr SQLite DB or a plain CSV of names.
models
Package models defines the domain types shared across the API, database, scheduler, and indexer layers.
Package models defines the domain types shared across the API, database, scheduler, and indexer layers.
notifier
Package notifier dispatches webhook notifications for grab, import, failure, and health events to user-configured HTTP endpoints.
Package notifier dispatches webhook notifications for grab, import, failure, and health events to user-configured HTTP endpoints.
opds
Package opds builds OPDS 1.2 / Atom 1.0 catalogue feeds from Bindery's authors / books / series tables.
Package opds builds OPDS 1.2 / Atom 1.0 catalogue feeds from Bindery's authors / books / series tables.
prowlarr
Package prowlarr provides a client for the Prowlarr API and a syncer that creates/updates/removes Bindery indexer entries from a Prowlarr instance.
Package prowlarr provides a client for the Prowlarr API and a syncer that creates/updates/removes Bindery indexer entries from a Prowlarr instance.
recommender
Package recommender implements Bindery's content-based book recommendation engine.
Package recommender implements Bindery's content-based book recommendation engine.
scheduler
Package scheduler runs Bindery's periodic background jobs (wanted-book search, download-status polling, metadata refresh, library rescan) via robfig/cron.
Package scheduler runs Bindery's periodic background jobs (wanted-book search, download-status polling, metadata refresh, library rescan) via robfig/cron.
seriesmatch
Package seriesmatch contains title and position matching helpers shared by Audiobookshelf import and user-triggered series linking.
Package seriesmatch contains title and position matching helpers shared by Audiobookshelf import and user-triggered series linking.
telemetry
Package telemetry sends an anonymous once-daily ping to api.getbindery.dev so the project maintainer can count active installs.
Package telemetry sends an anonymous once-daily ping to api.getbindery.dev so the project maintainer can count active installs.
textutil
Package textutil contains small normalization and cleanup helpers used across imports and API responses.
Package textutil contains small normalization and cleanup helpers used across imports and API responses.
webui
Package webui bundles the compiled React frontend assets into the Go binary via go:embed so Bindery ships as a single executable.
Package webui bundles the compiled React frontend assets into the Go binary via go:embed so Bindery ships as a single executable.
tests
abscontract
Package abscontract provides the pinned Audiobookshelf contract harness and fixtures.
Package abscontract provides the pinned Audiobookshelf contract harness and fixtures.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL