Use case · Ebook library

Calibre-Web self-hosted on a dedicated server

To run Calibre-Web self-hosted, install the calibreweb package with pip into a virtual environment, run it under systemd as an unprivileged user bound to 127.0.0.1 on port 8083, change the admin / admin123 login through an SSH tunnel, point it at the folder holding your Calibre metadata.db, and publish it through nginx with TLS. Everything below comes from the project's README and wiki.

See the machines

What Calibre-Web is and what it needs

Calibre-Web is a Python web application that reads an existing Calibre database and gives it a browser interface: browsing, an in-browser reader, downloads, shelves, per-user permissions, an OPDS feed and Kobo sync. It does not replace Calibre's database; it reads and writes the same metadata.db file and the book folders beside it.

PieceWhat the docs sayWhere it lives here
Python3.7 or newer (README)A venv in the service user's home
ImageMagickNeeded to pull covers out of EPUB files (README)Ubuntu package
Calibre binariesOptional; used for ebook-convert conversion and metadata embedding (wiki, Configuration)Installed separately if you want conversion
kepubifyNeeded for Kobo devices; README places the binary at /opt/kepubifyOptional
Settingsapp.db, plus gdrive.db, settings.yaml and gdrive_credentials when Google Drive storage is used (wiki FAQ)~/.calibre-web for a pip install (wiki)
LibraryA folder with metadata.db at its top and one folder per author/srv/books

The README gives no RAM or core figures, only the advice to add CPU and memory if the instance is slow. Our own rule of thumb: the library's size decides the disk, and whether you convert books on the server decides how much CPU matters. A personal library with no conversion is a small job.

Which machine to put it on

Calibre-Web is one service with one database, which is the case the dedicated server range describes for Moonshot cartridges: one job per machine. A cartridge with an SSD carries a personal or family library. Pick a rack server when the collection needs several drives or RAID, or when you want the out-of-band console: every racked single-, dual- and quad-socket server has one (HPE iLO, Dell iDRAC or a Supermicro BMC), and among cartridges only the m510 and m710x do; the rest have power control only.

  • Not the X-Gene ARM cartridge for this library: it boots only Ubuntu 16.04 and 18.04, older than the Ubuntu 24.04 these steps assume. (If you take the Docker route instead, the README says its Calibre conversion add-on is x64 only.)
  • The port is unmetered on every line, so readers downloading EPUBs and comic archives add nothing to the bill.
  • Root on the whole machine means the venv, the systemd unit, nginx and the firewall are all yours to set.
  • A ready server: handed over in about 30 minutes once payment is approved; a build to order takes 4 to 24 hours.

Install with pip under a service user

The README recommends pip inside a virtual environment, and the wiki's systemd page runs the cps starter as a named user. The block below does both on Ubuntu 24.04, and turns the firewall on (SSH only, IPv6 included) before anything else listens. The -i 127.0.0.1 flag is the documented way to limit the listening address, so port 8083 never faces the internet.

sudo sed -i 's/^IPV6=.*/IPV6=yes/' /etc/default/ufw
sudo ufw allow OpenSSH
sudo ufw --force enable
sudo apt update && sudo apt install -y python3-venv imagemagick
sudo useradd --system --create-home --home-dir /var/lib/calibre-web --shell /usr/sbin/nologin calibreweb
sudo install -d -o calibreweb -g calibreweb -m 750 /srv/books
sudo -u calibreweb bash -c 'cd /var/lib/calibre-web && python3 -m venv venv && venv/bin/pip install calibreweb'
sudo tee /etc/systemd/system/calibre-web.service > /dev/null <<'EOF'
[Unit]
Description=Calibre-Web
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=calibreweb
Group=calibreweb
ExecStart=/var/lib/calibre-web/venv/bin/cps -i 127.0.0.1
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now calibre-web

Optional features are pip extras, listed on the wiki's dependencies page: kobo for Kobo sync, metadata for reading metadata from EPUB, FB2 and PDF, gdrive for Google Drive storage, ldap and oauth for logins. Install one with sudo -u calibreweb bash -c "cd /var/lib/calibre-web && venv/bin/pip install 'calibreweb[kobo]'", then restart the unit.

First login and the library path

The README's default account is admin with password admin123. Reach it only through your own login: ssh -N -L 8083:127.0.0.1:8083 you@203.0.113.10 forwards the port, and with the tunnel up, http://localhost:8083 on your workstation shows the login. Sign in and set a new password on the admin account before the proxy section below.

  1. Copy your existing Calibre library folder to the server (rsync or scp to your home directory), move it into /srv/books and run sudo chown -R calibreweb:calibreweb /srv/books. No library yet: the README links a sample metadata.db in the repository's library folder.
  2. In the admin page's database configuration, set Location of Calibre database to /srv/books. The wiki says to enter the folder only; the file name metadata.db is not allowed in the path.
  3. Leave anonymous browsing and public registration off unless you mean them; both are opt-in settings under Basic Configuration, in its Feature Configuration section.
  4. Lost the admin password later? The wiki FAQ's recovery is stopping the service and starting cps -s admin:newpassword once as the service user. A password on a command line shows up in ps and in shell history, so change it again in the interface afterwards.

The wiki FAQ warns that Calibre desktop opened on a metadata.db first can lock Calibre-Web out, and that both editing metadata at once gives unpredictable results. Our practice: stop the calibre-web unit before syncing a changed library over from a desktop copy.

Uploads and conversion

Uploading is off until you tick Enable Uploading in Basic Configuration; the README notes the upload option does not appear before that. The wiki lists the accepted formats (EPUB, PDF, MOBI, AZW3, CBZ, CBR, MP3, M4B and more) and lets you trim them. Per the FAQ, the built-in Tornado server caps an upload at 200 MB, and any proxy in front must allow the same size or it answers 413.

Conversion between formats uses Calibre's own ebook-convert. Install Calibre on the server by its own instructions, then set Path to Calibre Binaries in the External binaries settings; the wiki says that is usually /opt/calibre on Linux. The same FAQ warns that the in-browser EPUB reader loads a book's HTML and JavaScript into the reader's browser, so take uploads only from people you trust.

nginx in front, with TLS

The wiki's configuration page is blunt about remote hosting: do not listen on 0.0.0.0, and use TLS, preferably nginx with a Let's Encrypt certificate. nginx runs on the host as a normal process, so ufw needs ports 80 and 443 opened for it, on IPv4 and IPv6. The proxy headers follow the wiki's nginx example; the buffer lines come from its proxy notes for Kobo sync, and the 200M body size is ours, matching the upload cap.

sudo apt install -y nginx certbot python3-certbot-nginx
sudo ufw allow 80,443/tcp
sudo tee /etc/nginx/sites-available/calibre-web > /dev/null <<'EOF'
server {
    listen 80;
    listen [::]:80;
    server_name books.example.com;
    client_max_body_size 200M;

    location / {
        proxy_pass http://127.0.0.1:8083;
        proxy_set_header Host            $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Scheme        $scheme;
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/calibre-web /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d books.example.com

The wiki's order is the certificate first, then the proxy location; ours puts the location block in before certbot runs, to keep it to one block. Either way, nobody should sign in through the domain until certbot has finished. If you put a login server such as Authentik in front, the wiki's Allow Reverse Proxy Authentication setting logs in whichever user a request header names. That is safe only while port 8083 stays on loopback and the proxy sets that header itself on every request, overwriting any value a client sends. For a full proxy stack on its own box, see Nginx Proxy Manager.

OPDS and Kobo sync

The OPDS catalogue is at /opds on the same address. The wiki FAQ lists readers the maintainer tested, KOReader, Librera and FBReader among them, and notes that some only download or show covers with anonymous browsing on. It also documents putting credentials in the catalogue URL for readers with no login field; that puts your password in the proxy's access log, so we would rather pick a reader that asks for it.

Kobo sync needs two things first: the kobo pip extra from the dependencies page, and the kepubify binary, which the README says to place in /opt/kepubify (its path goes in Path to Kepubify E-Book Converter). Then, per the Kobo wiki page: tick Enable Kobo sync, give the user Downloads permission, generate a sync URL on the user's profile page and write it as api_endpoint in the device's Kobo eReader.conf. The page marks the feature as fairly new with limited testing, says large libraries may time out, and that PDFs do not sync. It also warns that the device sends a fixed device and user id pair, so sync only over HTTPS.

Backups, updates and the licence

Back up the library folder, app.db, and the Google Drive files when you use that integration. The script below takes consistent SQLite copies, archives the books, and keeps 14 days (our choice; change -mtime). The cron line is written as its own file.

sudo apt install -y sqlite3
sudo tee /usr/local/sbin/calibre-web-backup.sh > /dev/null <<'EOF'
set -eu
umask 077
mkdir -p -m 700 /var/backups/calibre-web
D="/var/backups/calibre-web/$(date +%F)"
mkdir -p "$D"
CFG=/var/lib/calibre-web/.calibre-web
sqlite3 /srv/books/metadata.db ".backup '$D/metadata.db'"
sqlite3 "$CFG/app.db" ".backup '$D/app.db'"
for f in gdrive.db settings.yaml gdrive_credentials; do
  if [ -e "$CFG/$f" ]; then cp -p "$CFG/$f" "$D/"; fi
done
tar -C /srv --exclude=books/metadata.db -czf "$D/books.tar.gz" books
find /var/backups/calibre-web -mindepth 1 -maxdepth 1 -type d -mtime +14 -exec rm -rf {} +
EOF
printf '%s\n' '15 3 * * * root umask 077; bash /usr/local/sbin/calibre-web-backup.sh >> /var/log/calibre-web-backup.log 2>&1' | sudo tee /etc/cron.d/calibre-web-backup

Every copy here shares the server's own disks, so pull them to another machine yourself. To restore: stop the unit, confirm the dated folder holds books.tar.gz, metadata.db and app.db and that sqlite3 app.db 'PRAGMA integrity_check' (and the same for metadata.db) prints ok, and only then move /srv/books aside, unpack the archive into /srv, copy both databases back to their places and chown them to calibreweb.

Updates: the README lists self-update from the admin page, with a stable channel by default and a nightly one (wiki). On a pip install our preference is to upgrade with pip so the venv stays consistent: stop the unit, back up, run venv/bin/pip install --upgrade calibreweb as the service user, start it again.

Calibre-Web is licensed under the GNU GPL v3 (LICENSE file in the repository). Read generally (this is not legal advice): running it for yourself or a group of readers involves no distribution; if you hand out copies, modified or not, the licence requires you to pass on the source under the same terms.

Docker, and when this is the wrong setup

The README lists no image from the project itself. The one it points to is LinuxServer.io's, a community build for x64 and aarch64, whose optional DOCKER_MODS variable adds Calibre's ebook-convert on x64. If you use it, publish the port as 127.0.0.1:8083:8083. A mapping without an address binds every interface of the host, 0.0.0.0 and [::] alike; on IPv4 that traffic skips ufw's rules, and on IPv6 it does too when Docker's own IPv6 networking is on (otherwise the [::] listener is docker-proxy, which ufw filters). The 127.0.0.1 form stays local-only on Docker Engine 28 and later.

Skip all of this if one person reads from one laptop: Calibre desktop alone is simpler. For audiobooks with listening progress, Audiobookshelf fits better.

Questions

What is the Calibre-Web login out of the box?

The README gives admin as the user and admin123 as the password. Change it before the instance is reachable from outside, which is why this setup binds to 127.0.0.1 and does the first login over an SSH tunnel.

Which port does Calibre-Web listen on?

8083 by default; the README's quick start opens http://localhost:8083 and the OPDS feed at /opds. The port can be changed under Basic Configuration, and the CALIBRE_PORT variable only sets it when the settings database is first created. Behind nginx the port never needs to be public.

Is there an official Calibre-Web Docker image?

Not from the project. The only image the README lists is LinuxServer.io's, which that community maintains. The pip package is the install the README recommends, and it is what this page uses.

Do I need Calibre installed on the server?

Not to browse, read or download. You need Calibre's binaries for format conversion and for embedding metadata into downloads, and you set their path in the admin settings.

Where are the settings stored, and what do I back up?

A pip install keeps app.db in ~/.calibre-web of the user running it, per the wiki. Back that up with the library folder, and add gdrive.db, settings.yaml and gdrive_credentials if your library lives on Google Drive.

Can several people use one instance?

Yes. Calibre-Web has per-user accounts and permissions, and per-user visibility rules based on tags or custom columns. The wiki warns against linking read status to a Calibre column when there is more than one user.

Put your library on its own machine

Pick a line from the dedicated range, install Calibre-Web with the steps above, and keep the port on loopback behind nginx.

See the machines

Related on Server Room

Other use cases