Self-host your reading stack with a clean web library, KOReader sync, and provider-powered book imports.
If you already use KOReader, Sake gives you a much nicer home base around it. You get a self-hosted web library, seamless progress sync, note-aware reading updates, easy book delivery to devices, and a built-in plugin update flow without losing the KOReader setup you already like.
For the fastest fully self-hosted setup, use the prebuilt Docker image and the bundled self-host compose file from the repository root:
docker compose -f docker-examples/docker-compose.prebuilt.selfhost.yaml up
Then open http://localhost:5173.
This setup gives you:
ghcr.io/sudashiii/sake imageOPDS and WebDAV endpoints use HTTP Basic authentication. By default, your normal account password works there. In Settings -> Account, you can optionally set a separate Basic-auth password for those routes while keeping your normal account password valid too.
This repository has three important layers:
sake/ - the actual SvelteKit app (Svelte 5 + SvelteKit + Bun)koreaderPlugins/ - the KOReader plugin shipped by the appdocs/ - shared project documentation and screenshotsIf you are working on the app itself, run app commands from sake/.
Use this if you want the easiest all-in-one setup for local or personal self-hosting.
It uses:
docker-examples/docker-compose.prebuilt.selfhost.yaml for the published image pathdocker-compose.selfhost.yaml at the repository rootsake/.env.docker.selfhostedFrom the repository root with the prebuilt image:
docker compose -f docker-examples/docker-compose.prebuilt.selfhost.yaml up
Or build it locally from source:
docker compose -f docker-compose.selfhost.yaml up --build
Then open http://localhost:5173.
Data is persisted under:
./.data/selfhost/libsql./.data/selfhost/seaweedfsUse this if you want to run only the Sake containers but keep your database and object storage elsewhere, for example:
Edit sake/.env, then start from the repository root with the prebuilt image:
docker compose -f docker-examples/docker-compose.prebuilt.yaml up
Or build it locally from source:
docker compose up --build
This Compose stack runs:
sake-migrator first (bun run db:migrate)sake after the migration succeedsThen open http://localhost:5173.
Use this if you are developing the app locally and already have a reachable database and S3-compatible storage.
Configure sake/.env, then run from sake/:
bun install
bun run db:migrate
bun run dev
Then open http://localhost:5173.
If you are not using Docker Compose, run bun run db:migrate before first boot and again after future schema changes.
Published images live at ghcr.io/sudashiii/sake.
Available tags:
latest<version> where <version> matches the existing CalVer without the webapp/v prefixsha-<shortsha>Example:
SAKE_IMAGE=ghcr.io/sudashiii/sake:2026.03.28.1 docker compose -f docker-examples/docker-compose.prebuilt.yaml up
Copy sake/.env.example to sake/.env and fill in the values you need.
LIBSQL_* - database connectionS3_* - S3-compatible object storage connectionVITE_ALLOWED_HOSTS - comma-separated host overrides for Vite/dev setupsACTIVATED_PROVIDERS - comma-separated search providersBODY_SIZE_LIMIT - upload/body size limitIf ACTIVATED_PROVIDERS is unset, blank, or contains no valid values, search stays disabled and the search UI remains hidden.
Accepted provider names:
anna, annas, annas-archive, or annasarchiveopenlib or openlibrarygutenbergzlib or zlibraryLIBSQL_URL=libsql://your-database-name.turso.io
LIBSQL_AUTH_TOKEN=your-turso-auth-token
S3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
S3_REGION=auto
S3_BUCKET=your-bucket-name
S3_ACCESS_KEY_ID=your-access-key-id
S3_SECRET_ACCESS_KEY=your-secret-access-key
S3_FORCE_PATH_STYLE=false
ACTIVATED_PROVIDERS=anna,openlib,gutenberg
VITE_ALLOWED_HOSTS=
BODY_SIZE_LIMIT=Infinity
LIBSQL_URL=file:./sake-selfhosted.db
LIBSQL_AUTH_TOKEN=
S3_ENDPOINT=http://localhost:8333
S3_REGION=us-east-1
S3_BUCKET=sake
S3_ACCESS_KEY_ID=sakeadmin
S3_SECRET_ACCESS_KEY=sakeadminsecret
S3_FORCE_PATH_STYLE=true
ACTIVATED_PROVIDERS=anna,openlib,gutenberg
VITE_ALLOWED_HOSTS=
BODY_SIZE_LIMIT=Infinity
If the database is empty, Sake exposes the normal bootstrap flow in the UI so you can create the first account there. You do not need to predefine a user in the environment.
The KOReader plugin lives in koreaderPlugins/sake.koplugin.
Basic setup flow:
Settings -> More tools -> Sake.Setup.Server URL.Device Name.Pair Device and log in with the same username and password you use in the web app.Sync, Library Import/Export, and Maintenance as needed.The login step exchanges your password for a device API key and clears the password from the device afterward.
You can also export ebooks from the devices home folder back to the web app, including sidecar data such as progress and notes. Great if you have a pre-existing library on your device!
KOReader plugin releases are tracked in the database and the artifacts are served through S3-compatible storage. If the KOReader plugin is updated and you start the app, the new version will be uploaded to S3 so you can use the updater plugin to easily update the core plugin without needing to manually move the files to your KOReader device.
Setup contains Server URL, Device Name, and Pair Device / Refresh Device KeySync contains Download New Books, Pull Progress From Other Devices, and Upload Current Book ProgressDownload New Books or when setting the device to sleepPull Progress From Other Devices to fetch newer progress from another readerLibrary Import/Export -> Import or Export Existing Library uploads books already on the device, along with sidecar data such as progress and notesMaintenance -> Check for Plugin Updates checks for new plugin releasesMaintenance -> Advanced -> Remote Log Shipping toggles shipping KOReader logs back to SakeSearch is provider-based and routed through POST /api/search.
anna, openlibrary, and gutenberg work as normal providers once enabled in ACTIVATED_PROVIDERSzlibrary also requires you to connect your Z-Library session in Settings -> LoginsTo enable Z-Library support, add it to ACTIVATED_PROVIDERS:
ACTIVATED_PROVIDERS=zlib,anna,openlib,gutenberg
In the app UI, open Settings -> Logins, then use Connect Z-Library and either:
remix_userid and remix_userkey from your Z-Library cookiesThe app uses those session values for authenticated Z-Library requests.
Run these from sake/:
bun run dev
bun run build
bun run preview
bun run check
bun run test
bun run db:generate
bun run db:migrate
bun run db:status
From the repository root, these compose entry points are available:
docker-compose.yaml for a managed source builddocker-compose.selfhost.yaml for a self-hosted source builddocker-examples/docker-compose.prebuilt.yaml for a managed prebuilt imagedocker-examples/docker-compose.prebuilt.selfhost.yaml for a self-hosted prebuilt image








This repository is licensed under AGPL-3.0-only.
See LICENSE for the full text.