Gopherbook is a lightweight, single-binary, self-hosted web comic reader and library manager written in Go.
It is designed for people who want full control over their digital comic collection (CBZ/CBT files), including support for password-protected/encrypted archives, per-user libraries, tagging, automatic organization, and a clean modern reader.
- Upload & read
.cbz(ZIP-based) or.cbt(TAR-based) comics directly in the browser - Watch folder support for bulk imports – drop CBZ/CBT files into your watch folder and they're automatically imported
- Supports 8 Megapixel images at 512MB memory limits
- (increase in bash script for higher Megapixels or remove the limitation if you don't care)
- Full support for password-protected/encrypted CBZ files (AES-256 via yeka/zip) or CBT files (AES-256-CFB Openssl)
- Automatically tries all previously successful passwords when opening a new encrypted comic
- Persists discovered passwords securely (AES-encrypted on disk, key derived from your login password)
- Extracts ComicInfo.xml metadata (title, series, number, writer, inker, tags, story arc, etc.)
- Automatic folder organization:
Library/Artist/StoryArc/Comic.cbz - Manual reorganization via UI if needed
- Powerful tagging system with custom colors and counts
- Filter comics by any combination of tags
- Responsive grid view with cached JPEG covers
- Full-screen web reader with:
- Page pre-loading
- Zoom / pan
- Fit-to-width/height/page
- Keyboard navigation (←→, A/D, +/-, Esc)
- Multi-user support:
- Each user has their own completely isolated library and password vault
- First registered user becomes admin
- Admin can disable new registrations
- Admin can delete any comic
- No external database – everything stored in simple JSON files
- Single static Go binary + file storage – easy to deploy
- Go 1.25.2+ (only needed to build)
- Or just download a pre-built binary from Releases (when available)
git clone https://codeberg.org/riomoo/gopherbook.git
cd gopherbook
go build -o gopherbook app/gopherbook/main.go
./gopherbookThen open http://localhost:8080 in your browser.
git clone https://codeberg.org/riomoo/gopherbook.git
cd gopherbook
./scripts-bash/run-gb-container/run-podman.shor
git clone https://codeberg.org/riomoo/gopherbook.git
cd gopherbook
./scripts-bash/run-gb-container/run-docker.shThen open http://localhost:12010 in your browser.
- On first run there are no users → registration is open
- Create the first account → this user automatically becomes admin
- Log in → start uploading CBZ/CBT files
./library/username/ ← your comics (organized or Unorganized/)
./library/username/comics.json ← metadata index
./library/username/tags.json ← tag definitions & counts
./library/username/passwords.json ← encrypted password vault (AES)
./cache/covers/username/ ← generated cover thumbnails
./watch/username/ ← watch folder for bulk imports (auto-scanned)
./etc/users.json ← user accounts (bcrypt hashes)
./etc/admin.json ← admin settings (registration toggle)
Can be used to set where everything is stored with:
GOPHERBOOK_LIBRARY=$HOME/.config/gopherbook/library
GOPHERBOOK_CACHE=$HOME/.config/gopherbook/covers
GOPHERBOOK_ETC=$HOME/.config/gopherbook/etc
GOPHERBOOK_WATCH=$HOME/.config/gopherbook/watch
Gopherbook includes an automatic watch folder system that makes bulk importing comics effortless:
- Per-user watch folders: Each user gets their own watch folder at
./watch/[username]/ - Automatic scanning: The system checks for new CBZ/CBT files every 10 seconds
- Smart debouncing: Waits 5 seconds after detecting files to ensure they're fully copied
- File validation: Checks that files aren't still being written before importing
- Duplicate handling: Automatically renames files if they already exist (adds _1, _2, etc.)
- Zero configuration: Just drop CBZ/CBT files into your watch folder and they appear in your library
- After logging in, your personal watch folder is at
./watch/[yourusername]/ - Copy or move CBZ/CBT files into this folder using any method:
- Direct file copy/paste
- SCP/SFTP upload
- Network share mount
- Automated scripts
- Within ~15 seconds, files are automatically imported to your library
- Files are moved (not copied) to preserve disk space
- Check the API endpoint
/api/watch-folderto see pending files
Example workflow:
# Bulk copy comics to your watch folder
cp ~/Downloads/*.cbz ./watch/myusername/
cp ~/Downloads/*.cbt ./watch/myusername/
# Wait ~15 seconds, then check your library in the web UI
# All comics will be imported and organized automatically- When you upload or scan an encrypted CBZ/CBT that has no known password yet, the server marks it as Encrypted = true.
- The first time you open it in the reader, a password prompt appears.
- If the password is correct, Gopherbook:
- Stores the password (encrypted with a key derived from your login password)
- Extracts ComicInfo.xml metadata
- Auto-organizes the file into Artist/StoryArc folders
- Updates tags and cover cache
- From then on the comic opens instantly, and that password is automatically tried on every future encrypted comic you upload (so whole collections that share one password "just work").
- Passwords are stored encrypted on disk using AES-256-CFB with a key derived from your login password via SHA-256.
- Session cookie is HttpOnly, expires after 24 h.
- No external dependencies that phone home.
- Still: treat this as a personal/private server – do not expose it publicly without HTTPS/reverse-proxy auth.
upstream gopherbook {
server 127.0.0.1:8080;
#server 127.0.0.1:12010; #For Podman instead
server [::1]:8080;
#server [::1]:12010; #For Podman instead
}
server {
listen 80;
listen [::1]:80;
server_name gopherbook.example.com;
location / {
proxy_pass http://gopherbook;
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;
# 1. Allow very large uploads (e.g. 500 MB – adjust as needed)
client_max_body_size 500M; # 0 = unlimited, but never do that on a public server
# 2. Give the upload enough time (important for slow connections)
client_body_timeout 5m; # time to read the entire request body (default 60s)
proxy_read_timeout 5m; # if you're proxying to your Go app
proxy_send_timeout 5m;
# 3. Increase buffer sizes so Nginx doesn't spill everything to disk
client_body_buffer_size 512k; # default 8k/16k – too small for big uploads
proxy_buffers 8 512k;
proxy_buffer_size 256k;
# 4. Recommended: put uploads in a temporary directory with plenty of space
client_body_temp_path /var/lib/nginx/body 1 2; # make sure this directory exists and is writable by nginx
}
}
Pull requests are welcome! Especially:
- Better mobile reader experience
- Bulk tag editing
- Search box
- OPDS catalog endpoint
- More metadata sources (ComicVine, etc.)
Please open an issue first for bigger changes.
- Check the Wiki!
- GitHub: https://github.com/riomoo/gopherbook/wiki/Meet-Vinny
- GitGud: https://gitgud.io/riomoo/gopherbook/-/wikis/Meet-Vinny
- JesterDesigns: https://git.jester-designs.com/riomoo/gopherbook/wiki/Meet-Vinny
- yeka/zip – password-protected ZIP support in pure Go
- The ComicRack ComicInfo.xml standard
- Everyone who hoards comics ❤️
Enjoy your library!
– Happy reading with Gopherbook
