- Go 71.9%
- JavaScript 21.2%
- CSS 5.6%
- Python 0.8%
- NSIS 0.2%
- Other 0.2%
|
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
RFC 6749 §2.3.1 requires confidential clients to send the id/secret as a form-urlencoded Basic header; sending the secret only in the POST body (client_secret_post) breaks against providers that pin the registered token_endpoint_auth_method — Authelia rejected the exchange with invalid_client when the client was registered with the default basic method. Both call sites (authorization_code exchange and refresh grant) now set the Basic header; the form fields stay for providers that require the post method. The fake IdP in the e2e test now validates the Basic credentials, and the CI image tag bumps to v0.1.22-polka.2. |
||
|---|---|---|
| .github | ||
| cmd | ||
| collections | ||
| docs | ||
| internal | ||
| packaging | ||
| web | ||
| .dockerignore | ||
| .gitignore | ||
| .woodpecker.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| Makefile | ||
| oidc_smoke.py | ||
| README.md | ||
Polka
Your home e-book library — fast, private, and beautiful.
Polka (Russian for "bookshelf") is a self-hosted library for e-book
collection. Point it at a folder of books — or import a huge .inpx catalog —
and get a polished web interface with search, covers, annotations, an online
reader, reading lists, ratings, recommendations, and an OPDS feed for every
mobile reading app.
Highlights
- Built for big collections. A 690,000-book catalog imports in about a minute and stays instant to browse and search (SQLite + FTS5 under the hood).
- Read in your browser. A clean, newspaper-style reader for FB2, EPUB and TXT with continuous scrolling, themes (light / sepia / dark), adjustable fonts, footnotes, live tables of contents, and per-user reading progress. PDF opens in a dedicated reader with the same progress tracking.
- Find your next book. Personal shelves: Reading now, Want to read, Continue the series, and For you — recommendations scored from your ratings, lists, and reading history. Plus "similar books" on every book page, optionally enriched by external sources (FantLab, TasteDive).
- Search everything. Titles, authors, series, genres — and ISBN: paste an ISBN in any format and Polka finds the book locally or resolves it via Open Library / Google Books.
- Reading lists & ratings. Build custom lists, mark books you want to read, rate books 1–5 — average ratings are visible to everyone on your server. External ratings (LiveLib, Google Books, Open Library) can be enabled per source by the admin.
- Curated collections. Well-known book lists — 100 Books of the Century
(Le Monde), BBC's The Big Read, the Norwegian Book Club's 100 best books
and more — ship with Polka and appear as home-page shelves showing which of
the listed books you already have. Add your own as a JSON list of
"author + title", or enable an external source (Forbes.ru book selections,
polled daily; off by default). See
collections/. - OPDS catalog. Connect Moon+ Reader, KOReader, FBReader, or any other OPDS-capable app: new books, browse by author, series and genre, your "reading now" shelf, and search.
- E-ink reader progress sync. Polka speaks the KOReader sync protocol (kosync): KOReader on PocketBook, Kindle, Kobo, reMarkable and friends pushes the reading position straight to your server, and books read on the device show their progress on Polka's "Reading now" shelf. Each user sets a device password in the top-bar "E-reader" dialog.
- Send to your e-reader. Configure SMTP once and e-mail any book straight to your Kindle / Kobo / PocketBook from its page (the SMTP password is stored encrypted).
- Multi-user. Accounts with admin/reader roles, per-user progress, lists and ratings. Or run it fully open on a trusted home network.
- Add books from the browser. Upload fb2 / epub / pdf / djvu / txt / mobi; metadata is extracted automatically and three-level duplicate detection (file hash → text hash → fuzzy metadata) keeps your collection clean.
- Two languages. English and Russian UI, switchable in one click; genre names and the OPDS feed are localized too.
- Mobile-friendly + PWA. Add Polka to your phone's home screen and it behaves like an app.
- Desktop apps that don't need a server. Native-feel clients for Windows and Linux work fully standalone: your library, reader, lists and ratings live right on your machine — no server, no account, no internet required. Optionally connect them to your Polka server later and get two-way sync of progress, ratings, and lists, including offline copies of selected books.
Quick start
Docker (recommended for servers)
docker run -d --name polka \
-p 12791:12791 \
-v polka-data:/data \
-v /path/to/your/books:/books \
ghcr.io/vestigiumincaligne/polka:latest
Open http://localhost:12791, sign in with the bootstrap admin account
(created on first run — see the container log: docker logs polka), and start
exploring. Or use docker-compose.yml:
docker compose up -d
Desktop app — no server required
If you just want a personal library on one computer, skip the server entirely:
install the desktop app from the releases page
(polka-setup-<version>.exe on Windows, .deb/.rpm on Linux) and launch
Polka. It opens in its own window, stores everything locally, and works
offline. You can connect it to a server later at any time — nothing to
reconfigure.
Prebuilt binaries and installers
Grab the latest release:
| Platform | What you get |
|---|---|
| Windows | polka-setup-<version>.exe — installer for the desktop app (server included) |
| Linux | .deb / .rpm packages (amd64, arm64), plus standalone binaries |
| Raspberry Pi | 64-bit OS → polka-linux-arm64 (or the arm64 .deb / Docker); 32-bit OS → polka-linux-arm |
| Any | polka server binary — single file, no dependencies |
Run the server directly:
polka serve --library-dir /path/to/books
Build from source
Requires Go 1.26+ and Node 20+.
git clone https://github.com/vestigiumincaligne/polka
cd polka
make build # builds web UI + bin/polka + bin/polka-desktop
./bin/polka serve --library-dir /path/to/books
Importing a large catalog
Polka understands .inpx index files (MyHomeLib / Flibusta format) — both
from the command line and from the web UI (Manage → Import):
polka import --inpx collection.inpx --data-dir /path/to/data --library-dir /path/to/archives
You can also import an inpx that already sits on the server (e.g. a
mounted or NFS collection) straight from the web UI — paste its path in
Manage → Import instead of uploading. The book archives are looked up
under --library-dir.
Book files may sit in plain folders or inside ZIP or 7z archives (the
usual Flibusta layout, e.g. f.fb2-….7z) — Polka reads them directly, no
unpacking needed.
Hundreds of thousands of records import in about a minute. Re-importing replaces the catalog but never touches user data — accounts, progress, ratings and lists live in a separate database and survive re-imports.
The desktop apps
polka-desktop opens Polka in its own window (WebView2 on Windows, Chromium
app window on Linux) and can work two ways:
- Standalone (default) — a personal library on your computer. No server, no sign-in, works completely offline.
- Connected — point it at your Polka server (Server page in the app): the full catalog is available online, selected books are downloaded for offline reading, and progress / ratings / lists sync both ways automatically.
OPDS
Point your reading app at http://your-server:12791/opds — no converting or
copying files, the books open straight on the device. Authentication is HTTP
Basic with your Polka account. The catalog has new books, browse by author,
by series, and by genre (alphabetical), search, and a personal "Reading now"
feed; downloads work in fb2, zip, epub, and pdf. The admin can turn OPDS on or
off and copy the connection address in Manage → OPDS.
E-ink readers (PocketBook, Kindle, Kobo…)
Install KOReader on the device, then:
- Books: add the OPDS catalog
http://your-server:12791/opds(your Polka login and password) — browse, search and download right on the device. PocketBook owners can also use Polka's Send to e-reader button with their@pbsync.comaddress. - Progress sync: in Polka's top bar open E-reader, set a device password; on the device: Tools → Progress sync, server address = your Polka URL, username = your Polka login, password = the device password. Positions of books downloaded through Polka then follow you between the device, the web reader and other KOReader devices.
Configuration
Everything has a sensible default. The most useful flags of polka serve:
| Flag | Default | Meaning |
|---|---|---|
--addr |
:12791 |
listen address |
--data-dir |
~/.polka |
database, settings, covers cache |
--library-dir |
— | folder with books (or inpx archives) |
--auth |
users |
users (accounts) or none (open access) |
OIDC single sign-on (fork addition)
This fork adds an OIDC Authorization Code flow for the web UI (this is a fork-local feature, not in upstream Polka). Configure via env:
| Variable | Meaning |
|---|---|
POLKA_OIDC_ISSUER |
Issuer URL — enables SSO when set (e.g. https://auth.example.com) |
POLKA_OIDC_CLIENT_ID |
Client ID registered at the provider |
POLKA_OIDC_CLIENT_SECRET |
Client secret (omit for public clients) |
POLKA_OIDC_REDIRECT_URL |
https://<polka-host>/auth/oidc/callback |
POLKA_OIDC_SCOPES |
Defaults to openid profile email |
POLKA_OIDC_ADMIN_GROUP |
Group claim value mapping: strict mirror — in the group = admin, not in the group = user (both promotion and demotion at login; a background re-sync applies the same rule to already-signed-in users). The last active administrator is never demoted. |
POLKA_OIDC_PROVIDER_NAME |
Label on the login button (default SSO) |
POLKA_OIDC_SYNC_INTERVAL |
Re-sync interval (Go duration, default 5m; negative disables the loop). Each round re-validates every OIDC user with a stored refresh token against the IdP and applies the strict role mirror — a deposed admin loses the role within one interval, without re-login. |
Behaviour:
- Discovery via
/.well-known/openid-configuration(endpoints + PKCE support are resolved at startup). Works with Authelia, Keycloak, Dex, LLDAP's OIDC endpoint, etc. - Authorization Code flow with
state+noncebound to a short-lived HttpOnly cookie; PKCE S256 when the provider supports it. - The local account is linked to the IdP by the
subclaim and JIT-provisioned on first sign-in (login frompreferred_username/ email local-part). - Strict role mirror: membership in
POLKA_OIDC_ADMIN_GROUPis authoritative — in the group means admin, not in the group means user. Applied at every login and by a background re-sync loop (refresh grant → userinfo, default every 5 minutes) so a deposed admin loses the role quickly without re-logging in. The last active administrator is never demoted (same guard as local user management), and a failing IdP never takes the library down — the loop just skips that round. - Local password login stays available for the bootstrap admin; OPDS readers keep using HTTP Basic (SSO does not apply to Basic clients).
Tested against a mock provider in internal/server/oidc_e2e_test.go
(full browser-style flow) and oidc_smoke.py (live binary + mock IdP).
External rating/recommendation sources are configured in the web UI (Manage → External ratings / Similar books) and are off by default except local recommendations — nothing is queried without the admin's consent.
Tech notes
- Single Go binary; the React frontend is embedded at build time.
- SQLite (pure-Go driver) with WAL and FTS5 — no database server to run.
- User data (accounts, sessions, progress, ratings, lists) is stored separately from the catalog and survives re-imports; so do curated collections, which are re-matched against the catalog after every import.
- Sync between desktop clients and the server is state-based with last-write-wins per record.
Support the project ❤️
Polka is free and MIT-licensed. If it made your library nicer, you can support development through the Sponsor button on this repository — it genuinely helps.
Bug reports and feature ideas are welcome in Issues.
