Skip to content
metalogicoPublic

About

A fast, self-hosted comic library server. Scan your comics, read in browser, or use any OPDS client.

Topics

Resources

Stars

105 stars

Watchers

3 watching

Forks

Repository files navigation

Issued

Your personal comic library server

Host your digital comics (CBZ/CBR/CB7/PDF files) on your home server and read them on any device. Issued automatically organizes your collection and makes it available through mobile apps like Panels, Chunky, or a built-in web reader.

What You Get

  • πŸ“š Keep your folder structure – No need to reorganize your comics
  • πŸ”„ Automatic updates – New comics are detected and added automatically
  • πŸ–ΌοΈ Thumbnail previews – See cover images before opening
  • πŸ“± Read anywhere – Use your favorite comic reader app (Panels, Chunky, etc.)
  • 🌐 Web reader – Read in your browser without installing anything (on mobile too!)
  • πŸŒ™ Light and dark themes – Follow your system preference or switch manually
  • πŸ”– Ongoing series – Mark active series and quickly see new issues, totals, and possible gaps
  • ▢️ Continue a series – Resume the latest issue in progress or start the next unread issue
  • ⚑ Easy setup – One command to get started

Supported Formats

Issued works with all common digital comic formats:

  • CBZ (Comic Book ZIP) - ZIP archives containing images
  • CBR (Comic Book RAR) - RAR archives containing images (requires unrar)
  • CB7 (Comic Book 7-Zip) - 7-Zip archives containing images
  • PDF - PDF documents with comic pages

Issued detects the real container from the file contents. Misnamed archives, such as a .cbz file that is actually compressed with 7-Zip, are handled automatically.

All formats support:

  • βœ… Automatic page extraction and rendering
  • βœ… Thumbnail generation from first page
  • βœ… Metadata extraction (ComicInfo.xml or PDF metadata)
  • βœ… Full compatibility with OPDS readers and web reader
  • βœ… Reading progress tracking

OPDS Features

  • Browse your library – Navigate folders and series, with cover previews and a recent additions feed.
  • Search – Find comics by filename or metadata, with OpenSearch discovery for compatible apps.
  • Download originals – Download complete comic archives or PDFs.
  • Page streaming (OPDS-PSE 1.2) – Read individual pages in compatible apps without downloading the whole comic. Existing OPDS download links remain available.

PSE pages are served as JPEG. Existing JPEGs are passed through unchanged; other page images are converted on the fly at high quality, without resizing or modifying the original files. Streaming pages does not update reading progress.

Collection view

image

Web and Mobile reader

image

Edit metadata (uses ComicInfo.xml if available)

image

Continue reading and Last Added

image

Before You Start

Docker users: skip this section β€” the Docker image includes everything you need.

For CBR files only (skip if you only have CBZ or PDF):

Install unrar on your computer:

  • macOS: brew install rar
  • Linux: sudo apt install rar
  • Windows: Download from rarlab.com

Note: CBZ, CB7, and PDF files work without any extra software. CBR files need unrar to extract.

Installation

Option 1: Docker (Recommended)

Best for: Running on a home server or NAS. Everything is pre-configured, including unrar.

Step 1: Create a docker-compose.yml file anywhere on your server:

services:
  issued:
    image: ghcr.io/metalogico/issued:latest
    restart: unless-stopped
    ports:
      - "8181:8181"
    volumes:
      - ./data:/app/data
      - /path/to/your/comics:/comics:ro   # ← Change this path

Change /path/to/your/comics to your comics folder:

- /home/user/Comics:/comics:ro     # Linux
- /Users/john/Comics:/comics:ro    # macOS
- C:/Comics:/comics:ro             # Windows

Step 2: Start the server

docker compose up -d

If the comics folder is not mounted yet (for example the NAS is still coming up), Issued waits and leaves the database untouched. The web UI and OPDS catalog start only after the library is visible.

Done! Your comics are now available at:

  • πŸ“± Mobile apps: http://YOUR-SERVER-IP:8181/opds/
  • 🌐 Web reader: http://YOUR-SERVER-IP:8181/reader/

Replace YOUR-SERVER-IP with your computer's IP address (e.g., 192.168.1.100)

Alternative: docker run

docker run -d --name issued \
  --restart unless-stopped \
  -p 8181:8181 \
  -v /path/to/your/comics:/comics:ro \
  -v issued_data:/app/data \
  ghcr.io/metalogico/issued:latest

Alternative: docker create (create now, start later)

docker create \
  --name=issued \
  --user 1000:1000 \
  -p 8181:8181 \
  --mount type=bind,source=/path/to/your/comics,target=/comics,readonly \
  --mount type=bind,source=/path/to/data,target=/app/data \
  --restart unless-stopped \
  ghcr.io/metalogico/issued:latest

Then start it:

docker start issued

The image is also available on Docker Hub as metalogico/issued.


Option 2: Standalone Executable

Best for: Quick setup on your personal computer.

Windows note: Put the executable in a writable folder, such as your Desktop or another folder inside your user profile. Avoid C:\Program Files unless you run it with permissions to write there, because Issued stores config.ini, library.db, logs, and thumbnails beside the executable by default.

Step 1: Download for your system

Get the latest release from GitHub Releases:

  • macOS: issued-macos
  • Linux: issued-linux
  • Windows: issued.exe

Step 2: Make it executable (macOS/Linux only)

chmod +x issued

# macOS only: If blocked by security
xattr -d com.apple.quarantine issued

Step 3: Initialize your library

# Replace with your actual comics folder path
./issued init --library /path/to/your/comics

Examples:

./issued init --library ~/Comics              # macOS/Linux
./issued init --library C:\Users\You\Comics   # Windows

Step 4: Scan your comics

./issued scan

This will:

  • Find all CBZ/CBR/CB7/PDF files
  • Create thumbnails
  • Build the library database

Step 5: Start the server

./issued serve

Done! Your comics are now available at:

  • πŸ“± Mobile apps: http://YOUR-COMPUTER-IP:8181/opds/
  • 🌐 Web reader: http://YOUR-COMPUTER-IP:8181/reader/

Tip: Keep the terminal window open while the server runs. New comics will be detected automatically.


Using Your Comic Library

On Mobile Apps

Popular apps that work with Issued:

  • Panels (iOS) - Best overall experience
  • Chunky Reader (iOS) - Great for iPad
  • KyBook (iOS) - Feature-rich
  • Moon+ Reader (Android) - Highly customizable
  • And many oders with opds support (please let me know what you use and I'll add it here)

How to connect:

  1. Open your comic reader app
  2. Add a new OPDS catalog
  3. Enter: http://YOUR-IP:8181/opds/
  4. Browse, search, and download comics!

Compatible OPDS clients discover library search automatically via OpenSearch.

Issued supports OPDS Page Streaming Extension (OPDS-PSE) 1.2 in folder, recent, and search feeds. This extends the existing Atom OPDS catalog; it does not add OPDS 2. Clients can read or download individual pages without downloading the original comic archive.

  • Endpoint: GET /opds/comic/{comic_uuid}/page/{page_number}.
  • Page numbering is 0-based, from 0 to N-1. The web reader API remains 1-based at /reader/api/comic/{comic_uuid}/page/{page_num}.
  • Every successful PSE response is image/jpeg. Original JPEG bytes are preserved; other supported page images (including PNG and WebP, and rendered PDF pages) are converted with Pillow at quality 95, without chroma subsampling or resizing. Transparency is composited on white; animated images use their first frame. Conversion can introduce JPEG compression loss.
  • The feed uses the scanned database page count. If it is missing or invalid, the entry retains its existing links but omits PSE until a scan records a positive count. Building feeds never opens archives to count pages. A direct page request uses the actual archive contents and does not update the count.
  • Streaming, preloading, and downloading pages never save reading progress. Existing Issued progress APIs remain responsible for that. No pse:lastRead, pse:lastReadDate, or {maxWidth} capability is advertised.

Example link for a 24-page comic (the feed declares xmlns:pse="http://vaemendis.net/opds-pse/ns"):

<link rel="http://vaemendis.net/opds-pse/stream"
      type="image/jpeg"
      href="https://issued.example.com/opds/comic/abc123/page/{pageNumber}"
      pse:count="24" />

Access: the page endpoint follows the existing OPDS access model: it is accessible without a reader session cookie, including when reader password protection is enabled. It never redirects to the reader login. Any access control provided by your reverse proxy continues to apply. Public URLs use the same forwarded host/protocol configuration described below.

Responses use Cache-Control: private, max-age=3600. Missing comics/files and out-of-range pages return 404; non-integer page parameters return 422; unreadable archives/images return 500; unavailable extraction backends return 503. Errors are JSON and do not include filesystem paths. No persistent page cache is added.

See the OPDS-PSE 1.2 specification.

Finding your IP:

  • macOS/Linux: Run ifconfig or ip addr
  • Windows: Run ipconfig
  • Look for something like 192.168.1.100

In Your Browser

Just open: http://localhost:8181/reader/

From the web reader you can browse folders, search your library, read comics, edit comic details, and keep track of what you are reading.

The reader's scripts and styles are served with Cache-Control: no-cache: the browser keeps its copy but checks it with the server on each load, so an update takes effect without a forced refresh.

  • Use Recent to see the comics you added most recently.
  • Use Continue Reading to jump back into comics you have started but not finished.
  • Mark comics as done from the grid or table view.
  • When you are inside a series folder, use Mark all as completed if you want to mark the whole series as done.
  • In a series folder, use Continue series to resume the most recently opened unfinished issue or start the first unread one. The reader also links to the previous and next issue and offers the next cover when you reach the end.

Ongoing series

If you follow series that are still coming out, Issued can keep them together for you.

  1. Open the series folder in the web reader.
  2. Click the Ongoing button.
  3. Use Ongoing in the top menu to see all the series you are tracking.

The Ongoing page shows the latest added issue, how many issues are in the series, and possible missing issue numbers. The button appears on series folders that contain comics directly.

Optional: Add password protection by editing config.ini:

[reader]
user = yourname
password = yourpassword

Common Tasks

Add new comics

Just copy them to your comics folder! If the server is running, they'll be detected automatically.

You can also start a scan from the web reader: click the refresh icon in the top menu. Issued will scan your library, show how many comics were added, updated, or deleted, and then refresh the page.

Or manually scan from the command line:

./issued scan

Rescan everything

./issued scan --force

If you really emptied the comics folder and want the database to drop those entries, use ./issued scan --prune. Without --prune, Issued will refuse to wipe the library when the folder looks unmounted or empty.

Check library stats

./issued stats

Generate missing thumbnails

./issued thumbnails

Only comics without a thumbnail β€” or whose thumbnail file is missing β€” are processed.

Regenerate all thumbnails

./issued thumbnails --regenerate

Change settings

Edit config.ini in the app data folder. For standalone executables this is the same folder as the executable unless you set DATA_DIR; for Docker it is /app/data inside the container, usually backed by your mounted volume.

  • Change port: [server] β†’ port = 8080
  • Add password: [reader] β†’ user = name, password = pass
  • Adjust thumbnails: [thumbnails] β†’ width, height, quality

Advanced Configuration

Edit config.ini for more options:

[library]
path = /path/to/comics    # Your comics folder
name = My Comics          # Library name shown in apps

[server]
host = 0.0.0.0           # Listen on all network interfaces
port = 8181              # Change if port is already in use

[thumbnails]
width = 300              # Thumbnail width in pixels
height = 450             # Thumbnail height in pixels
quality = 85             # JPEG quality (1-100)
format = jpeg            # jpeg or webp

[monitoring]
enabled = true           # Auto-detect new comics
debounce_seconds = 2     # Wait time before processing changes

[reader]
user =                   # Leave empty for no password
password =               # Leave empty for no password

Reverse proxy

Issued keeps its two public route prefixes when served through a reverse proxy:

  • Web reader: https://issued.example.com/reader/
  • OPDS catalog: https://issued.example.com/opds/

Do not strip or rewrite /reader or /opds. For example, with nginx:

server {
    listen 443 ssl;
    server_name issued.example.com;

    location / {
        proxy_pass http://issued:8181;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Reader assets and images use origin-relative URLs, so they work with either an IP address or a domain. OPDS clients require absolute URLs; forwarding Host and X-Forwarded-Proto ensures those URLs contain the public domain and protocol.

When nginx, Caddy, Traefik, or another proxy runs in a separate container, add FORWARDED_ALLOW_IPS=* to the Issued container environment, or replace * with the proxy network/IP range. This lets Uvicorn trust the forwarded protocol.

Troubleshooting

Comics not showing up

  1. Check the scan worked:

    ./issued stats

    Should show your comic count.

  2. Try a forced rescan:

    ./issued scan --force

Can't connect from mobile app

  1. Use your computer's IP address, not localhost

    • Find it: ifconfig (Mac/Linux) or ipconfig (Windows)
    • Example: http://192.168.1.100:8181/opds/
  2. Check firewall:

    • Make sure port 8181 is allowed
    • macOS: System Settings β†’ Network β†’ Firewall
    • Windows: Windows Defender Firewall β†’ Allow an app
  3. Make sure both devices are on the same network

    • Computer and phone/tablet must be on the same WiFi

CBR files won't open

Install unrar:

  • macOS: brew install unrar
  • Linux: sudo apt install unrar
  • Windows: Download from rarlab.com

Then restart the server.

macOS says "cannot be opened"

xattr -d com.apple.quarantine issued

Port 8181 already in use

Edit config.ini and change the port:

[server]
port = 8080

Then use http://YOUR-IP:8080/opds/ instead.

Server stops when I close the terminal

Docker: It runs in the background automatically.

Executable: Run in the background:

# macOS/Linux
nohup ./issued serve &

# Or use screen/tmux
screen -S issued
./issued serve
# Press Ctrl+A then D to detach

Why is it Violet / Purple?

This project uses the violet accent color just because my baby daughter is called Violet <3


Getting Help

If you're stuck:

  1. Check the Issues page
  2. Open a new issue with:
    • Your OS (macOS/Linux/Windows)
    • How you installed (Docker/executable)
    • What you tried
    • Error messages (if any)

License

MIT. See LICENSE for details.

About

A fast, self-hosted comic library server. Scan your comics, read in browser, or use any OPDS client.

Topics

Resources

Stars

105 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages