Photoprism
Introduction
Photoprism is an amazing application to self-host. For me, it’s a direct alternative to Google Photos. It utilizes google’s tensorflow, but it doesn’t connect to Google at all. This means it has more advanced features, like facial recognition. This tutorial outlines how to set it up using docker. I personally use nextcloud to handle automatically uploading photos from my phone.
Prerequisites
- docker
- knowledge
- Nextcloud (optional, if you want to use nextcloud for upload)
Steps
- Folder creation
- Create the docker
- Create systemd unit
- link with nextcloud (for automatic photo upload from phones)
1. Folder creation
You’re going to want to create folders on your computer to store all the photoprism data. Photoprism needs two main folders. Originals and Storage. Originals is where photoprism stores all the original copies of your photos. This is also where you can put your own photos, if you want to move your existing library to Photoprism. I like to create a folder specifically for the docker compose, and anything else that I may want to add on to photoprism. For example, I have a cron task (explained later) that automatically re-indexes my photoprism library, and so I log the output of that to a file in the folder where my docker-compose is in.
2. Create the docker
This is where the fun begins. cd into the directory where you want to keep your docker-compose, and make the following file with the following contents:
vim docker-compose.yml
Then paste these contents into it:
version: '3.5'
# Example Docker Compose config file for PhotoPrism (Linux / AMD64)
#
# Note:
# - Running PhotoPrism on a server with less than 4 GB of swap space or setting a memory/swap limit can cause unexpected
# restarts ("crashes"), for example, when the indexer temporarily needs more memory to process large files.
# - If you install PhotoPrism on a public server outside your home network, please always run it behind a secure
# HTTPS reverse proxy such as Traefik or Caddy. Your files and passwords will otherwise be transmitted
# in clear text and can be intercepted by anyone, including your provider, hackers, and governments:
# https://docs.photoprism.app/getting-started/proxies/traefik/
#
# Documentation : https://docs.photoprism.app/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# DOCKER COMPOSE COMMAND REFERENCE
# see https://docs.photoprism.app/getting-started/docker-compose/#command-line-interface
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
# Logs | docker-compose logs --tail=25 -f
# Terminal | docker-compose exec photoprism bash
# Help | docker-compose exec photoprism photoprism help
# Config | docker-compose exec photoprism photoprism config
# Reset | docker-compose exec photoprism photoprism reset
# Backup | docker-compose exec photoprism photoprism backup -a -i
# Restore | docker-compose exec photoprism photoprism restore -a -i
# Index | docker-compose exec photoprism photoprism index
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
#
# All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory shortcut ~ to /root in volume mounts.
services:
photoprism:
## Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
depends_on:
- mariadb
## Don't enable automatic restarts until PhotoPrism has been properly configured and tested!
## If the service gets stuck in a restart loop, this points to a memory, filesystem, network, or database issue:
## https://docs.photoprism.app/getting-started/troubleshooting/#fatal-server-errors
# restart: unless-stopped
security_opt:
- seccomp:unconfined
- apparmor:unconfined
ports:
- "2342:2342" # HTTP port (host:container)
environment:
PHOTOPRISM_ADMIN_PASSWORD: "password" # !!! PLEASE CHANGE YOUR INITIAL "admin" PASSWORD !!!
# PHOTOPRISM_SITE_URL: "http://localhost:2342/" # public server URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_SITE_URL: "https://johannphotoprism.tk" # public server URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 100000 # file size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # run in debug mode (shows additional log messages)
PHOTOPRISM_PUBLIC: "false" # no authentication required (disables password protection)
PHOTOPRISM_READONLY: "false" # don't modify originals directory (reduced functionality)
PHOTOPRISM_EXPERIMENTAL: "false" # enables experimental features
PHOTOPRISM_DISABLE_CHOWN: "false" # disables storage permission updates on startup
PHOTOPRISM_DISABLE_WEBDAV: "false" # disables built-in WebDAV server
PHOTOPRISM_DISABLE_SETTINGS: "false" # disables Settings in Web UI
PHOTOPRISM_DISABLE_TENSORFLOW: "false" # disables all features depending on TensorFlow
PHOTOPRISM_DISABLE_FACES: "false" # disables facial recognition
PHOTOPRISM_DISABLE_CLASSIFICATION: "false" # disables image classification
PHOTOPRISM_DARKTABLE_PRESETS: "false" # enables Darktable presets and disables concurrent RAW conversion
PHOTOPRISM_DETECT_NSFW: "false" # flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # allows uploads that MAY be offensive
# PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_DATABASE_DRIVER: "mysql" # use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "password" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App"
PHOTOPRISM_SITE_DESCRIPTION: ""
PHOTOPRISM_SITE_AUTHOR: ""
## Run/install on first startup (options: update, gpu, tensorflow, davfs, nano, clean):
# PHOTOPRISM_INIT: "gpu tensorflow"
## Hardware video transcoding config (optional)
PHOTOPRISM_FFMPEG_BUFFERS: "64" # FFmpeg capture buffers (default: 32)
NVIDIA_DRIVER_CAPABILITIES: "all"
NVIDIA_VISIBLE_DEVICES: "all"
# PHOTOPRISM_FFMPEG_ENCODER: "h264_nvenc" # uncomment this line for nvenc support
PHOTOPRISM_FFMPEG_BITRATE: "8" # FFmpeg encoding bitrate limit in Mbit/s (default: 50)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_v4l2m2m" # use Video4Linux for AVC transcoding (default: libx264)
# PHOTOPRISM_FFMPEG_ENCODER: "h264_qsv" # use Intel Quick Sync Video for AVC transcoding (default: libx264)
## Run as a specific user, group, or with a custom umask (does not work together with "user:")
# PHOTOPRISM_UID: 1000
# PHOTOPRISM_GID: 1000
# PHOTOPRISM_UMASK: 0000
HOME: "/photoprism"
## Start as a non-root user (see https://docs.docker.com/engine/reference/run/#user)
# user: "1000:1000"
## Share hardware devices with FFmpeg and TensorFlow (optional):
devices:
# - "/dev/dri:/dev/dri"
# - "/dev/nvidia0:/dev/nvidia0" # Uncomment these lines for nvenc support
# - "/dev/nvidiactl:/dev/nvidiactl"
# - "/dev/video11:/dev/video11" # Video4Linux (h264_v4l2m2m)
working_dir: "/photoprism"
## Storage Folders: "~" is a shortcut for your home directory, "." for the current directory
volumes:
# "/host/folder:/photoprism/folder" # example
- "<path to originals>:/photoprism/originals" # original media files (photos and videos)
# - "/example/family:/photoprism/originals/family" # *additional* media folders can be mounted like this
# - "~/Import:/photoprism/import" # *optional* base folder from which files can be imported to originals
- "<path to storage>:/photoprism/storage" # *writable* storage folder for cache, database, and sidecar files (never remove)
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
## Database Server (recommended)
## see https://docs.photoprism.app/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
## If MariaDB gets stuck in a restart loop, this points to a memory or filesystem issue:
## https://docs.photoprism.app/getting-started/troubleshooting/#fatal-server-errors
restart: unless-stopped
image: mariadb:10.6
security_opt:
- seccomp:unconfined
- apparmor:unconfined
command: mysqld --innodb-buffer-pool-size=128M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
## Never store database files on an unreliable device such as a USB flash drive, an SD card, or a shared network folder:
volumes:
- "./database:/var/lib/mysql" # important, don't remove
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: photoprism
MYSQL_USER: photoprism
MYSQL_PASSWORD: password
## Watchtower upgrades services automatically (optional)
## see https://docs.photoprism.app/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # optional, for authentication if you have a Docker Hub account
Once you have saved, exited, and edited this compose to suit your needs (required lol), you can then run docker-compose up -d
to create all the dockers
3. Create systemd unit
This step shows you how to make a systemd service, which can be enabled and it will automatically update and recreate the photoprism dockers upon reboot. To do this, you just create a .service file in /etc/systemd/system
sudo vim /etc/systemd/system/photoprism-docker.service
Once you do that, paste in the following, and don’t forget to edit :) :
[Unit]
Description=Photoprism docker using docker-compose
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=<directory where you have the docker-compose file>
ExecStart=/usr/bin/docker-compose up -d
ExecStop=/usr/bin/docker-compose down
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
After that, reload the systemd configuration by entering the command:
sudo systemctl daemon-reload
Then you can enable the service:
sudo systemctl enable photoprism-docker.service
and boom, photoprism will automatically start on boot.
4. Link with Nextcloud
This is where it can get confusing. You can connect Nextcloud to Photoprism as a webdav share, but I find this very unreliable. It doesn’t work after a while if you have too many pictures. My solution is to just mount the Photos directory from Nextcloud to a folder in the Originals folder, and run a cron task to automatically index those photos every 15 minutes.
On mine, the folder is mounted like this in the docker-compose:
- "/mnt/main-storage/nextcloud/ncdata/johann/files/Photos:/photoprism/originals/nextcloud"
After that, I make a cron task to index the photos.
crontab -e
In the crontab, paste in:
*/15 * * * * /usr/bin/docker exec photoprism-photoprism-1 photoprism index
Unfortunately this hacky solution exists because of a lack of features in photoprism. This is because Photoprism on mobile is severely lacking, not allowing automatic upload. The nextcloud client works perfectly, and so I decided to do it like this. Don’t get me wrong, photoprism is awesome! I think it is one of the best things to self-host, as the web-interface is very polished and fast, providing features that compare to Google’s offerings.