Skip to content

PhotoPrism

AI-Powered Photo Management

PhotoPrism is an AI-powered photos app for the decentralized web. It uses the latest technologies to tag and find pictures automatically without getting in your way. Browse all your photos and videos without worrying about RAW conversion, duplicates, or video formats.

Why Choose PhotoPrism?

  • AI-powered - automatic tagging with facial recognition
  • Universal formats - RAW, HEIF/HEIC, and video support
  • Smart organization - world map and timeline views
  • Privacy-first - 100% private with no cloud dependencies

Install

Infrastructure as Code

This PhotoPrism instance is deployed using OpenTofu with custom Incus images. The infrastructure configuration manages container provisioning and persistent storage volumes.

Custom PhotoPrism Image

The PhotoPrism Incus image is built and maintained at forgejo.benoit.jp.net/Benoit/Laminar.

Infrastructure Configuration

The OpenTofu configuration provisions:

  • Incus instance running custom PhotoPrism image
  • Four persistent storage volumes:
    • /opt/photoprism/config - PhotoPrism configuration
    • /opt/photoprism/storage - Database, cache, and sidecar files
    • /opt/photoprism/originals - Original photo files
    • /opt/photoprism/backup - Backup storage
OpenTofu Configuration
resource "incus_storage_volume" "photoprism_opt_photoprism_config" {
  name = "photoprism_opt_photoprism_config"
  pool = incus_storage_pool.default.name
  config = {
    "initial.gid"  = "1001"
    "initial.uid"  = "1001"
    "initial.mode" = "755"
  }
}

resource "incus_storage_volume" "photoprism_opt_photoprism_storage" {
  name = "photoprism_opt_photoprism_storage"
  pool = incus_storage_pool.default.name
  config = {
    "initial.gid"  = "1001"
    "initial.uid"  = "1001"
    "initial.mode" = "755"
  }
}

resource "incus_storage_volume" "photoprism_opt_photoprism_originals" {
  name = "photoprism_opt_photoprism_originals"
  pool = incus_storage_pool.default.name
  config = {
    "initial.gid"  = "1001"
    "initial.uid"  = "1001"
    "initial.mode" = "755"
  }
}

resource "incus_storage_volume" "photoprism_opt_photoprism_backup" {
  name = "photoprism_opt_photoprism_backup"
  pool = incus_storage_pool.default.name
}

resource "incus_instance" "photoprism" {
  name  = "photoprism"
  image = "laminar.incus:photoprism-1.2507.07+250707-d28b3101e-1benoitjpnet"

  device {
    name = "photoprism_opt_photoprism_config"
    type = "disk"
    properties = {
      path   = "/opt/photoprism/config"
      source = incus_storage_volume.photoprism_opt_photoprism_config.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "photoprism_opt_photoprism_storage"
    type = "disk"
    properties = {
      path   = "/opt/photoprism/storage"
      source = incus_storage_volume.photoprism_opt_photoprism_storage.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "photoprism_opt_photoprism_originals"
    type = "disk"
    properties = {
      path   = "/opt/photoprism/originals"
      source = incus_storage_volume.photoprism_opt_photoprism_originals.name
      pool   = incus_storage_pool.default.name
    }
  }

  device {
    name = "photoprism_opt_photoprism_backup"
    type = "disk"
    properties = {
      path   = "/opt/photoprism/backup"
      source = incus_storage_volume.photoprism_opt_photoprism_backup.name
      pool   = incus_storage_pool.default.name
    }
  }
}

Deploy Infrastructure

Apply OpenTofu configuration
tofu apply

After provisioning, configure PhotoPrism by editing /etc/photoprism/defaults.yml with your settings and preferences.

Upgrade

Incus Image Upgrade

When upgrading to a newer Incus image version, follow these steps to migrate your data.

Backup current instance data before upgrading:

Enter Incus container
incus shell photoprism

Backup configuration file

cp /etc/photoprism/defaults.yml /opt/photoprism/backup/

Backup MySQL database

mysqldump photoprism > /opt/photoprism/backup/db.sql

Deploy to new Incus image and restore data:

Update OpenTofu configuration

Edit your OpenTofu configuration file to update the image version:

resource "incus_instance" "photoprism" {
  name  = "photoprism"
  image = "laminar.incus:photoprism-NEW-VERSION"  # Update this line
  # ...
}

Apply infrastructure changes

Provision new Incus container
tofu apply
Enter Incus container
incus shell photoprism

Restore configuration file

cp /opt/photoprism/backup/defaults.yml /etc/photoprism/

Restore MySQL database

mysql photoprism < /opt/photoprism/backup/db.sql

Restart PhotoPrism service

systemctl restart photoprism

Upgrade Complete

Your PhotoPrism instance is now running on the new Incus image with all photos and AI data intact!


Related Documentation: - Infrastructure Overview - Complete self-hosting architecture - Docker Management Guide - Container orchestration tips