Sign inSign up

tallon43/pdf-library

By tallon43

•Updated 19 days ago

Self-hosted personal PDF library: catalog, nested collections, cover thumbnails, reader & users

Image
0

682

tallon43/pdf-library repository overview

⁠pdf-library

Self-hosted personal library to store, organize and read PDF files (manuals, notes, papers, scanned invoices…), with a library-card catalog instead of a generic dashboard. Runs as a single Docker container (backend serves the API and the built frontend) and is designed for a home server such as TrueNAS SCALE, with storage paths configurable via environment variables.

⁠Features

  • Upload .pdf files (drag & drop or picker), one or many at once, with a configurable size limit.
  • Cover thumbnail (first page) generated automatically.
  • Reader with pagination, zoom and page navigation (view only, no editing).
  • Hierarchical collections (folders and subfolders, unlimited depth): create / rename / move / delete. Deleting a collection leaves its files uncategorized (never deletes them) and promotes its subfolders one level up.
  • Catalog filterable by collection and title search, and sortable (recent / A–Z / Z–A).
  • Edit metadata (title, collection) and delete documents.
  • Login with roles: admin (full control) and read-only user. Admins create users and share specific collections with each one (sharing a parent includes its subfolders).
  • English and Spanish UI, with the language remembered per user.

⁠Tags & architectures

  • tallon43/pdf-library:latest, tallon43/pdf-library:1.0.0
  • Multi-arch: linux/amd64 and linux/arm64

⁠Quick start

Create a .env file:

PORT=3000
MAX_UPLOAD_MB=50
JWT_SECRET=change-me-to-a-long-random-secret   # openssl rand -hex 32
ADMIN_USER=admin
ADMIN_PASSWORD=            # empty => a random one is generated and printed once in the log
STORAGE_HOST_PATH=./storage
DB_HOST_PATH=./data

docker-compose.yml:

services:
  pdf-library:
    image: tallon43/pdf-library:latest
    container_name: pdf-library
    restart: unless-stopped
    ports:
      - "${PORT:-3000}:3000"
    environment:
      PORT: 3000
      PDF_STORAGE_PATH: /data/storage
      DB_PATH: /data/db/library.db
      MAX_UPLOAD_MB: ${MAX_UPLOAD_MB:-50}
      JWT_SECRET: ${JWT_SECRET:?Set JWT_SECRET in .env}
      ADMIN_USER: ${ADMIN_USER:-admin}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD:-}
    volumes:
      - ${STORAGE_HOST_PATH:-./storage}:/data/storage
      - ${DB_HOST_PATH:-./data}:/data/db

Then:

docker compose up -d
docker compose logs -f pdf-library   # the generated admin password is shown here once

Open http://localhost:3000 and sign in.

Environment variables

┌──────────────────┬─────────────────────────────────────────────────────────────────────────────────┬─────────────────────┐
│     Variable     │                                   Description                                   │       Default       │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ PORT             │ Server port                                                                     │ 3000                │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ PDF_STORAGE_PATH │ Path where the real .pdf files are stored                                       │ /data/storage       │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ DB_PATH          │ Path to the SQLite metadata file                                                │ /data/db/library.db │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ MAX_UPLOAD_MB    │ Per-file upload size limit (MB)                                                 │ 50                  │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ JWT_SECRET       │ Secret used to sign the session JWT (required)                                  │ —                   │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ ADMIN_USER       │ Admin user created on first run                                                 │ admin               │
├──────────────────┼─────────────────────────────────────────────────────────────────────────────────┼─────────────────────┤
│ ADMIN_PASSWORD   │ Admin password. If empty, a random one is generated and printed once in the log │ (generated)         │
└──────────────────┴─────────────────────────────────────────────────────────────────────────────────┴─────────────────────┘

Volumes

- /data/storage — stored PDF files (and generated thumbnails under thumbs/)
- /data/db — SQLite database

Mount both from the host (or your TrueNAS datasets) to persist data across restarts.

First login

On first run the admin user (ADMIN_USER) is created. If you didn't set
ADMIN_PASSWORD, check the container log — the generated password is printed once.
From the user menu you can switch language, and from Users (admin only) you can create
more accounts and choose which collections each one can see.

License / notes

No credentials are baked into the image: the admin is created at first run from
environment variables. Keep your JWT_SECRET private.

---

Tag summary

Content type

Image

Digest

sha256:2d165d858…

Size

88.4 MB

Last updated

19 days ago

docker pull tallon43/pdf-library