Self-hosted service
LibrePhotos/librephotos avatar
LibrePhotos/librephotos

LibrePhotos: Self-Hosted Photo Management With Face Recognition and Semantic Search

A self-hosted open source photo management service.

8,075 stars395 forksPythonMIT

At a glance

What is it?
LibrePhotos is an MIT-licensed Django and React application that indexes a photo library on disk, runs face recognition, object detection and captioning over it, and exposes the results through a web client. It is a good fit for engineers with a spare Linux box and 8 GB of RAM who want their photos off someone else's servers.
Who is it for?
Adopt LibrePhotos if you already run Docker Compose on a Linux host with 8 GB or more of RAM and you want face clustering, scene classification and semantic search over a library you control. Do not adopt it if your only machine has 4 GB of RAM or less, or if you need the mobile client on iOS, since the repository lists a React Native Android client only.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The Problem LibrePhotos Solves, and Who Has It

Cloud photo services give you face grouping, object search and a timeline in exchange for uploading your library to someone else's storage and accepting whatever terms they set. Running a local alternative has historically meant either a bare folder of files with no indexing or a service that indexes metadata but does nothing with image content. LibrePhotos occupies the second position: it scans pictures on the file system, extracts EXIF through ExifTool, and then runs machine learning over the pixels. The README lists face recognition and classification, object and scene detection, semantic image search, reverse geocoding, and album generation from events such as a day in a particular city.

The audience is narrow but real. It is a self-hoster who already runs Docker and is comfortable with Compose files, who has a Linux machine or NAS with at least 8 GB of RAM, and who values the ability to query their own library by content rather than by filename. Multiuser support is listed as a feature, so a household sharing one instance is within scope. Anyone who wants a hosted product with a support contract is not the target, and the installation documentation does not pretend otherwise.

How the Indexing and Machine Learning Pipeline Is Assembled

The repository is a monorepo that consolidates five previously separate projects: apps/backend, apps/frontend, apps/mobile, apps/docs and deploy. Commit history was preserved across the move, so git log --follow apps/backend/<file> still walks back through the old repository. That matters if you are evaluating how a particular ML component evolved, because the history is not truncated at the merge point.

The backend is Django 5 with Django REST Framework, backed by PostgreSQL. Background work runs through Django-Q2, which is the queue that carries scanning and ML jobs. Image conversion goes through ImageMagick, video through FFmpeg, and EXIF extraction through ExifTool. The ML stack is a set of separate libraries rather than one model: face_recognition for detection, scikit-learn and hdbscan for clustering faces into people, im2txt for image captioning, places365 for scene classification, and geopy for reverse geocoding. The frontend is React 18 with TypeScript, built by Vite, using Mantine for components, TanStack Router and Query for routing and data fetching, MapLibre GL for maps, and i18next for localization.

The data flow implied by that stack is: files on disk get scanned by a Django-Q2 job, EXIF is read out, converted derivatives are produced by ImageMagick and FFmpeg, and the ML libraries produce embeddings and labels that land in PostgreSQL alongside the file records. The React client then queries the Django REST API. The README states that interactive API documentation is served at /api/swagger and /api/redoc on port 3000 once the service is running, which means the API surface is inspectable without reading the backend source.

Getting an Instance Running

The README does not inline the install commands. It points to the standard install guide at docs.librephotos.com/docs/installation/standard-install, and the deploy/ directory holds the Dockerfiles, Compose configs, proxy configuration and Kubernetes manifests. The documented path is Docker Compose on any Docker-compatible OS, with Linux listed as recommended.

The resource table in the README gives 4 GB RAM as the minimum and 8 GB or more as recommended, 10 GB of storage plus your photo library, 2 CPU cores minimum and 4 or more recommended, and an SSD for storage. A note directly below the table states that machine learning features are memory-intensive and that 8 GB or more is strongly recommended for smooth operation. Treat the 4 GB figure as the floor for the web application and database, not for a full ML scan.

For development rather than deployment, the Compose-based dev environment lives in deploy/compose/ and is described in the development install guide at docs.librephotos.com/docs/development/dev-install. The README claims that guide gets a contributor started in under 30 minutes. Once the stack is up, the API docs are at http://localhost:3000/api/swagger and http://localhost:3000/api/redoc. Beyond the paths and the resource figures, the README does not specify environment variable names or Compose service names, so the exact keys have to come from the deploy/ files and the installation guide rather than from this page.

Where the Design Costs You: Memory, Scanning and Model Quality

The clearest limitation is stated by the project itself: the ML features are memory-intensive. Face recognition, scene classification and captioning each load models, and the README's own recommendation doubles the minimum RAM figure. A 4 GB machine that satisfies the minimum table will run the web application but is likely to struggle when a scan kicks off. That is a hardware constraint, not a configuration mistake.

The second cost is the model set. Face clustering is described as scikit-learn plus hdbscan, which is density-based clustering. Density-based clustering does not require you to specify the number of people in advance, but it does mean cluster boundaries depend on distance thresholds, and the documentation does not describe an interface for tuning those thresholds. Scene classification via places365 assigns one of a fixed set of scene categories, so a query for something outside that taxonomy will not match on scene label. Captioning through im2txt is an older image-to-text architecture; the README lists it without any claim about caption quality, and none should be assumed.

The third cost is operational. Django-Q2 carries the background jobs, and there is no described mechanism in the supplied material for incremental rescanning guarantees, conflict handling when files change on disk, or what happens to ML results when a file is moved. The release history shows small corrective releases after 1.0.0, including 1.0.2 titled "Fix gpu image again" and 1.0.3 fixing a user list popup for non-admin users. Those titles suggest the GPU image path has been unstable enough to need repeat attention, and that the 1.x line is still absorbing UI-level defects. If you need a system that has stopped changing, this is not it.

How It Differs From Immich and PhotoPrism

The obvious comparison is Immich, a self-hosted photo and video backup service that has become the default recommendation in this category. The difference in approach is where the library lives and what the system is for. Immich is built around the mobile client uploading from a phone into its own managed storage, so the application owns the files. LibrePhotos scans pictures on the file system, which means the library stays where you put it and the application indexes it in place. If you already have a directory tree you do not want to reorganize, that is a meaningful distinction.

The second comparison is PhotoPrism, which also indexes an existing library and also runs TensorFlow-based classification and face clustering. Both projects are self-hosted, both are open source, and both target the same user. The observable difference from the material here is the stack: LibrePhotos is Django and PostgreSQL with Django-Q2 for jobs, while PhotoPrism is Go with its own indexing daemon. That choice shows up in how you operate it. A Django application is straightforward to extend if your team already writes Python, and the README's contributing section points at per-app READMEs for backend, frontend, mobile and docs, plus a CONTRIBUTING.md with code quality standards and PR guidelines. A Go binary is easier to ship as a single artifact but harder to modify if you do not write Go.

A third point of difference is the mobile client. LibrePhotos lists a React Native client for Android only. That is a real gap for anyone whose primary device is an iPhone, and the README does not mention an iOS client anywhere.

Maintenance, Upgrades and the MIT Licence

LibrePhotos is MIT licensed. That is permissive: you can use, modify, redistribute and sell derivative work, provided the copyright notice and permission notice are retained. It is not a copyleft licence, so changes you make to the backend do not have to be published. This is a summary of what MIT typically means, not legal advice; read the LICENSE file in the repository if the distinction matters to your organization.

Maintenance cost is dominated by the ML dependencies rather than by LibrePhotos itself. The backend pulls in face_recognition, scikit-learn, hdbscan, im2txt, places365 and geopy, plus ImageMagick, FFmpeg and ExifTool as external binaries. Each of those has its own release cadence and its own compatibility constraints. The monorepo consolidation helps here: five repositories became one, so a dependency bump for the backend and a matching frontend change can land in a single pull request instead of being coordinated across repos.

The release cadence visible in the supplied material is a 1.0.0 line followed by 1.0.2 and 1.0.3 within about two months, then 1.1.0 covering June through August 2026. The patch titles are narrow fixes, not feature drops. The README also describes a dev tag intended for users who want to help find bugs, with the instruction to update it regularly. If you run the dev tag you are opting into that role. For a stable deployment, pin to a released version and read the release notes before moving, particularly around the GPU image, which has been patched more than once.

Who Should Take It On

The case for LibrePhotos rests on a specific combination: you have a Linux host with 8 GB or more of RAM, you already run Docker Compose, your photos live in a directory you control, and you want content-based search over them without uploading anything. The monorepo layout, the preserved git history, and the per-app READMEs make it a reasonable codebase to contribute to if you write Python or TypeScript. The Swagger and ReDoc endpoints at /api/swagger and /api/redoc mean you can build against the API without reverse-engineering the frontend.

The case against is equally specific. If your hardware is at or near the 4 GB minimum, the ML features are the part you will lose first, and they are the reason to choose this over a plain folder browser. If you want iOS support, the repository lists an Android client only. If you need a system whose GPU path has settled, the 1.0.x patch titles suggest otherwise. And if you want the application to own and sync your files from a phone rather than index a directory you manage, the Immich model of upload-into-managed-storage is the closer fit to that requirement.

The practical next step is to stand up the Compose stack from deploy/compose/ on the machine you intend to use, point it at a small test directory rather than your full library, and confirm that a scan completes within your memory budget before you commit the real archive.

Editorial conclusion

Adopt LibrePhotos if you already run Docker Compose on a Linux host with 8 GB or more of RAM and you want face clustering, scene classification and semantic search over a library you control. Do not adopt it if your only machine has 4 GB of RAM or less, or if you need the mobile client on iOS, since the repository lists a React Native Android client only. Before committing a real library, verify three things: that the deployment stack in deploy/compose/ starts cleanly on your hardware, that your photos are reachable as a mounted volume rather than copied in, and that the ML worker containers complete a scan without exhausting memory.

Official sources

  1. LibrePhotos/librephotos on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Community notes

Community notes