I’ve switched from managed photo providers (such as Apple or Google photos) to a self-hosted Photoprism instance. This note documents my setup.
I use Linode for this, and you can get a free $100 credit using this referral link.
Update 2022: More recently I’ve migrated Photoprism over to a home-based Raspberry Pi, which works great.
Server setup
Provision a new server or instance (at least 4GB memory and 2 CPU cores), and create and attach a big (I use 1TB) volume.
Encrypt the attached volume using LUKS, create a filesystem, mount points (fstab
, etc.) and mount it (e.g. to /data
).
Alternatively use fscrypt to encrypt a directory.
This note should help with the encryption process.
Install Docker and Docker Compose.
Running Photoprism
Create a docker-compose.yml
:
services:
photoprism:
image: photoprism/photoprism:latest
depends_on:
- mariadb
restart: unless-stopped
security_opt:
- seccomp:unconfined
- apparmor:unconfined
ports:
- "80:2342"
environment:
PHOTOPRISM_ADMIN_PASSWORD: "CHANGEME"
PHOTOPRISM_AUTH_MODE: "password"
PHOTOPRISM_SITE_URL: "http://CHANGEME"
PHOTOPRISM_ORIGINALS_LIMIT: 5000
PHOTOPRISM_HTTP_COMPRESSION: "gzip"
PHOTOPRISM_LOG_LEVEL: "info"
PHOTOPRISM_READONLY: "false"
PHOTOPRISM_EXPERIMENTAL: "false"
PHOTOPRISM_DISABLE_CHOWN: "false"
PHOTOPRISM_DISABLE_WEBDAV: "false"
PHOTOPRISM_DISABLE_SETTINGS: "false"
PHOTOPRISM_DISABLE_TENSORFLOW: "false"
PHOTOPRISM_DISABLE_FACES: "false"
PHOTOPRISM_DISABLE_CLASSIFICATION: "false"
PHOTOPRISM_DISABLE_RAW: "false"
PHOTOPRISM_RAW_PRESETS: "false"
PHOTOPRISM_JPEG_QUALITY: 85
PHOTOPRISM_DETECT_NSFW: "false"
PHOTOPRISM_UPLOAD_NSFW: "true"
PHOTOPRISM_DATABASE_DRIVER: "mysql"
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
PHOTOPRISM_DATABASE_NAME: "photoprism"
PHOTOPRISM_DATABASE_USER: "photoprism"
PHOTOPRISM_DATABASE_PASSWORD: "CHANGEME"
PHOTOPRISM_SITE_CAPTION: "AI-Powered Photos App"
PHOTOPRISM_SITE_DESCRIPTION: ""
PHOTOPRISM_SITE_AUTHOR: ""
working_dir: "/photoprism"
volumes:
- "/data/originals:/photoprism/originals"
- "./import:/photoprism/import"
- "/data/storage:/photoprism/storage"
mariadb:
restart: unless-stopped
image: mariadb:10.8
security_opt:
- seccomp:unconfined
- apparmor:unconfined
command: mysqld --innodb-buffer-pool-size=512M --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
volumes:
- "/data/database:/var/lib/mysql"
environment:
MARIADB_AUTO_UPGRADE: "1"
MARIADB_INITDB_SKIP_TZINFO: "1"
MARIADB_DATABASE: "photoprism"
MARIADB_USER: "photoprism"
MARIADB_PASSWORD: "CHANGEME"
MARIADB_ROOT_PASSWORD: "CHANGEME"
Bring up the instance using docker compose up -d
.
Backups
Photoprism provides its own backup facility. However, since I run nearly everything in Docker, I am hesitant when adding too much configuration to the host itself.
Instead I created my own Photoprism Docker image that uses Restic to backup the originals and database to a compatible Restic backend.
See the repo (git.wilw.dev/wilw/photoprism-backup) for more information, but a basic container can be brought up with:
...
photosbackup:
image: wilw/photoprism-backup
restart: always
volumes:
- "/path/to/originals:/photoprism/originals"
environment:
PHOTOPRISM_DATABASE_SERVER: "mariadb"
PHOTOPRISM_DATABASE_NAME: "photoprism"
PHOTOPRISM_DATABASE_USER: "photoprism"
PHOTOPRISM_DATABASE_PASSWORD: "CHANGEME"
AWS_ACCESS_KEY_ID: "CHANGEME"
AWS_SECRET_ACCESS_KEY: "CHANGEME"
RESTIC_REPOSITORY: "s3:endpoint/bucket"
RESTIC_PASSWORD: "CHANGEME"
RESTIC_HOSTNAME: "hostname"
Syncing photos
I take many photos on my phone. In the bad old days of Apple and Google Photos, the official apps would seamlessly sync photos to the cloud. To replicate this model with Photoprism, I downloaded the PhotoSync app, which has built-in support for Photoprism servers. Below summarises my setup:
- I configured PhotoSync with my Photoprism server as a target, and configured it to upload to the Photoprism
/import
directory. - I setup an Autotransfer trigger in PhotoSync to automatically upload new photos and videos when I attach my charger each evening.