Skip to content

ArchiveLabs/lenny

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Lenny Logo

Lenny

The open source Library-in-a-Box to preserve and lend digital books.
Learn more Β»

Issues Β· Pull Requests Β· License

Stars Forks Open Issues Pull Requests Last Commit License Ask DeepWiki

πŸ“– Table of Contents


About the Project

Lenny is a free, open source, Library-in-a-Box for libraries to preserve and lend digital books.

  • πŸ“š Designed for libraries that want control over their digital collections.
  • πŸ” Built with modern authentication, DRM, and flexible storage options.
  • 🌍 Easy to self-host, customize, and scale for any library size.
  • πŸš€ Active development and open to contributions!

πŸ” Authentication Modes

Lenny supports two authentication modes for lending:

  1. OAuth Implicit (Default): Standard OPDS authentication flow. Clients like Thorium Reader use this to request a token via a popup/webview.
  2. Direct Token (Beta): A simpler, link-based authentication flow. Useful for environments where full OAuth support is tricky.
    • Browser-Friendly: Users authenticate via an OTP (One-Time Password) email directly in the browser.
    • Configuration: Set LENNY_AUTH_MODE=direct in .env to enable globally.
    • Per-Request Override: Append ?beta=true to an OPDS borrow link to trigger this mode on demand.

To switch the global mode:

  1. Edit .env and set LENNY_AUTH_MODE=direct.
  2. Run make restart to apply changes instantly.

Features

  • Full Lending Workflow: Borrow, return, and manage digital books.
  • API-first: RESTful endpoints for integration and automation.
  • Containerized: Simple Docker deployment and robust Makefile for scripts.
  • Book Importer: Quickly load hundreds of test books for demos or pilots.
  • Readium Integration: Secure, browser-based reading experience.
  • Flexible Storage: S3, Internet Archive, or local file support.
  • Database-backed: Uses PostgreSQL and SQLAlchemy.

OPDS 2.0 Feed


Technologies

  • Docker for deployment and containerization
  • nginx as a reverse proxy
  • FastAPI (Python) as the web & API framework
  • Minio API for storing digital assets
  • YAML for configuring library-level rules
  • PostgreSQL for the database
  • SQLAlchemy as the Python ORM
  • Readium LCP for DRM
  • Readium Web SDK for a secure web reading experience
  • OPDS for syndicating holdings

Endpoints

  • /v{1}/api
  • /v{1}/manage
  • /v{1}/read
  • /v{1}/opds
  • /v{1}/stats

Getting Started

To install and run Lenny as a production application:

curl -fsSL https://raw.githubusercontent.com/ArchiveLabs/lenny/refs/heads/main/install.sh | sudo bash

Development Setup

git clone https://github.com/ArchiveLabs/lenny.git
cd lenny
make all
  • This will generate a .env file with reasonable defaults (if not present).
  • Navigate to localhost:8080 (or your $LENNY_PORT).
  • Enter the API container with:
    docker exec -it lenny_api bash

Adding Books encrypted or unencrypted

To add a book to Lenny, you must provide an OpenLibrary Edition ID (OLID). Books without an OLID cannot be uploaded.

Adding Books Metadata

Sign in to your Openlibrary.org account.

https://openlibrary.org/books/add

navigate to the above link and add all the details.

Usage

make addbook olid=OL123456M filepath=/path/to/book.epub [encrypted=true]

Examples

# Add an unencrypted book
make addbook olid=OL60638966M filepath=./books/mybook.epub

# Add an encrypted book
make addbook olid=OL60638966M filepath=./books/mybook.epub encrypted=true

# Using numeric OLID format (without OL prefix and M suffix)
make addbook olid=60638966 filepath=./books/mybook.epub

Important Notes

  • File Location: The EPUB file must be within the project directory (e.g., in ./books/ or project root)
  • OLID Formats: Accepts both OL123456M and 123456 formats
  • Duplicates: If a book with the same OLID already exists, the upload will fail with a conflict.

Troubleshooting

If you get a "File not found" or permission error, make sure:

  1. The file is copied into your lenny project directory.
  2. You're using a relative path from the project root (e.g., ./books/mybook.epub)

Testing Readium Server

BOOK=$(echo -n "s3://bookshelf/32941311.epub" |  base64 | tr '/+' '_-' | tr -d '=')
echo "http://localhost:15080/$BOOK/manifest.json"
curl "http://localhost:15080/$BOOK/manifest.json"

Rebuilding

docker compose -p lenny down
docker compose -p lenny up -d --build

FAQs

Everything is broken and I need to start from scratch
make tunnel rebuild start preload items=10 log
If I disconnect from the internet and tunnel stops working, what do I do?
make untunnel tunnel start
I am getting database connection problems
make resetdb restart preload items=5
I need to stop services (also kills the tunnel)
make stop 
The /v1/api/items/{id}/read endpoint redirects to Nginx default page

This happens when using docker compose up -d directly instead of make start or make build.

Why it happens: The Thorium Web reader requires NEXT_PUBLIC_* environment variables at build time. When running docker compose up -d directly, these variables may not be passed correctly.

Solution: Use the Makefile commands which properly source the environment:

# Fast build (uses cache)
make build

# Full rebuild (no cache)
make rebuild

Both commands source reader.env before building, ensuring the reader is configured correctly.


Tests

All automated tests are in the tests/ directory.

To run tests:

pytest
  • Install dependencies:
    pip install -r requirements.txt
  • Test configs via .env.test if needed.

Project Structure

/
β”œβ”€β”€ lenny/                # Core application code
β”‚   └── routes/           # API route definitions and docs
β”œβ”€β”€ scripts/              # Utility scripts (e.g. load_open_books.py)
β”œβ”€β”€ tests/                # Automated tests
β”œβ”€β”€ docker/               # Docker configuration
β”œβ”€β”€ Makefile              # Make commands for setup/maintenance
β”œβ”€β”€ install.sh            # Production install script
β”œβ”€β”€ .env                  # Environment variables (generated)
└── README.md             # Project documentation

Contributing

There are many ways volunteers can contribute to the Lenny project, from development and design to data management and community engagement. Here’s how you can get involved:

Developers

  • Getting Started: Check out our Development Setup for instructions on how to set up your development environment, find issues to work on, and submit your contributions.
  • Good First Issues: Browse our Good First Issues to find beginner-friendly tasks.

Community Engagement

  • Join our Community Calls: Open Library hosts weekly community Zoom call for Open Library & Lenny and design calls. Check the community call schedule for times and details.
  • Ask Questions: If you have any questions, request an invitation to our Slack channel on our volunteers page.

Lenny Slack Channel

  • If you are a Developer or an library instrested in contributing or trying lenny feel free to join our lenny slack channel from Here

For more detailed information on community call. refer to Open Libraries page Here


Pilot

We're seeking partnerships with libraries who would like to try lending digital resources to their patrons.


Open Topics

  • Authentication - How does your library perform authentication currently?

Community & Support


πŸ“„ License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).


Empowering libraries to share digital knowledge.

About

An open source set of Lending APIs

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 6