Convalesco

Current revision: 0.8

Last update: 2024-09-29 19:00:26 +0000 UTC

Many people would sooner die than think; In fact, they do so.

B. Russel


Setup photoprism in Gentoo GNU/Linux

Date: 29/09/2024, 08:51

Category: technology

Revision: 1



Introduction

PhotoPrism is an AI-powered photos app for the decentralized web. It leverages modern technologies to automatically tag and search pictures without getting in your way. You can run it at home, on a private server, or in the cloud. While the proposed installation method is via Docker, this guide uses MariaDB as the database and Nginx as the web server.

This guide is specifically tailored for the Gentoo GNU/Linux distribution, but the steps should be similar for other distributions.

Prerequisites

Ensure you have installed ImageMagick, ffmpeg, MariaDB, and Nginx.

PhotoPrism requires several libraries and tools for a smooth experience, especially for handling photo and video formats. You need to install these libraries manually. Add the following USE flags to your /etc/portage/make.conf file:

jpeg tiff avif heic png webp ffmpeg imagemagick

Next, install the required packages:

emerge -av www-servers/nginx dev-db/mariadb media-libs/libheif media-libs/libavif media-video/ffmpeg media-gfx/imagemagick

NOTE: PhotoPrism can integrate with tools like DarkTable for professional photographers.

Storage Filesystem

The microserver features four 2TB disk drives in a storage array and a 250GB SSD drive for the operating system. The storage layer runs in ZFS mirror (RAID1) mode, providing 4TB of usable space on a system that can tolerate one HDD failure1 without data loss.

NOTE: I recommend using RAID5 instead of RAID1. RAID5 offers more space, better performance, and nearly the same level of reliability.

Filesystem configuration is out of the scope of this document.

Setup MySQL and Nginx

Setting up MySQL is also out of the scope of this guide. You can follow the official documentation for assistance. Once the database is set up, create a new database and user for PhotoPrism:

CREATE DATABASE photoprism;
CREATE USER 'photoprism'@'localhost' IDENTIFIED BY 'password123';
GRANT ALL PRIVILEGES ON photoprism.* TO 'photoprism'@'localhost';
FLUSH PRIVILEGES;

For SSL certificates and DNS, I am using AWS Route53, but this is a personal preference, so I’ll skip the setup here. Connections over VPN are secure, so SSL setup isn’t mandatory.

NOTE: To set up Let’s Encrypt with AWS Route53 DNS verification, I recommend using the acme-sh package (app-crypt/acme-sh in Gentoo) instead of certbot.

Here is my Nginx configuration for PhotoPrism. Adjust it according to your needs:

Generic Nginx Configuration

# /etc/nginx/nginx.conf
user nginx nginx;
worker_processes 2;

error_log /var/log/nginx/error_log info;

events {
    worker_connections 1024;
    use epoll;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    dav_methods PUT DELETE MKCOL COPY MOVE;
    dav_ext_methods PROPFIND OPTIONS;
    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $bytes_sent '
        '"$http_referer" "$http_user_agent" '
        '"$gzip_ratio"';

    client_header_timeout 10m;
    client_body_timeout 30m;
    client_max_body_size 0;
    create_full_put_path on;
    client_body_temp_path /tmp/;
    send_timeout 10m;

    connection_pool_size 256;
    client_header_buffer_size 4k;
    large_client_header_buffers 4 2k;
    request_pool_size 4k;

    gzip on;

    output_buffers 1 32k;
    postpone_output 1460;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 75 20;

    ignore_invalid_headers on;

    index index.html;

    include /etc/nginx/conf.d/*.conf;
}

Nginx Website Configuration

server {
  listen 443 ssl;
  server_name photoprism.example.com;

  ssl_certificate /etc/acme-sh/example.com_ecc/fullchain.cer;
  ssl_certificate_key /etc/acme-sh/example.com_ecc/example.com.key;
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
  ssl_dhparam /etc/nginx/ssl/dhparams.pem;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 30m;
  client_max_body_size 15G;

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_pass http://localhost:2342;

    proxy_buffering off;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

While the PhotoPrism developers recommend Traefik as a reverse proxy, I am using Nginx because I am more familiar with it.

TensorFlow

TensorFlow is required for face recognition, a highly desired feature for family photo libraries. Setting up TensorFlow varies depending on your hardware. You can follow the official guide to compile TensorFlow from source, or use precompiled libraries if available for your CPU.

Setting Up PhotoPrism

There is no Portage package for PhotoPrism. It is distributed as a Go binary, which you can download from the GitHub repository.

First, create the photoprism user and group:

groupadd photoprism
useradd -r -g photoprism -d /opt/photoprism -s /sbin/nologin photoprism
mkdir -p /opt/photoprism
id photoprism # Verify setup

Download and extract the latest version to the /opt/photoprism directory:

cd /tmp && curl -LO https://github.com/photoprism/photoprism/releases/download/240915-e1280b2fb/photoprism_240915-e1280b2fb-linux-amd64.tar.gz
tar zxf -C /opt/photoprism photoprism_240915-e1280b2fb-linux-amd64.tar.gz
chown photoprism:photoprism -R /opt/photoprism

You can run the binary directly, but I recommend creating an OpenRC service.

Setting Up Photoprism Init Script

Create the init configuration in /etc/conf.d/photoprism:

# /etc/conf.d/photoprism
# Global photoprism options
group="photoprism"
user="photoprism"

# Photoprism configuration
pidfile="/var/run/photoprism.pid"
log="/var/log/photoprism/photoprism.log"
photoprism_defaults="/etc/photoprism/defaults.yml"

And the init script at /etc/init.d/photoprism:

#!/sbin/openrc-run

name="photoprism"
description="Manage pictures automatically"
command="/opt/photoprism/bin/photoprism"
pidfile=${pidfile:-"/run/${RC_SVCNAME}.pid"}
output_log="${log}"
error_log="${log}"

user=${user:-root}
group=${group:-root}
command_user="${user}:${group}"

command_args="--defaults-yaml ${photoprism_defaults} --pid-filename ${pidfile} --log-filename ${log} start"
command_background="true"

depend() {
    need net
    use logger
}

start_pre() {
    checkpath -q -d -m 0755 -o ${user}:${group} /var/log/photoprism
}

Setting Up Photoprism Directories

Create the necessary directories:

mkdir -p /storage/photoprism/{originals,import}
chown photoprism:photoprism -R /storage/photoprism
mkdir /etc/photoprism

The library will live under /storage/photoprism/originals, and files added to /storage/photoprism/import will be automatically imported.

NOTE: Following best practices, the library is stored on the HDD, while thumbnails are stored on the SSD.

Configuration Files

Create the defaults.yml configuration file in /etc/photoprism:

ConfigPath: "/etc/photoprism"
StoragePath: "/opt/photoprism/storage"
OriginalsPath: "/storage/photoprism/originals"
AssetsPath: "/opt/photoprism/assets"
ImportPath: "/storage/photoprism/import"
AdminUser: "admin"
AdminPassword: "<password>"
HttpPort: 2342
...

Then set up the options.yml file, which includes MySQL configuration:

AdminPassword: Chee8eihoh
AdminUser: admin
AutoImport: 60
DatabaseDriver: mysql
...

Ensure the correct permissions:

chown photoprism:photoprism -R /etc/storage

Closing Notes

Explore PhotoPrism to understand its logic. With this setup, adding files to the /import directory will trigger an import workflow after about 60 seconds.

Use /var/log/photoprism/photoprism.log for debugging startup issues. Photoprism can be finicky about permissions, so carefully review your setup.


  1. Under circumstances the system could support simultaneously two HDDs failures, assuming they don’t belong to the same source-mirror pair.