What Kavita asks of the hardware
Very little. The wiki says every build is self-contained, with no runtime to install, and names one hard requirement: a processor with the SSE4.2 instruction set, because NetVips, the image library behind cover generation, depends on it. Without it, the FAQ says, Kavita either crashes or draws black-and-white covers.
| Resource | What the project states | What it means here |
|---|---|---|
| Processor | SSE4.2 required; users report running it on a single 1 GHz core | Check Instruction Set Extensions on Intel's specification page; the Intel processor list links one per CPU |
| Memory | Users report 256 MB; Server Settings has a Cache Size field for hot API responses, default 75 | The smallest line on the service page has 8 GB, so memory is not the constraint |
| Disk I/O | First scans are slow, worse on network or rclone storage; cover refresh and file analysis are heavy on I/O and memory | Keep the library on local disks in the machine |
| Capacity | Not stated: it depends on your library | The library, plus config: database, covers, bookmarks and up to 30 days of backup zips |
Formats, per the README: cbr, cbz, zip, rar and rar5, 7zip and loose images for comics and manga; epub and pdf for books.
Choosing the line
Kavita is a light service, so the numbers that decide the machine are disk capacity and the city nearest your readers. On the dedicated server range that leaves three shapes:
- A Moonshot cartridge for a personal or household library: one service per machine is what the cartridges are sold for. The Xeon D-1587 cartridge pairs 16 cores with one NVMe disk of 1.92 TB.
- A single-socket rack server once the collection outgrows one disk, with its own chassis and out-of-band console.
- A build to order when you need drive bays: you pick drives, count and RAID level, up to 24 bays on the largest lines, delivered in 4 to 24 hours.
Handover of a ready server takes about 30 minutes once payment is approved. Every racked single-, dual- and quad-socket server has an out-of-band console (HPE iLO, Dell iDRAC or a Supermicro BMC); among the cartridges only the m510 and m710x have one, the rest have power control. Ports are unmetered, so readers paging through large scans from outside your network count against no transfer allowance.
Leave the X-Gene ARM cartridge out. It boots Ubuntu 16.04 and 18.04 and nothing else, which is our reason to keep Kavita on an x86 line, where current Ubuntu releases install from the control panel.
Native install under systemd
This follows the wiki's Linux steps and its example unit, with changes of ours: ufw is enabled before the first start, the service account is a system user with no login shell, and the library sits under /srv, readable by that account. Kavita's default bind is 0.0.0.0 and :: (every IPv4 and IPv6 address, per Configuration.cs in the source), so ufw must cover IPv6 before anything listens. Run as root; you is your own login:
sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
ufw allow OpenSSH
ufw --force enable
useradd --system --user-group --home-dir /opt/Kavita --shell /usr/sbin/nologin kavita
cd /tmp && wget https://github.com/Kareadita/Kavita/releases/latest/download/kavita-linux-x64.tar.gz
tar -xzf kavita-linux-x64.tar.gz -C /opt && chmod +x /opt/Kavita/Kavita
chown -R kavita:kavita /opt/Kavita && chmod 700 /opt/Kavita/config
install -d -o you -g kavita -m 2750 /srv/library /srv/library/manga /srv/library/comics /srv/library/books
printf '%s\n' '[Unit]' 'Description=Kavita Server' 'After=network.target' '[Service]' 'User=kavita' 'Group=kavita' 'Type=simple' 'WorkingDirectory=/opt/Kavita' 'ExecStart=/opt/Kavita/Kavita' 'TimeoutStopSec=20' 'KillMode=process' 'Restart=on-failure' '[Install]' 'WantedBy=multi-user.target' > /etc/systemd/system/kavita.service
systemctl daemon-reload && systemctl enable --now kavita
The archive unpacks to /opt/Kavita. On first start Kavita renames config/appsettings-init.json to appsettings.json and replaces the placeholder session-signing key in it with a random one (Program.cs in the source). That file and the kavita.db database next to it are the instance, hence mode 700 on config.
The first registration is the admin
Kavita ships with no default login. The first account registered gets the Admin role, and the register endpoint refuses further sign-ups once an admin exists (RegisterFirstUser in AccountController.cs). Make that registration yours while ufw still blocks port 5000: from your workstation run ssh -L 5000:127.0.0.1:5000 you@your-server and load http://localhost:5000 in a browser to register with a long password.
Still in the tunnel, open Server Settings > General and set IP Address to 127.0.0.1, so Kavita listens on loopback only; the source keeps that value in appsettings.json. Run systemctl restart kavita and reconnect. On the same page, Allow Anonymous Usage Collection is on by default and, per the wiki, first sends after 24 hours; switch it off if you want no install statistics leaving the box.
The wiki advises against reading from the admin account day to day: admins bypass age restrictions and see full disk paths. Create an ordinary account for yourself under Users.
Library layout the scanner accepts
Kavita works out series, volume and chapter from filenames and embedded metadata, not by mirroring your folders, and the wiki sets two hard rules: no files at a library's root, and every series in a folder of its own, never split across two sibling folders. A publisher level above the series folders is fine.
- Manga:
/srv/library/manga/Series Name/Series Name v01.cbz, then v02 and on, with aSpecialssubfolder whose files carry SP01, SP02 markers. - Volume and chapter markers go in the filename: v01, vol. 1 or tome 2; c01, ch. 1 or chapter 1.
- EPUBs are grouped by the metadata inside the file first; the wiki points to Calibre for fixing series and volume fields.
- Set the library type to match the content: Manga, Comic, Comic (Flexible), Book, Light Novels or Image. Pick the library root in the folder picker, not a series folder.
Upload only books and comics you own or hold the rights to, over your own login: rsync -rlt ~/manga/ you@your-server:/srv/library/manga/. The setgid bit on those folders puts new files in the kavita group, so the service can read them.
OPDS and Kavita+
OPDS is enabled on every install by default. Each user gets a personal feed URL carrying an auth key; set Host Name under Server Settings > General so that URL uses your domain. Kavita serves plain OPDS and OPDS-PS, the page-streaming extension, and the wiki's client tables list KOReader, Panels and Chunky among the apps that handle page streams. The key in the URL signs in as that user, so treat the URL like a password.
Kavita+ is an optional subscription run by Kavita's main developer, majora2007, for features that depend on outside services: metadata from Mangabaka, Hardcover and ComicBookRoundup; scrobbling, meaning progress sync, to Hardcover, MAL, AniList and MangaBaka; and external recommendations, reviews and ratings. A licence is node-locked to one instance and covers every user on it. The wiki says changing hardware or OS, or reinstalling, can trip its already-tied-to-another-server check, which recent versions resolve by offering to overwrite. It supports the latest three stable releases, and the wiki states no base feature will ever be moved behind it.
TLS through nginx
The wiki recommends a VPN for one or two readers and a reverse proxy for many. For the first, a WireGuard server on the same machine keeps Kavita off the public internet entirely. For the second, Kavita trusts forwarding headers only from localhost, so nginx on the same host needs no extra setting. nginx is an ordinary host process, so without a ufw rule it is blocked on IPv4 and IPv6 alike. In order:
- Point the A and AAAA records for your name, kavita.example.com here, at the server.
- Open the web ports:
ufw allow 80,443/tcp. - With nginx, Certbot and Certbot's nginx plugin installed, get the certificate before writing the site:
certbot certonly --nginx -d kavita.example.com. - Save the block below as /etc/nginx/sites-available/kavita and link it in with
ln -s /etc/nginx/sites-available/kavita /etc/nginx/sites-enabled/kavita. - Check the syntax and load it:
nginx -t && systemctl reload nginx.
The block is the wiki's NGINX example aimed at loopback, with an IPv6 listener and the certificate paths Certbot writes:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name kavita.example.com;
ssl_certificate /etc/letsencrypt/live/kavita.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kavita.example.com/privkey.pem;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://127.0.0.1:5000;
}
}
The Docker route instead
- Image:
jvmilazz0/kavita:latest, the same build asghcr.io/kareadita/kavita:latest. The old kizaing/kavita repository is unsupported, and the wiki advises against nightly tags for a main instance. - Mounts: config at
/kavita/config(the wiki says that path must not change) and each library folder at its own path such as/manga. - Publish
127.0.0.1:5000:5000, not the wiki's5000:5000. A mapping with no address is published on 0.0.0.0 and [::]; that traffic skips ufw's rules on IPv4, and on IPv6 too when Docker's own IPv6 networking is on. With Docker Engine 28 or later the loopback binding is reachable from the host alone. - The IP Address setting is disabled under Docker, per the wiki, so the mapping is your bind.
- Our reading of the forwarded-header rule: a host proxy connects to the container from the Docker bridge's gateway IP, not from localhost, so put that address in
KnownProxiesin appsettings.json, as the wiki shows for proxies on another host. - Keep secrets out of the container environment:
docker inspectprints every value in it.
Backups, restores and updates
Kavita backs itself up. The source seeds the backup task as daily (Seed.cs), the wiki's Daily is midnight in the server's time zone, and Days of Backups defaults to 30. Each zip in config/backups holds kavita.db, appsettings.json with its signing key, logs, every collection, library and reading-list cover plus the series, volume and chapter covers you have locked (the unlocked ones are not copied), bookmarks, themes, fonts and favicons (BackupService.cs), but none of your library files. The zips sit on the same disks as everything else, so copy them off the machine yourself. This root block stages a private copy for you to pull, keeping 30 days of it:
install -d -m 700 -o you -g you /srv/kavita-out
printf '%s\n' '15 2 * * * root umask 077; cp -u /opt/Kavita/config/backups/kavita_backup_*.zip /srv/kavita-out/ && chown you:you /srv/kavita-out/*.zip; find /srv/kavita-out -name "kavita_backup_*.zip" -mtime +30 -delete' > /etc/cron.d/kavita-out
chmod 644 /etc/cron.d/kavita-out
Pull it from another machine with rsync -rt you@your-server:/srv/kavita-out/ ~/kavita-backups/, and copy the library itself the same way.
Restoring, per the wiki, means stopping Kavita, copying everything in a backup zip into config/ and starting it. Check first: unzip -l on the zip you mean to use shows it exists and its index reads, though not that every entry is intact (install unzip with apt if it is missing). Then systemctl stop kavita, unzip -o the zip into /opt/Kavita/config, chown -R kavita:kavita /opt/Kavita/config and systemctl start kavita. Nothing is emptied beforehand; the zip's files overwrite their namesakes.
Updating a native install, per the wiki: extract the new tarball in a temporary folder, delete the config folder inside that temporary copy, stop the service, copy the files over /opt/Kavita and start it again. Two steps are our additions, not the wiki's: run Backup Database from the Tasks tab before you begin, and run chown -R kavita:kavita /opt/Kavita before the restart, because files copied as root arrive owned by root. Coming from anything older than v0.7.6, the wiki says to step through v0.7.1.4, v0.7.3.1, v0.7.6 and v0.7.14 rather than jump.
Questions
Which port does Kavita listen on, and can I move it?
Port 5000 by default. On a native install you change it in Server Settings > General, and the wiki says the change needs a manual restart. Under Docker you change the host side of the port mapping instead.
Native build or Docker image on a dedicated server?
Both come from the same releases. Our view: on a machine of your own the native build is the shorter path, because Kavita can bind itself to 127.0.0.1 and nginx on the host counts as localhost. Docker suits you if the box already runs other containers; then the bind lives in the port mapping and the proxy address goes in KnownProxies.
Can Kavita be used without logging in?
No. The wiki's FAQ says anonymous access is not supported and is not planned. Refresh tokens keep a session alive, and an API key can sign a user in through a URL, which is another reason to keep those keys private.
Does the built-in backup cover everything?
It covers the database, settings, locked and list-level covers, bookmarks and logs, not the books and comics themselves. It also lands on the same disks as the instance, and each zip carries the session-signing key, so copy the zips off the machine and keep them private.
What is Kavita's licence?
GPL-3.0, per the LICENSE file in the Kareadita/Kavita repository. Our general reading, not legal advice: you may run, study and modify it, and serving it to your own readers over the web is use rather than distribution. If you distribute the program or a modified build, you pass the source on under the same licence.
Is Kavita stable enough to rely on?
The README calls it beta software until the 1.0.0 release and warns that data loss is possible as the platform changes. Treat the off-machine backups as part of the install, and read the release notes before each update.