Kavita: Self-Hosted Reading Server for Manga, Comics, and Ebooks
If you’ve ever wanted Jellyfin-style library management for your book and manga collection, Kavita is the closest thing to it. It’s a self-hosted reading server that automatically organizes manga, comics, light novels, and ebooks into series, tracks your reading progress across devices, and serves content via a polished web reader or OPDS to third-party apps.
With 10,000+ GitHub stars and regular releases, it’s the most actively maintained option in the self-hosted comic/manga server space. The core is open-source and fully functional without paying anything — Kavita+ (a paid subscription) adds metadata syncing with AniList and scrobbling, but everything else works out of the box.
Supported Formats
Kavita handles four categories of content, each with its own optimized reader:
Comics and manga (image-based archives):
- CBZ — Comic Book ZIP (most widely used)
- CBR — Comic Book RAR
- CB7 — Comic Book 7-zip
- CBT — Comic Book TAR
- Loose image folders (JPG, PNG, WebP, AVIF)
Documents:
- EPUB — ebooks and light novels
- PDF — documents and scanned books
Each format gets a hand-crafted reader. The manga/comic reader has single-page, double-page, and webtoon modes. The EPUB reader handles reflowable text. The PDF reader is separate from both. You’re not getting a generic iframe dump — each format is rendered thoughtfully.
Architecture
Kavita is a C#/.NET ASP.NET Core backend with an Angular frontend. The database is SQLite via Entity Framework Core — no PostgreSQL or MySQL needed, which simplifies both deployment and backup. The entire application ships as a single Docker image.
Authentication is JWT-based. The scanner runs on background threads, parsing filenames and folder structures to build the library index, and extracts metadata from embedded ComicInfo.xml files when present. Cover images are generated asynchronously — they won’t appear the instant a series is indexed, but they arrive shortly after.
Resource requirements are low. The documented minimum is a 1 GHz single-core CPU and 256 MB RAM, and most homelabs will have plenty of headroom. One hardware caveat worth knowing: cover generation requires SSE4.2 CPU instructions. This is present in any Intel Core i3 or newer, and any modern AMD CPU — but Pentium and Celeron chips lack it. On those, covers either fail or render incorrectly.
Deploying with Docker Compose
Basic Setup
|
|
Media directories on the host are mounted into the container. The internal paths (/manga, /comics, /books) are arbitrary — you’ll point Kavita’s library configuration at whichever container paths you use. The config directory at /kavita/config stores the SQLite database, logs, and settings. Back this up; it’s everything.
PUID and PGID ensure Kavita runs as your user instead of root, so it can read your media files without permission issues. Set these to match the UID/GID of your media files (id your-username to check).
Behind Traefik
For HTTPS termination — required if you want remote access via iOS apps like Panels:
|
|
No ports: block needed — Traefik routes directly to port 5000 inside the container.
Library Setup
On first login you’ll create libraries. Each library has a type that controls how Kavita interprets the content:
| Type | Use for |
|---|---|
| Manga | Japanese manga, organized by volume/chapter |
| Comic | Western comics, TPBs, annuals, one-shots |
| Book | Ebooks, organized as series |
| Light Novel | Japanese light novel series |
| Loose Images | Custom image folders without a specific format |
You can have multiple libraries of the same type — separate libraries for manga and manhwa, for example, or separate libraries for different physical locations. Point each library at one or more folders, and Kavita scans them.
Folder watching detects new files automatically with roughly a 10-minute delay. One limitation: Docker on Windows (WSL2) doesn’t support folder watching. On Windows, use manual scanning instead — trigger it on demand from the library settings or set a scan schedule.
File Naming and Organization
This is the area that trips up most new Kavita users. Understanding how the scanner parses files prevents a lot of confusion.
The Core Rule
Everything must be inside a series folder. Files at the library root are ignored. The structure looks like this:
/manga/
├── Attack on Titan/
│ ├── Attack on Titan - v01.cbz
│ ├── Attack on Titan - v02.cbz
│ └── Attack on Titan - v03.cbz
├── Demon Slayer/
│ ├── Demon Slayer - v01.cbz
│ └── Demon Slayer - v02.cbz
└── One Piece/
├── One Piece - v001.cbz
└── One Piece - v002.cbz
Kavita groups files with the same series name into one series entry. Volume numbers (v01, v02) drive ordering. Chapter numbers can be embedded in filenames too (c001), but volume numbers are the primary grouping key for most manga.
Naming Conventions
Volume markers: v01, v02, v003 — Kavita handles zero-padding variations.
Chapter markers: c001, c002 — used when you have chapter-level granularity without volumes.
Specials: Prefix with SP — these appear in a separate “Specials” section rather than the main volume list. Example: Attack on Titan - SP01 Side Story.cbz
The parentheses gotcha: Kavita strips content in parentheses during parsing. A file named Series Name (2019) - v01.cbz gets parsed as series Series Name with the (2019) discarded. If you need a year or variant marker in the filename, use curly braces instead:
# Wrong — parentheses get stripped
Series Name (2019) - v01.cbz
# Correct — curly braces preserved
Series Name {2019} - v01.cbz
Numbers in series names can be misidentified as chapter numbers without a ComicInfo.xml to anchor the metadata. If you have a series like Gundam 00, embed a ComicInfo.xml to make the series name explicit.
Priority Order
Kavita’s metadata resolution goes:
- Embedded
ComicInfo.xml— always wins - EPUB metadata (for book libraries)
- Filename parsing
- Folder structure
If your files have a ComicInfo.xml, the filename format matters less. If they don’t, follow the naming conventions carefully.
ComicInfo.xml
ComicInfo.xml is the standard metadata format for comic archives. Place it at the root of the archive (not in a subfolder), and Kavita will read it on scan.
Useful tags:
|
|
LocalizedSeries enables searching by the original language title. SeriesGroup creates a collection grouping multiple series together. Count drives publication status detection: if Count is set and greater than zero, Kavita marks the series as Ended; if the count matches the actual volume count in your library, it marks it as Completed.
Tools like Komf can automatically fetch and embed ComicInfo.xml from MangaUpdates, AniList, and other sources — useful for large existing libraries.
Reading Experience
The web reader is the main interface. Key features:
Reading modes:
- Single page — one image at a time, standard for Western comics
- Double page — landscape spread, good for wide panels
- Webtoon mode — continuous vertical scroll, essential for Korean manhwa and long-strip manga. Kavita can auto-switch to webtoon mode based on image aspect ratios.
Reading direction: Left-to-right or right-to-left, configurable per-library or per-series.
Progress tracking: Kavita tracks your position at the page level and syncs across devices. If you start reading on your desktop and switch to your phone, you continue where you left off.
Collections: Group series together (e.g., “Marvel”, “Shonen Jump”). Users can create personal collections; admins can promote them to server-wide collections.
Reading lists: Ordered sequences of chapters across series. Useful for reading events that span multiple titles, or for recommended reading orders. Can be imported from .cbl (Comic Book List) files.
Bookmarks: Mark specific pages for reference without affecting read progress.
User Management
Kavita supports multiple users with per-library access control:
- Users only see libraries explicitly shared with them
- Age restriction system — admins can set content rating limits per user; series with ratings above the limit are hidden entirely
- Unrated content can be configured to show or hide for restricted users
- Admins bypass all restrictions
Authentication supports both local username/password and OIDC for SSO with Authentik, Keycloak, or other providers. Configure OIDC in Admin → Settings after deployment.
OPDS for External Apps
OPDS (Open Publication Distribution System) is the standard protocol for serving ebooks and comics to external reader apps. Kavita implements OPDS and OPDS-PS (the page streaming extension for image-based content).
Each user gets a unique OPDS URL and API key, visible in their profile settings. The format is:
https://manga.yourdomain.com/api/opds/{api-key}
Compatible apps:
| App | Platform | Protocol | Progress Sync |
|---|---|---|---|
| Panels | iOS/macOS | OPDS-PS | Yes (via Kavita) |
| KOReader | Android/Linux | OPDS-PS | Yes |
| Moon+ Reader | Android | OPDS | No |
| Mihon/Tachiyomi | Android | Kavita extension | Chapter-level |
| Booklore | Web | OPDS | Limited |
iOS note: Panels requires HTTPS for remote connections. This is why the Traefik setup with a real certificate matters — without it, Panels won’t connect from outside your local network.
Tachiyomi/Mihon Integration
For Android manga readers using Tachiyomi or its forks (Mihon, Yokai, etc.), there’s a Kavita extension that connects directly to the API rather than going through OPDS. Install it via the extension’s repository, add your server URL and API key, and your Kavita library appears as a source. Progress sync happens at the chapter level — marking a chapter complete in Mihon marks it read in Kavita.
Kavita+
Kavita+ is an optional subscription that unlocks metadata features. Key distinction: it’s priced per server instance, not per user. One subscription covers everyone using that server.
What Kavita+ adds:
- Metadata matching from AniList — automatically fetch series descriptions, cover art, genre tags, and staff info from AniList and apply them to your library
- Scrobbling to AniList — sync your reading progress to your AniList account (takes the maximum between local and remote, so it won’t overwrite further-ahead progress)
- Recommendations — discover new series based on your reading history
- Smart Collections — advanced collection filtering based on metadata
Without Kavita+:
- All reading features work normally
- Local metadata from
ComicInfo.xmland EPUB tags is fully processed - No external metadata fetching or scrobbling
- You can still enrich metadata manually or with tools like Komf
For a personal homelab where you know your collection well, Kavita+ is optional. For a large library where you want automatic metadata and AniList integration, it’s the unlock.
REST API
Every Kavita operation is available via REST API. The OpenAPI spec is at https://www.kavitareader.com/docs/api/ and Swagger UI is available in development builds.
Authentication:
|
|
Generate API keys in your user profile under Settings → Security → API Keys.
Common operations:
|
|
The API makes Kavita a reasonable target for automation — triggering scans after a download completes, pulling reading stats, or building custom dashboards.
Comparison with Alternatives
| Kavita | Komga | Calibre-Web | Ubooquity | |
|---|---|---|---|---|
| Active development | Yes | Yes | Yes | No (abandoned) |
| Comic/manga | Excellent | Excellent | Limited | Good |
| EPUB/books | Good | Basic | Excellent | Basic |
| Database | SQLite | H2 | SQLite | H2 |
| Tech stack | .NET + Angular | Kotlin + Spring | Python + Flask | Java |
| OPDS | Yes (+ OPDS-PS) | Yes (+ OPDS-PS) | Yes | Yes |
| Tachiyomi integration | Via extension | Native | No | No |
| Webtoon mode | Yes | Yes | No | No |
| Progress sync | Yes (cross-device) | Yes | Limited | No |
| Multi-user | Yes | Yes | Yes | Yes |
| Metadata matching | Kavita+ (AniList) | Komf (external) | Via Calibre | No |
| Kindle send-to | No | No | Yes | No |
| Setup complexity | Low | Low | Medium | Low |
Choose Kavita when you have a mixed library (manga + comics + ebooks) or a manga-heavy collection and want the most polished reading experience.
Choose Komga when you want a lighter footprint, your collection is primarily Western comics, or you want tighter native Tachiyomi integration without extensions.
Choose Calibre-Web when your collection is primarily ebooks and you already use Calibre for library management and metadata, or you need send-to-Kindle functionality.
Gotchas and Known Issues
SSE4.2 requirement. Covers fail on Pentium/Celeron CPUs. Any Core i-series or modern AMD CPU is fine — but if you’re running Kavita on old low-end hardware, check your CPU first.
Folder watching doesn’t work in Docker on Windows (WSL2). Use manual scanning or a scheduled scan interval instead.
Parentheses in filenames get stripped. Use {curly braces} for year markers and variants instead of (parentheses).
Numbers in series names confuse the parser. Gundam 00 or Area 51 can have the number misidentified as a chapter number. Add a ComicInfo.xml to anchor the series name.
First scan is slow; subsequent scans are fast. Kavita uses file modification times to skip unchanged files on incremental scans. After the initial index, scanning a library only processes changed files.
OPDS can be slow on large libraries. The OPDS service has a known N+1 query issue that makes it slower as the library grows. Fine for typical homelab collections; noticeable at very large scale.
Cover images appear after a delay. Cover generation runs on a background thread. A freshly-scanned series shows a placeholder initially, then the cover appears. This is normal.
Backup Strategy
Kavita’s entire state is in two places:
/kavita/config— the SQLite database, settings, logs, and generated covers- Your media files — the CBZ/EPUB/etc. files themselves
Back up /kavita/config on a schedule. If you lose it, Kavita rescans and rebuilds the index from your media files, but you lose read progress, collections, reading lists, user accounts, and settings. The media files themselves are the source of truth for content; the config directory is the source of truth for your reading history.
A simple approach: rsync the config directory to a backup location daily, and rely on your existing media backup strategy for the actual files.
The Bottom Line
Kavita is the most complete self-hosted reading server available right now. The web reader handles every format well, the automatic series organization works reliably when you follow the naming conventions, and OPDS+OPDS-PS covers the mobile app ecosystem adequately until native apps arrive.
The main rough edges are around the scanner — naming conventions require attention, the parentheses behavior surprises new users, and very large libraries can stress the current implementation. But for a typical homelab collection of hundreds to a few thousand series, it’s smooth and capable.
If your media is already organized reasonably, getting Kavita running and pointed at your library takes under 30 minutes. The reading experience after that is excellent.
Comments