rbv

Personal photo library indexer with facial recognition and semantic search. Extracts CLIP embeddings and face detections from image galleries via an immich-ml compatible ML API, clusters faces into person identities, and serves results through a mTLS-authenticated HTTPS API with a React web UI.

Workspace layout

Cargo.toml          workspace root
migrations/         PostgreSQL migrations (sqlx)
crates/
  rbv-entity        shared type definitions (no logic)
  rbv-hash          BLAKE3 content-addressed ID generation
  rbv-data          database access layer (sqlx + pgvector)
  rbv-ml            ML API client (immich-ml wire format)
  rbv-cluster       face embedding clustering (DBSCAN / union-find)
  rbv-ingest        gallery discovery and ingest pipeline
  rbv-auth          mTLS validation, argon2 passwords, sessions
  rbv-search        combined CLIP + face search queries
  rbv-cli           binary: `rbv`
  rbv-api           binary: `rbv-api` (axum HTTPS server)
ui/                 Vite + React + TypeScript frontend

Crate dependency graph

rbv-entity  (no deps)
rbv-hash    → rbv-entity
rbv-data    → rbv-entity, rbv-hash
rbv-ml      → rbv-entity
rbv-cluster → rbv-entity
rbv-ingest  → rbv-entity, rbv-hash, rbv-data, rbv-ml
rbv-auth    → rbv-entity
rbv-search  → rbv-entity, rbv-data, rbv-ml
rbv-cli     → rbv-entity, rbv-hash, rbv-data, rbv-ml, rbv-ingest, rbv-cluster
rbv-api     → rbv-entity, rbv-data, rbv-ml, rbv-auth, rbv-search

Prerequisites

  • PostgreSQL with the pgvector extension
  • An immich-ml compatible ML API (e.g. the immich machine-learning container)
  • Rust toolchain (stable)
  • Node.js + npm (for the UI)

Building

cargo build --release

Binaries are written to target/release/rbv and target/release/rbv-api.

Build the UI:

cd ui && npm install && npm run build

The built assets land in dist/ui/ and are served by rbv-api --ui-dir.

Deployment

See script/deploy.sh for the build-and-deploy script used to push to the server, and asset/ for the systemd unit and Podman quadlet files.

Usage

See crates/rbv-cli/README.md for the full rbv index / rbv cluster workflow, incremental re-indexing, and how to reset face assignments.

API server

rbv-api \
  --ca-cert   /etc/rbv/ca.pem \
  --server-cert /etc/rbv/server.pem \
  --server-key  /etc/rbv/server.key \
  --database  "$DATABASE_URL" \
  --ml-uri    http://127.0.0.1:3003 \
  --ui-dir    /srv/rbv/ui \
  --face-cache /srv/rbv/cache/faces \
  [--listen 0.0.0.0:8443] \
  [--client-cn browser.local]

The server requires mTLS: clients must present a certificate signed by the configured CA. --client-cn restricts access to specific certificate common names; if omitted, any valid client cert is accepted.

API routes

Method Path Description
POST /api/auth/login Authenticate (sets session cookie)
POST /api/auth/register Create account
POST /api/auth/logout Invalidate session
GET /api/auth/me Current user
GET /api/galleries Paged gallery list
GET /api/galleries/random Random gallery sample
GET /api/galleries/:id Gallery metadata
GET /api/galleries/:id/images Images in a gallery
GET /api/images/:id/file Full image file
GET /api/images/:id/thumbnail Resized thumbnail
GET /api/persons Paged person list
GET /api/persons/:id Person detail + names
GET /api/persons/:id/galleries Galleries containing person
GET /api/persons/:id/faces Face detections for person
PUT /api/persons/:id/name Set primary name
POST /api/persons/:id/alias Add alias name
POST /api/persons/merge Merge two persons
GET /api/faces/:id/crop Cropped face image (cached)
POST /api/search Combined CLIP + person search

All routes except the auth endpoints require a valid session cookie.

A gallery directory must contain:

  • index.json — metadata (id, collection, source name/url, subjects, tags)
  • tn/ — thumbnail subdirectory (used to detect gallery directories)
  • Image files (jpg, png, gif, webp, tiff, bmp)

Directories are discovered recursively from --target; the structure may be flat, chunked (galleries grouped in subdirectories), or mixed.

Description
No description provided
Readme 295 KiB
Languages
Rust 63.4%
TypeScript 25.4%
CSS 6.6%
Shell 3.8%
PLpgSQL 0.7%
Other 0.1%