Running Shelf
Running on a server
HTTPS and a reverse proxy
Passwords, device keys, and passkeys need HTTPS on any shelf reached from outside your own network. The usual way is a reverse proxy that holds the certificate and passes requests to Shelf. Tell Shelf it is there with Hosting:BehindProxy set to true, so it trusts the proxy's forwarded headers, and only when Shelf can't be reached except through it.
Caddy
Caddy gets and renews a certificate by itself:
shelf.example.org {
reverse_proxy localhost:8080
}
nginx
server {
listen 443 ssl;
server_name shelf.example.org;
# ssl_certificate and ssl_certificate_key, from Let's Encrypt, say
client_max_body_size 1100m; # audiobooks can be up to 1 GB; raise it with Uploads:MaxAudioMegabytes
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 1h;
}
}
The Upgrade lines matter: Shelf's pages keep a WebSocket open to the server.
Tip
Set Email:PublicAddress and Passkeys:Origin to the address readers use, such as https://shelf.example.org, so links in emails and passkeys are right.
Without a proxy, Shelf sends HSTS and redirects HTTP to HTTPS whenever it has an HTTPS port of its own.
OCR for scanned PDFs
Reading scanned pages needs Tesseract and Poppler. The Docker image has both, with English. From source, install them yourself; Shelf looks for tesseract, pdftoppm, pdftotext, and pdfinfo on the path when it starts.
# Debian and Ubuntu
sudo apt install tesseract-ocr tesseract-ocr-eng poppler-utils
# Arch Linux
sudo pacman -S tesseract tesseract-data-eng poppler
# macOS
brew install tesseract poppler
For other languages, install their Tesseract data and list them in Ocr:Languages, such as eng+fra. In Docker, extend the image:
FROM ghcr.io/doodersrage/shelf:latest
USER root
RUN apt-get update && apt-get install -y --no-install-recommends tesseract-ocr-fra && rm -rf /var/lib/apt/lists/*
USER app
Each PDF is read once, a page at a time, and the words are kept in the database, so a restart carries on where it stopped.
Calibre for Kindle files
Kindle files are turned into EPUBs by Calibre's ebook-convert. Install Calibre on the server, or build the Docker image with it:
docker build --build-arg CALIBRE=true -t shelf https://github.com/doodersrage/shelf.git
Email lets readers reset a forgotten password themselves and get their notifications by email, which is on for each reader until they turn it off. Readers sign in with their email address whether or not the shelf can send email. Any SMTP server works: your email provider's, or a service such as Fastmail, Mailgun, or Amazon SES. Configuration lists the settings. Readers can send themselves a test from Account once their address is saved.
Disk space
Plan for your files more than Shelf itself: e-books are a few megabytes each, audiobooks a few hundred, and the database stays small. Held uploads that nobody decided on are cleared after a day.
When buttons do nothing
Most buttons on Shelf's pages work through a live connection to the server (a WebSocket, or a slower fallback when that is not allowed). If it cannot start, a banner at the bottom of the page says so. The usual causes:
- A browser extension that blocks scripts or WebSockets, such as uBlock Origin in advanced mode, NoScript, or Privacy Badger. Allow your Shelf's address in it, then reload.
- A reverse proxy that does not pass WebSockets on. In nginx, add
proxy_http_version 1.1;and theUpgradeandConnectionheaders; Caddy and Traefik pass them on by themselves. - A strict corporate or school network that blocks WebSockets.
Links and forms work without the connection. In the browser's developer tools, the page's <html> element carries data-live: connected when all is well, failed when the connection could not start.
How big a library can be
Shelf was tried with a library of 10,000 books, 2,000 of them with an e-book, on a desktop computer (a 12-core Ryzen 9, so a Raspberry Pi or a small NAS will be a few times slower):
| What | Time |
|---|---|
| The library, any view | about 140 ms |
| Stats | about 220 ms |
| A book's page, Authors, Series, Shelves, Quotes | under 20 ms |
| Search inside books | under 10 ms |
| All books as JSON (7 MB) | about 200 ms |
| A snapshot of the whole server | about 140 ms |
The server used about 75 MB of memory for it. The library draws 60 books at a time, so a long list stays quick in the browser too.