Bit Tuppi
Bit Tuppi is a minimal filesystem library indexer for PDF, EPUB, MOBI, and MP3 files. It treats directory structure as the category hierarchy, stores metadata in SQLite with FTS5 full-text search, and serves a small web UI for browsing and searching the collection. Currently limited to a directory depth of '3'.
The only dependency beyond the Go standard library is modernc.org/sqlite, a pure-Go SQLite driver. No CGO required, which makes cross-compilation to OpenBSD (and other targets) straightforward.
Table of Contents
Requirements
- Go 1.22 or later
No other dependencies need to be installed. The SQLite driver is compiled from pure Go.
Build
go build -o bittuppi ./cmd/bittuppi
Usage
Point the binary at a directory tree containing your files:
./bittuppi -root /srv/library
Then open http://127.0.0.1:8080 in a browser.
Flags
| Flag | Default | Description |
|---|---|---|
-root |
(required) | Library root directory to index |
-db |
./bittuppi.sqlite |
Path to the SQLite database file |
-listen |
127.0.0.1:8080 |
HTTP listen address |
-rescan |
60s |
Periodic rescan interval; set to 0 to disable |
Example
go run ./cmd/bittuppi -root ~/Documents/Library -db ./bittuppi.sqlite -listen 127.0.0.1:8080 -rescan 120s
Example directory layout
/srv/library/
Indo-European/
Slavic/
Russian/
grammar_textbook.pdf
Germanic/
English/
pronunciation_guide.mp3
Mathematics/
linear_algebra_done_right.epub
Files are indexed with the directory path as the category. The filename (minus extension, with underscores and dots replaced by spaces) becomes the title. In the example above, Indo-European/Slavic/Russian/grammar_textbook.pdf gets category Indo-European/Slavic/Russian and title grammar textbook.
API
GET /api/search?q=...&category=... returns up to 200 matching documents as JSON. When q is provided, FTS5 full-text search is used with BM25 ranking. When q is empty, the newest files in the given category (or all categories) are returned.
GET /api/categories returns a JSON array of {"category": "...", "count": N} objects.
GET /f/<path> serves the underlying file. The path must exist in the database; arbitrary filesystem access is not possible.
OpenBSD Notes
Cross-compile from Linux:
GOOS=openbsd GOARCH=amd64 CGO_ENABLED=0 go build -o bittuppi ./cmd/bittuppi
Since there is no CGO involved, the resulting binary runs without any shared library dependencies.
To expose the service on a public interface, you can place it behind httpd(8) or relayd(8) as a reverse proxy. A minimal relayd.conf snippet:
relay "bittuppi" {
listen on egress port 443 tls
protocol https
forward to 127.0.0.1 port 8080
}
No systemd or rc scripts are strictly necessary. Running the binary directly (or from a tmux/screen session, or via an /etc/rc.local entry) works fine.