Performance and self-hosting focused
High performance: Built with Go and SQLite for high performance on minimal hardware.
Flexible deployment: Can be deployed with Docker or on bare metal in monolithic mode, or with Kubernetes in “scalable” mode with the option to scale various portions of the application separately.
Originals access: Original media files are only accessed once - image thumbnails and video transcodings are created on import for fast retrieval.
Privacy focused
Offline only: rgallery does not require calls to third party APIs (including reverse geocoding), and does not require internet access.
Authentication: Keep your library private with multi-user support.
No lock-in: Works with any folder structure - original files are never modified.
How to deploy
The recommended method for deploying rgallery is Docker, however it can be deployed on bare-metal as well. Binaries can be downloaded from https://packages.rmilo.dev/rgallery/ and dependencies such as ExifTool, Vips, and FFmpeg need to be installed.
Deploy with Docker
In a terminal, run the following command:
docker run \
-v ./media:/media:ro \
-v ./data:/data \
-v ./cache:/cache \
-p 3000:3000 \
robbymilo/rgallery:latest
or with docker compose:
wget https://packages.rmilo.dev/rgallery/latest/docker-compose.yml
docker compose up
or with docker compose in scalable mode:
wget https://packages.rmilo.dev/rgallery/latest/docker-compose-scalable.yml
docker compose -f docker-compose-scalable.yml up --scale goresize=3
The application will be available at http://localhost:3000.
If there are no media items in the database on startup, a scan will be initiated. Otherwise subsequent scans can be initiated on the Admin page at http://localhost:3000/admin.
The default user is admin
and the default password is admin
. Once logged in, create a new account and the admin account will be deleted.
Backup SQLite with Litestream
It is recommended to deploy rgallery with Litestream, which continuously backs up database changes to persistent storage (ex S3 or NFS).
Architecture
rgallery is built with Go. SQLite is used for persistence, Go templates for the frontend, and Alpine.JS for frontend interactivity. JavaScript is compiled with ESBuild.
How rgallery works
Admin account
The default user is admin
, and the default password is admin
. Once logged in for the first time, create a new account. The default admin account will be deleted.
Scanning and import
When rgallery is run for the first time, a default scan is started. During a default scan, the media directory is walked recursively, and media files are read and persisted, and thumbnails and video transcode files are generated.
rgallery will attempt to load files with the following extensions:
Images:
- .jpg
- .jpeg
- .heic
- .gif
- .png
Videos:
- .mp4
- .mov
When a subsequent scan is started, rgallery removes any files in the database that are no longer on disk. If any files have been updated they are reimported.
There are three types of scans:
- Default scan - regenerates thumbnails of modified media only.
- Metadata scan - re-imports all existing media items without recreating thumbnails.
- Deep scan - re-imports all existing media items and recreates thumbnails.
Only users with the role of admin can initiate scans.
User interface
Timeline view
The timeline view displays your media library with items grouped by day. It is possible to search and filter by rating via the UI. The view also accepts query params for filtering that are not yet available via the UI.
Memories
If media items exist “on this day” from year(s) ago, they will be displayed at the top of the timeline. They can be dismissed for the day, which is persisted via the browser’s local storage.
Favorites
The favorites view shows all media items with an EXIF rating of 5.
Folders
The folders view shows a navigable list of all folders found in the media directory.
Tags
The tags view shows a navigable list of all EXIF tags. The EXIF field “subject” is used.
Gear
The gear view shows a navigable list of cameras, lenses, focal lengths, and more along with the total count of media items.
Lens aliases
Camera manufactures often report various EXIF values for the same lens used on different camera bodies. This makes it difficult to count lens use totals across images and requires filtering under different labels even though the same lens was used to take the image.
For example, the Nikon AF-S Nikkor 70-200mm f/2.8G ED VR II is recorded under three values:
- AF-S Nikkor 70-200mm f/2.8G ED VR II
- 70.0-200.0 mm f/f2.8
- VR 70-200mm f/2.8G
rgallery supports Lens aliases, allowing various values to be grouped under the same lens.
To enable lens aliases:
Create a file under the
config
directory calledconfig.yml
.Populate it with the following YAML:
aliases: lenses: '70.0-200.0 mm f/f2.8': 'AF-S Nikkor 70-200mm f/2.8G ED VR II' 'VR 70-200mm f/2.8G': 'AF-S Nikkor 70-200mm f/2.8G ED VR II' 'AF-S Nikkor 70-200mm f/2.8G ED VR II': 'AF-S Nikkor 70-200mm f/2.8G ED VR II'
Restart the application.
All images with the lens value of 70.0-200.0 mm f/f2.8
, VR 70-200mm f/2.8G
, AF-S Nikkor 70-200mm f/2.8G ED VR II
will be totaled and can be filtered under the AF-S Nikkor 70-200mm f/2.8G ED VR II
lens value (ex: ?lens=AF-S Nikkor 70-200mm f%2f2.8G ED VR II
).
Map
The map view shows geo tagged images on the world map.
If the tile_server
CLI flag or RGALLERY_TILE_SERVER
environmental variable is not set, a low-resolution, offline-only map tile server is used.
Admin
The admin UI allows a user to initiate scans, create users, and create API keys.
API keys are granted admin access.
To initiate a scan daily at 00:30:
- Create an API key
- Save the API key to your secrets manager as it will never be shown again.
- Create a cron job on a server, such as:
30 0 * * * curl -H 'api-key: $(API_KEY)' 'https://<replace-with-rgallery-url>/scan'
- You may need to restart the cron service - refer to your distribution’s documentation.