Author | Nejat Hakan |
nejat.hakan@outlook.de | |
PayPal Me | https://paypal.me/nejathakan |
Photo Management PhotoPrism
Introduction
Welcome to this comprehensive guide on self-hosting PhotoPrism, a powerful, open-source application for browsing, organizing, and sharing your personal photo collection. In an era where cloud photo services raise privacy concerns and often come with recurring costs or limitations, self-hosting offers a compelling alternative, giving you complete control over your precious memories.
PhotoPrism stands out in the self-hosted landscape due to its modern user interface, robust feature set, and reliance on standard technologies. It automatically tags pictures based on their content using advanced machine learning (specifically Google TensorFlow), recognizes faces, identifies locations, and reads existing metadata (EXIF, XMP). It's designed to run efficiently, even on lower-powered hardware like a Raspberry Pi, although performance scales with available resources.
Why choose self-hosting for your photos?
- Privacy: Your photos remain on hardware you control. There's no third-party scanning your images for data mining or advertising purposes. You dictate who gets access.
- Control: You are not subject to the changing terms of service, pricing models, or feature deprecations of cloud providers. You decide when to update, how to back up, and how your library is structured.
- Cost: While there's an initial hardware investment (if you don't already have a server/NAS/spare computer) and ongoing electricity costs, you avoid potentially escalating subscription fees, especially for large libraries.
- Features: PhotoPrism offers features comparable to commercial services, including AI tagging, maps, facial recognition, raw file support, and metadata handling, all without vendor lock-in.
- Learning: Setting up and managing a service like PhotoPrism is an excellent way to deepen your understanding of Linux, Docker, networking, data management, and system administration – valuable skills for any university student, particularly in technical fields.
However, self-hosting isn't without its challenges. It requires a degree of technical comfort, ongoing maintenance (updates, backups), and responsibility for securing your setup. This guide aims to equip you with the knowledge and practical skills needed to successfully deploy and manage PhotoPrism, categorized into basic, intermediate, and advanced topics, suitable for learners at various levels. We'll start with the fundamentals and progressively delve into more complex configurations and optimizations. Each theoretical section is followed by a hands-on workshop to solidify your understanding through practical application.
Let's begin your journey into taking full ownership of your digital photo library!
1. Getting Started with Docker and PhotoPrism
This section covers the foundational knowledge required to get PhotoPrism up and running using Docker, the recommended deployment method. We'll introduce Docker concepts, guide you through its installation, and help you launch your first PhotoPrism instance.
Understanding Docker Basics
Before diving into PhotoPrism, it's crucial to grasp the fundamentals of Docker, the containerization platform that makes deploying applications like PhotoPrism significantly easier and more consistent across different environments.
What is Containerization? Imagine shipping goods. Instead of loading individual items onto a ship where they might shift, break, or get mixed up, you put them into standardized containers. These containers protect the contents and can be easily loaded, unloaded, and stacked using standard equipment, regardless of what's inside.
Containerization in software works similarly. An application and all its dependencies (libraries, configuration files, runtime environments) are packaged together into a standardized unit called a container image. This image can then be run as a container on any system that has a container runtime (like Docker) installed.
Containers vs. Virtual Machines (VMs) You might be familiar with VMs. VMs virtualize an entire hardware stack (CPU, RAM, storage, network card) and run a full guest operating system on top of the host OS. This provides strong isolation but consumes significant resources (RAM, disk space, CPU overhead).
Containers, on the other hand, virtualize the operating system level. They share the host system's OS kernel but have their own isolated user space, file system, and network stack. This makes containers:
- Lightweight: They require much less RAM and disk space than VMs.
- Fast: Containers start almost instantly as there's no OS boot process.
- Efficient: Less overhead means you can run more containers on the same hardware compared to VMs.
Key Docker Concepts:
- Docker Engine: The core background service (daemon) that builds, runs, and manages containers.
- Docker CLI: The command-line tool you use to interact with the Docker Engine (e.g.,
docker run
,docker ps
,docker build
). - Image: A read-only template containing the application code, libraries, dependencies, and configuration needed to run a container. Images are often built in layers, making them efficient to store and transfer. You can find pre-built images on registries like Docker Hub (e.g., the official
photoprism/photoprism
image). - Container: A runnable instance of an image. It's an isolated environment where the application runs. You can start, stop, move, and delete containers. Changes made inside a running container are typically lost when the container is removed unless you use volumes.
- Volume: A mechanism for persisting data generated by and used by Docker containers. Volumes are managed by Docker and exist independently of the container lifecycle. This is crucial for PhotoPrism, as you need to store your photos, database, and configuration persistently, even if you update or recreate the PhotoPrism container. Volumes are mapped into specific directory paths inside the container.
- Network: Docker containers can communicate with each other and the outside world through networks. Docker creates default networks, but you can define custom networks for better isolation and service discovery.
- Dockerfile: A text file containing instructions on how to build a custom Docker image. While we'll primarily use pre-built images for PhotoPrism, understanding Dockerfiles is essential for advanced customization.
- Docker Compose: A tool for defining and running multi-container Docker applications. It uses a YAML file (typically
docker-compose.yml
) to configure the application's services (containers), networks, and volumes. This is the preferred way to run PhotoPrism, as it often involves at least the PhotoPrism application container and potentially a separate database container (though PhotoPrism includes an embedded option).
Understanding these concepts is vital for effectively deploying, managing, and troubleshooting PhotoPrism in a Docker environment.
Workshop Installing Docker and Docker Compose
Goal: Install Docker Engine and Docker Compose on your Linux system (e.g., Ubuntu/Debian).
Prerequisites:
- A Linux machine (physical or virtual) with internet access. Ubuntu 20.04/22.04 LTS or Debian 11/12 are good choices.
- User account with
sudo
privileges.
Steps:
-
Update Package Index: Open a terminal and update your distribution's package list:
Explanation: This command refreshes the local list of available packages from the repositories configured on your system. It's essential to do this before installing new software to ensure you get the latest available versions and dependency information. -
Install Prerequisite Packages: Install packages required to allow
Explanation:apt
to use repositories over HTTPS:apt-transport-https
: Allows the package manager to retrieve packages over secure HTTPS connections.ca-certificates
: Allows the system to check the security certificates of the Docker repository.curl
: A command-line tool for transferring data using various protocols, used here to download the Docker GPG key.software-properties-common
: Provides helper scripts for managing software repositories, includingadd-apt-repository
.gnupg
: Utility for handling GPG keys, used for verifying the authenticity of the Docker repository.-y
: Automatically answers "yes" to any prompts during installation.
-
Add Docker's Official GPG Key: Download and add Docker's official GPG key to ensure the packages you download are authentic:
Explanation:curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
curl -fsSL ...
: Downloads the GPG key from Docker's official URL.-f
fails silently,-s
runs in silent mode,-S
shows errors if-s
is used,-L
follows redirects.|
: Pipes the downloaded key content to the next command.sudo gpg --dearmor -o ...
:gpg
is the GNU Privacy Guard tool.--dearmor
converts the key from the standard ASCII-armored format to the binary formatapt
uses.-o ...
specifies the output file location, placing it in a standard keyring directory.
-
Set Up the Stable Docker Repository: Add the official Docker repository to your system's APT sources. Replace
$(lsb_release -cs)
with your distribution's codename if needed (e.g.,jammy
for Ubuntu 22.04,bullseye
for Debian 11).Explanation:echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
echo "..."
: Constructs the repository definition string.[arch=$(dpkg --print-architecture)]
: Specifies the architecture (e.g.,amd64
,arm64
) automatically.signed-by=...
: Tellsapt
where to find the GPG key for verifying packages from this repository.https://download.docker.com/linux/ubuntu
: The base URL for the Docker repository (works for Debian too).$(lsb_release -cs)
: Automatically determines your distribution's codename (e.g.,jammy
,focal
,bullseye
).stable
: Specifies that you want the stable release channel of Docker.| sudo tee /etc/apt/sources.list.d/docker.list
: Writes the constructed string to a new file in theapt
sources directory.tee
is used to write to the file while also requiringsudo
privileges.> /dev/null
discards the standard output oftee
.
-
Update Package Index Again: Refresh the package list now that the Docker repository has been added:
-
Install Docker Engine: Install the latest stable version of Docker Engine, containerd, and the Docker CLI:
Explanation:sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker-ce
: The Docker Community Edition engine (the daemon).docker-ce-cli
: The Docker command-line interface.containerd.io
: An industry-standard container runtime that Docker Engine uses.docker-buildx-plugin
: Enables advanced build capabilities with BuildKit.docker-compose-plugin
: Integrates Docker Compose functionality directly into the Docker CLI (usingdocker compose
syntax instead of the olderdocker-compose
standalone command).
-
Verify Docker Installation: Check that Docker is installed and the service is running:
(Pressq
to exit the status view). You should see output indicating the service isactive (running)
.Run the
Explanation: This command downloads the smallhello-world
container to confirm Docker works correctly:hello-world
image (if not present locally) and runs it in a container. The container prints a confirmation message and exits. Seeing this message means your Docker installation is functional. -
(Optional but Recommended) Add User to Docker Group: To run
Explanation:docker
commands withoutsudo
every time, add your user to thedocker
group:usermod
modifies user accounts.-aG docker
adds (-a
) the user to the supplementary group (-G
) nameddocker
.$USER
automatically substitutes your current username. Important: You need to log out and log back in (or runnewgrp docker
in your current shell, though logging out/in is generally more reliable) for this group membership change to take effect. -
Verify Docker Compose Plugin: Check the installed version of the Docker Compose plugin:
Explanation: This uses the integrateddocker compose
command (part of the plugin installed in step 6) to display its version. This confirms Compose functionality is ready.
Conclusion: You have successfully installed Docker Engine and the Docker Compose plugin. Your system is now prepared to run containerized applications like PhotoPrism.
Setting Up Your First PhotoPrism Instance
Now that Docker is ready, we can prepare to launch PhotoPrism. The recommended method uses Docker Compose, which simplifies managing the application's configuration, volumes, and networking.
Core Components of a PhotoPrism Setup:
- PhotoPrism Container: Runs the main PhotoPrism application (web server, indexer, AI tools).
- Database: PhotoPrism needs a database to store metadata, user information, albums, etc. It supports MariaDB (recommended for multi-user or larger libraries) or an embedded SQLite database (simpler for single-user or initial testing). We'll start with the embedded database for simplicity.
- Volumes: Persistent storage is essential:
/photoprism/originals
: Stores your original, unmodified photo and video files. PhotoPrism reads from here but doesn't write to it by default./photoprism/storage
: Stores configuration files (options.yml
), sidecar files (containing metadata changes, generated JPEGs for RAWs), cache (thumbnails, index data), and the database (if using SQLite). This directory must be persistent./photoprism/import
: (Optional) A directory PhotoPrism can watch for new files to import automatically.
Creating the Necessary Structure:
Before launching PhotoPrism, create the directories on your host machine that will be mapped to the container's volumes. Choose a location for your PhotoPrism data, for example, /opt/photoprism
or ~/photoprism
.
# Choose a base directory (adjust as needed)
PHOTOPRISM_BASE_DIR="/opt/photoprism"
# Or: PHOTOPRISM_BASE_DIR="$HOME/photoprism"
# Create the main data directories
sudo mkdir -p "${PHOTOPRISM_BASE_DIR}/originals"
sudo mkdir -p "${PHOTOPRISM_BASE_DIR}/storage"
sudo mkdir -p "${PHOTOPRISM_BASE_DIR}/import" # Optional
# Set appropriate permissions (adjust if needed, especially if not running as root/docker group)
# This step might be necessary if you encounter permission errors later.
# sudo chown -R your_user:your_group "${PHOTOPRISM_BASE_DIR}"
mkdir -p
: Creates the specified directory and any necessary parent directories without error if they already exist.- We create separate directories for
originals
(where you'll place your source photos) andstorage
(where PhotoPrism keeps its working data). Theimport
directory is optional for now. - Setting permissions (
chown
) might be needed depending on how Docker maps users and groups. If the user running thedocker
command (or thedocker
daemon itself) doesn't have write access to these host directories, PhotoPrism inside the container won't be able to write to thestorage
volume.
The docker-compose.yml
File:
This file defines how Docker should run PhotoPrism. Create a file named docker-compose.yml
inside your chosen base directory (/opt/photoprism
or ~/photoprism
).
# ~/photoprism/docker-compose.yml or /opt/photoprism/docker-compose.yml
version: "3.7" # Specifies the Compose file version
services: # Defines the application's services (containers)
photoprism:
image: photoprism/photoprism:latest # Use the latest official PhotoPrism image
container_name: photoprism # Assign a specific name to the container
restart: unless-stopped # Automatically restart the container unless manually stopped
security_opt: # Improve security
- seccomp:unconfined # Often needed for TensorFlow/AI features
- apparmor:unconfined # May be needed depending on your system's AppArmor profile
depends_on: # Optional: Define dependencies if using external DB (e.g., mariadb)
# - mariadb # Example if using a separate MariaDB service
ports: # Map host ports to container ports (host:container)
- "2342:2342" # Map host port 2342 to the container's web UI port 2342
environment: # Set environment variables for PhotoPrism configuration
# --- Basic Configuration ---
PHOTOPRISM_ADMIN_USER: "admin" # Initial admin username (change later!)
PHOTOPRISM_ADMIN_PASSWORD: "insecure_password" # !! CHANGE THIS !! Set a strong password!
PHOTOPRISM_ORIGINALS_LIMIT: "-1" # Default: 500 GB, -1 = disabled (scan everything in originals)
PHOTOPRISM_HTTP_HOST: "0.0.0.0" # Listen on all network interfaces within the container
PHOTOPRISM_HTTP_PORT: "2342" # Port the PhotoPrism service listens on inside the container
PHOTOPRISM_SITE_URL: "http://YOUR_SERVER_IP:2342/" # !! CHANGE THIS !! URL used for sharing links etc. (use your server's IP or domain)
# --- Database Configuration (Using Built-in SQLite) ---
PHOTOPRISM_DATABASE_DRIVER: "sqlite" # Use the embedded SQLite database
# PHOTOPRISM_DATABASE_DSN: "photoprism?cache=shared&mode=rwc&_journal=WAL&_vacuum=incremental" # Default SQLite DSN (Data Source Name)
# --- Advanced Configuration (Examples - uncomment/adjust as needed) ---
# PHOTOPRISM_READONLY: "false" # false = library can be modified (default)
# PHOTOPRISM_EXPERIMENTAL: "false" # Enable experimental features (use with caution)
# PHOTOPRISM_WORKERS: "0" # Number of workers for indexing/conversion (0 = auto based on CPU cores)
# PHOTOPRISM_DETECT_NSFW: "false" # Automatically flag NSFW content (requires TensorFlow)
# PHOTOPRISM_UPLOAD_NSFW: "true" # Allow upload of potentially NSFW content
# PHOTOPRISM_DEBUG: "false" # Enable debug logging
# PHOTOPRISM_LOG_LEVEL: "info" # Set log level (debug, info, warning, error, fatal, panic)
# TZ: "America/New_York" # !! CHANGE THIS !! Set your timezone, e.g., Europe/Berlin
volumes: # Map host directories/volumes to container directories (host:container)
- "./originals:/photoprism/originals" # Map the 'originals' dir you created
- "./storage:/photoprism/storage" # Map the 'storage' dir for persistent data
# - "./import:/photoprism/import" # Uncomment if you created and want to use the import folder
working_dir: "/photoprism" # Set the working directory inside the container
# Optional: Define networks if needed for complex setups
# networks:
# photoprism_network:
# Optional: Define named volumes if preferred over bind mounts (useful for backups)
# volumes:
# photoprism_originals:
# photoprism_storage:
Key Configuration Points:
image
: Specifies the Docker image to use.photoprism/photoprism:latest
pulls the most recent stable build.restart: unless-stopped
: Ensures the container restarts automatically if it crashes or if the Docker daemon restarts, unless you explicitly stop it.security_opt
: Necessary for certain PhotoPrism features, particularly AI-based classification which might require specific system calls blocked by default security profiles.ports
: Maps port2342
on your host machine to port2342
inside the container. You'll access PhotoPrism viahttp://<your-host-ip>:2342
.environment
: This is crucial for configuring PhotoPrism.PHOTOPRISM_ADMIN_USER
/PHOTOPRISM_ADMIN_PASSWORD
: Change the default password immediately! This sets the initial admin credentials.PHOTOPRISM_SITE_URL
: Must be changed to the actual URL you will use to access PhotoPrism. This is used for generating share links. Use your server's IP address or eventually its domain name.PHOTOPRISM_DATABASE_DRIVER: "sqlite"
: Tells PhotoPrism to use the built-in SQLite database, which will be stored within the/photoprism/storage
volume.TZ
: Important: Set this to your local timezone (e.g.,Europe/London
,America/Los_Angeles
). Find your timezone name usingtimedatectl list-timezones
on most Linux systems. This ensures correct timestamps in PhotoPrism.
volumes
: Maps the host directories you created (./originals
,./storage
) to the corresponding directories inside the container. The./
notation refers to the directory where thedocker-compose.yml
file is located. This is how your photos and PhotoPrism's data persist outside the container.
This docker-compose.yml
file provides a solid starting point for your PhotoPrism instance using the simple embedded database.
Workshop Launching PhotoPrism with Docker Compose
Goal: Launch the PhotoPrism container using the docker-compose.yml
file created previously.
Prerequisites:
- Docker and Docker Compose installed (from the previous workshop).
- The
docker-compose.yml
file created and saved (e.g., in~/photoprism/
or/opt/photoprism/
). - The corresponding
originals
andstorage
directories created on the host. - You have replaced the placeholder values (password, site URL, timezone) in
docker-compose.yml
.
Steps:
-
Navigate to the Compose File Directory: Open a terminal and change to the directory where you saved your
docker-compose.yml
file. -
Pull the PhotoPrism Image: (Optional but good practice) Download the latest PhotoPrism image explicitly. Docker Compose will do this automatically if the image isn't present, but doing it manually gives you more control.
Explanation: This command reads thedocker-compose.yml
file in the current directory, identifies the required images (in this case,photoprism/photoprism:latest
), and downloads them from Docker Hub. -
Start PhotoPrism: Launch the PhotoPrism service(s) defined in your
Explanation:docker-compose.yml
file in detached mode (-d
).docker compose up
: Readsdocker-compose.yml
, creates/starts containers, networks, and volumes as defined. If containers already exist, it might recreate them if the image or configuration has changed.-d
: Detached mode. Runs the containers in the background and prints the new container name(s). Without-d
, logs would be streamed to your terminal, and closing the terminal would stop the containers.
-
Verify Container Status: Check if the PhotoPrism container is running.
Explanation:docker compose ps
: Shows the status of containers managed by the currentdocker-compose.yml
file.docker ps
: Lists all currently running containers on the system. You should see a container namedphotoprism
(or the name you set incontainer_name
) with a status indicating it's "Up" or "Running". Note the port mapping (e.g.,0.0.0.0:2342->2342/tcp
).
-
Check Container Logs (Initial Startup): View the logs generated by the PhotoPrism container to see the startup process and check for any errors.
Explanation:docker compose logs
: Fetches the logs of the services defined in the compose file.-f
: Follow log output. Keeps the log stream open and shows new messages as they arrive. PressCtrl+C
to stop following. Look for messages indicating the web server has started and is listening on port 2342. Initial startup might take a minute or two as PhotoPrism initializes its database and configuration. Ignore warnings aboutPHOTOPRISM_SITE_URL
potentially being insecure if you are using HTTP initially; we'll address HTTPS later.
-
Access PhotoPrism Web UI: Open a web browser on a machine that can reach your server (it could be the server itself if it has a graphical interface, or another computer on the same network). Navigate to:
http://YOUR_SERVER_IP:2342
ReplaceYOUR_SERVER_IP
with the actual IP address of the machine running Docker. Explanation: You are connecting to the port2342
on your host machine, which Docker forwards to port2342
inside the PhotoPrism container where the web server is listening. -
Log In: You should see the PhotoPrism login screen. Use the admin username and password you configured in the
PHOTOPRISM_ADMIN_USER
andPHOTOPRISM_ADMIN_PASSWORD
environment variables in yourdocker-compose.yml
file.
Troubleshooting:
- Connection Refused:
- Verify the container is running (
docker compose ps
). - Check the logs (
docker compose logs
) for errors during startup. - Ensure no firewall on the host machine is blocking port
2342
. (e.g.,sudo ufw status
on Ubuntu). If needed, allow the port:sudo ufw allow 2342/tcp
. - Double-check the IP address you are using.
- Verify the container is running (
- Permission Errors in Logs:
- Stop PhotoPrism:
docker compose down
- Check permissions on the host directories (
originals
,storage
). The user running the Docker container (often root or a specific UID inside the container) needs read/write access tostorage
and read access tooriginals
. You might needsudo chown -R <UID>:<GID> /opt/photoprism/storage
where UID/GID match the user inside the container (PhotoPrism docs sometimes specify this, or you might need to inspect the running container). A simpler, though less secure, approach for initial setup might besudo chmod -R 777 /opt/photoprism/storage
, but avoid this in production. - Restart:
docker compose up -d
- Stop PhotoPrism:
- Container Exits Immediately: Check logs (
docker compose logs photoprism
) for fatal errors, often related to configuration issues (e.g., database connection problems if using MariaDB, invalid environment variables).
Conclusion: You have successfully launched PhotoPrism using Docker Compose. The web interface is accessible, and the basic structure is in place. You are ready to perform the initial configuration within the PhotoPrism UI.
Initial Configuration and User Setup
Once you've successfully logged into the PhotoPrism web interface for the first time using the admin credentials set in your docker-compose.yml
, there are a few initial steps recommended to personalize and secure your instance.
First Login and Welcome: Upon logging in, PhotoPrism might present a welcome message or guide. Take a moment to look around the interface – the main navigation is typically on the left (Search, Browse, Places, People, Labels, Albums, etc.), and settings are accessed via the user menu or a dedicated settings icon (often top right or bottom left).
Essential Initial Settings:
-
Change Admin Password: This is the most critical first step if you used a weak password in
docker-compose.yml
.- Navigate to
Settings
>Account
. - Find the section for changing your password.
- Enter the current password (the one from
docker-compose.yml
) and choose a new, strong, unique password. - Save the changes.
- Navigate to
-
Review Library Settings:
- Navigate to
Settings
>Library
. - Originals Path: Verify it shows
/photoprism/originals
. This confirms the volume mapping is correct. - Storage Path: Verify it shows
/photoprism/storage
. - Read-only Mode: Ensure this is unchecked (
false
) if you want PhotoPrism to be able to write sidecar files (for metadata, RAW conversions) and manage its cache. If checked, the library content cannot be modified by PhotoPrism (useful for specific archival workflows, but not typical initial setup). - Scan Interval: Configure how often PhotoPrism should automatically check the
originals
directory for changes (if automatic scanning is enabled). A value like1h
(1 hour) or6h
(6 hours) is common. Set to0
to disable automatic scanning if you prefer manual indexing. - Workers: Controls the number of concurrent background jobs for tasks like indexing, importing, and generating thumbnails.
0
usually means auto-detect based on CPU cores, which is a good starting point. You might adjust this later based on performance.
- Navigate to
-
Review Upload Settings:
- Navigate to
Settings
>Upload
. - Configure settings related to uploads via the web interface, such as allowed file types or size limits if needed.
- Navigate to
-
Review Search Settings:
- Navigate to
Settings
>Search
. - Here you can enable/disable features like TensorFlow for automatic image classification (tagging based on content) and face recognition.
- Classification: Ensure "Classify" is enabled if you want AI-powered tagging. You might need to download TensorFlow models initially (PhotoPrism usually handles this automatically if enabled).
- Face Recognition: Enable "Detect Faces" and "Recognize Faces" if desired. Note that facial recognition can be CPU-intensive, especially during the initial scan of a large library.
- Navigate to
-
Set Up Map Features (Optional but Recommended):
- Navigate to
Settings
>Maps
. - PhotoPrism can display photos on a world map based on their GPS metadata. To enable map tiles (the visual map background), you often need an API key from a map provider.
- Map Tile Provider: Select a provider (e.g., MapTiler, Mapbox, Stadia Maps). Some offer free tiers suitable for personal use.
- API Key: Follow the instructions for your chosen provider to obtain an API key and enter it here.
- Save the changes. Maps should start working under the "Places" section once photos with GPS data are indexed.
- Navigate to
-
Add More Users (Optional):
- Navigate to
Settings
>Users
. - Click "Add User".
- Define a username, display name, role (e.g.,
viewer
,editor
,admin
), and password. - This allows you to share your library with family or friends with potentially restricted permissions.
- Navigate to
Understanding the Interface:
- Search: The main entry point for finding photos using keywords, dates, locations, etc.
- Browse: View photos chronologically or by folder structure.
- Calendar: View photos grouped by year, month, and day.
- Places: View photos on a map (requires GPS metadata in photos and map provider configured).
- Labels: View automatically generated (AI) or manually added tags/keywords.
- People: View photos grouped by recognized faces (requires face recognition enabled).
- Albums: View manually curated collections of photos.
- Videos: Filter to show only video files.
- Settings: Access all configuration options.
- Library: Trigger manual library scans (Index, Import).
Take some time to click through these sections to familiarize yourself with the layout, even though your library is likely empty at this stage.
Workshop First Steps Inside PhotoPrism
Goal: Log in, change the initial admin password, and explore the basic settings interface.
Prerequisites:
- PhotoPrism running and accessible via
http://YOUR_SERVER_IP:2342
. - The initial admin username and password from your
docker-compose.yml
.
Steps:
- Access PhotoPrism: Open your web browser and navigate to
http://YOUR_SERVER_IP:2342
. - Log In: Enter the
PHOTOPRISM_ADMIN_USER
(e.g.,admin
) and the insecurePHOTOPRISM_ADMIN_PASSWORD
you initially set indocker-compose.yml
. Click "Sign In". - Navigate to Account Settings: Once logged in, locate the settings menu. This is often represented by a gear icon or your username in the top-right or bottom-left corner. Click it and select "Settings". Then, navigate to the "Account" section within Settings.
-
Change Password:
- Find the "Change Password" form.
- Enter the current (insecure) password in the "Current Password" field.
- Enter a new, strong, unique password in the "New Password" field.
- Confirm the new password in the "Verify Password" field.
- Click the "Save" or "Change Password" button. You might be logged out automatically or see a confirmation message. If logged out, log back in with your new password.
- Verification: Ensure you can successfully log in with the new password. This confirms the change was successful.
-
Explore Library Settings:
- Navigate back to "Settings" and select the "Library" section.
- Observe the "Originals Path" and "Storage Path". Confirm they match
/photoprism/originals
and/photoprism/storage
. - Look at the "Scan Interval". Note its current value. You don't need to change it now, but understand its purpose.
- Check the "Read-only" checkbox state (should be unchecked).
- Look at the "Workers" setting. Note the default value (likely 0 for auto).
-
Explore Search Settings:
- Navigate to "Settings" and select the "Search" section.
- Find the options for "Classify" (TensorFlow) and "Detect Faces" / "Recognize Faces". Note whether they are enabled or disabled by default in your setup. You don't need to enable them fully yet, but know where these controls are.
-
Explore Map Settings:
- Navigate to "Settings" and select the "Maps" section.
- See the available "Map Tile Provider" options. Note that an API key is likely required for most. We will configure this in a later workshop.
-
(Optional) Explore User Management:
- Navigate to "Settings" and select the "Users" section.
- Observe the interface for adding new users, even if you don't add one now. Understand that you can create different roles.
-
Log Out: Click your username or the user icon and select "Sign Out".
Conclusion: You have successfully performed the essential initial configuration steps within the PhotoPrism web UI, most importantly securing the admin account with a new password. You have also familiarized yourself with the location of key settings related to the library, search features, maps, and users. Your PhotoPrism instance is now better secured and ready for the next step: adding photos.
2. Importing and Organizing Your First Photos
With PhotoPrism installed and initially configured, the next step is to populate it with your photos. This section explains PhotoPrism's library structure and guides you through different methods of importing your images and performing basic organization using albums and tags.
Understanding PhotoPrism's Library Structure
PhotoPrism maintains a specific directory structure within its storage
volume to manage metadata, cache, and its database. Understanding this structure helps in troubleshooting, backups, and comprehending how PhotoPrism works internally. You primarily interact with the originals
directory and the PhotoPrism UI, but knowing what's happening behind the scenes is beneficial.
Key Directories (Inside the Container):
-
/photoprism/originals
:- Purpose: This is where PhotoPrism looks for your original photo and video files.
- Management: You manage the content of this directory yourself. You place your photos here (or map an existing photo directory on your host to this path).
- PhotoPrism Interaction: By default, PhotoPrism reads from this directory during indexing but does not modify or delete files here. It treats this as the authoritative source. If you enable the
PHOTOPRISM_READONLY=true
setting, PhotoPrism only reads from here.
-
/photoprism/storage
:- Purpose: This directory holds all the data generated and managed by PhotoPrism. This must be persistent and backed up.
- Subdirectories:
cache
: Contains generated thumbnails, preview images of various sizes, temporary files, and index data used for searching. If you delete the contents ofcache
(while PhotoPrism is stopped), PhotoPrism will regenerate it, but this can take a very long time for large libraries.sidecar
: Stores XMP sidecar files. When you edit metadata (like titles, descriptions, keywords, ratings) within PhotoPrism, or when it converts RAW files, it often saves these changes or generated JPEGs into.xmp
or.jpg
files alongside the originals (or in this separate directory, depending on configuration). This approach enables non-destructive editing – your original files remain untouched. Default behavior saves sidecars in this centralstorage/sidecar
directory, mirroring the structure of youroriginals
directory. You can configure PhotoPrism to write sidecars directly into theoriginals
directory if preferred, but this modifies the contents oforiginals
.database
: If using the embedded SQLite database (PHOTOPRISM_DATABASE_DRIVER: "sqlite"
), theindex.sqlite
database file resides here (or within a sub-folder likedb
). This file contains all metadata, file paths, album information, user accounts, settings, etc. Losing this file means losing your entire PhotoPrism library organization (though not the original photos). If using MariaDB, this directory might be empty or contain other configuration.config
: Often contains theoptions.yml
file where PhotoPrism caches its configuration settings. Manually editing this is usually not recommended; prefer environment variables indocker-compose.yml
.import
: If you map a host directory to/photoprism/import
, PhotoPrism can automatically import files placed here, moving them into theoriginals
structure based on date. This directory withinstorage
might be used for temporary staging during the import process.
Relationship between originals
and storage
:
Think of originals
as your physical photo albums and negatives – the pristine source material. Think of storage
as the library's card catalog, index, generated prints (thumbnails), and librarian's notes (metadata changes) – everything needed to manage and access the originals effectively.
- Indexing: When PhotoPrism indexes, it scans
originals
, reads metadata from the files (EXIF, IPTC, XMP), potentially generates AI tags and recognizes faces, and stores all this information in the database (storage/database/index.sqlite
). It also generates various sized thumbnails and previews stored instorage/cache
. - Metadata Edits: When you change a photo's title in PhotoPrism, the change is recorded in the database and potentially written to a
.xmp
sidecar file instorage/sidecar
(or next to the original file if configured differently). The original file remains unchanged. - Display: When you browse photos, PhotoPrism fetches the metadata from the database and displays the appropriate cached thumbnail or preview from
storage/cache
. Clicking to view the full image might load the original file directly fromoriginals
or a generated preview depending on the file type and configuration.
Understanding this separation is key: back up both your originals
and the storage
volume regularly! Losing originals
means losing your photos. Losing storage
means losing your PhotoPrism organization, edits, and generated data (requiring a full re-index).
Workshop Preparing Your Photo Collection
Goal: Organize a small batch of photos on your host machine, ready to be placed into the PhotoPrism originals
directory.
Prerequisites:
- Access to the host machine where PhotoPrism is running (or where you will mount the
originals
volume from). - A small collection of sample photos (e.g., 10-20 JPEGs, maybe a RAW file or a short video if you have them). You can use personal photos or download some copyright-free sample images from sites like Unsplash or Pexels.
Steps:
-
Locate Host
originals
Directory: Identify the directory on your host machine that is mapped to/photoprism/originals
in yourdocker-compose.yml
. In our example setup, this was likely/opt/photoprism/originals
or~/photoprism/originals
. Let's assume it's/opt/photoprism/originals
. -
Gather Sample Photos: Collect your sample photos (JPEGs, PNGs, maybe a .CR2, .NEF, .MP4, .MOV file) into a temporary location on your computer (e.g.,
~/sample_photos
). -
Choose an Organization Strategy (Optional but Recommended): Decide how you want to organize photos within the
originals
directory. PhotoPrism is flexible, but common strategies include:- Year/Month:
/opt/photoprism/originals/2023/11/photo1.jpg
- Chronological (YYYY-MM-DD):
/opt/photoprism/originals/2023-11-21_holiday_photo.jpg
- Event/Topic:
/opt/photoprism/originals/Vacations/Italy_2023/IMG_001.jpg
PhotoPrism primarily uses metadata for organization, but a logical folder structure inoriginals
can be helpful for manual access or migration later. For this workshop, let's use a simple Year/Month structure.
- Year/Month:
-
Create Subdirectories: Inside your host
originals
directory, create a structure for your sample photos. For example, if your photos are from November 2023:Explanation: We create the# Navigate to the base directory containing 'originals' cd /opt/photoprism # Or cd ~/photoprism # Create the year and month directories within 'originals' sudo mkdir -p originals/2023/11
2023
directory and the11
subdirectory within it inside theoriginals
folder.sudo
is likely needed if you created/opt/photoprism
as root. Adjust ownership/permissions if necessary:sudo chown -R $USER:$USER originals/2023
(replace$USER
if needed). -
Copy Photos into the Structure: Copy your sample photos from your temporary location (
Explanation: This copies all files from~/sample_photos
) into the newly created directory structure withinoriginals
.~/sample_photos
into theoriginals/2023/11/
directory. Usesudo
if required due to permissions on theoriginals
directory. If you only want to copy specific files, list them individually. -
Verify File Placement: List the files in the target directory to ensure they were copied correctly.
Explanation:ls -lh
lists files in long format (-l
) with human-readable sizes (-h
). You should see your sample photos listed. -
Check Permissions (Crucial): Ensure the files you just copied are readable by the PhotoPrism container. The simplest way (though not always ideal for security long-term) is to ensure they are world-readable, or readable by the group the Docker process runs as. Often, the user/group inside the PhotoPrism container needs read access.
Explanation: Permission issues are common. PhotoPrism running inside Docker needs permission to read these files on the host system via the volume mount. If PhotoPrism later fails to index these files, permissions are a likely culprit. The# Example: Make files readable by everyone (use with caution) # sudo chmod -R a+r originals/2023/11 # Better: Ensure the owner/group has read access (adjust owner/group if needed) # ls -l originals/2023/11 # Check current permissions # sudo find originals/2023/11 -type f -exec chmod 644 {} \; # Sets rw-r--r-- for files # sudo find originals/2023/11 -type d -exec chmod 755 {} \; # Sets rwxr-xr-x for directories
find
commands provide a more granular way to set read permissions for files and execute/search permissions for directories, which is generally preferred overchmod 777
.
Conclusion: You have prepared a small set of sample photos and placed them into the designated originals
directory on your host machine, using a simple organizational structure. These files are now ready to be recognized and processed by PhotoPrism.
Importing Methods (Web UI Upload, Indexing)
PhotoPrism offers several ways to get your photos into its library. The two primary methods for users are:
-
Indexing:
- How it works: You place your photos directly into the
originals
directory structure on the host machine (as done in the previous workshop). Then, you instruct PhotoPrism to scan this directory. PhotoPrism reads the metadata, generates thumbnails/sidecars (in thestorage
volume), and adds the photos to its database index. The original files remain in place in theoriginals
directory. - Pros:
- Best for large, existing collections.
- Preserves your chosen folder structure within
originals
. - Integrates well with automated workflows (e.g., syncing photos from your phone to the
originals
directory). - Generally faster for bulk imports compared to uploading one by one.
- Cons:
- Requires access to the server's filesystem to place the files.
- Initial indexing can be time-consuming and resource-intensive for very large libraries.
- Triggering:
- Manual: Click the "Library" icon/menu in the PhotoPrism UI, then choose "Index" > "Start". You can choose a full scan or scan specific folders.
- Automatic: If configured in
Settings > Library > Scan Interval
, PhotoPrism will periodically scan for changes automatically. - Command Line: You can use
docker compose exec photoprism photoprism index
for advanced scripting.
- How it works: You place your photos directly into the
-
Web UI Upload:
- How it works: You use the "Upload" button within the PhotoPrism web interface to select photos directly from the computer you are browsing from. PhotoPrism uploads these files to the server. By default, uploaded files are typically moved into the
originals
directory, organized into subfolders based on the photo's date (e.g.,originals/YYYY/MM/
). - Pros:
- Easy to use for adding a few new photos without direct server access.
- Convenient for users who only interact via the web UI.
- PhotoPrism handles placing the file in the
originals
structure automatically.
- Cons:
- Less efficient for importing thousands of photos due to browser limitations and HTTP overhead.
- Upload speed is limited by your network connection to the server.
- Gives you less control over the exact folder structure within
originals
(though PhotoPrism's date-based organization is sensible).
- Triggering: Click the "Upload" button (often a cloud icon or plus sign) in the PhotoPrism UI, select files, and start the upload. Uploaded files are typically indexed automatically shortly after the upload completes.
- How it works: You use the "Upload" button within the PhotoPrism web interface to select photos directly from the computer you are browsing from. PhotoPrism uploads these files to the server. By default, uploaded files are typically moved into the
-
Import Folder (Hybrid):
- How it works: You map a dedicated
import
directory on your host to/photoprism/import
indocker-compose.yml
. You place files into this hostimport
directory. PhotoPrism monitors this folder. When new files appear, it moves them into theoriginals
directory (organized by date) and indexes them. Theimport
folder is then left empty. - Pros:
- Good for automated workflows where external tools drop files into a specific location.
- Combines filesystem access with PhotoPrism's automatic organization and indexing.
- Cons:
- Files are moved, not copied, from the import source.
- Requires setting up the
import
volume mapping.
- Triggering:
- Manual: Click "Library" > "Import" > "Start".
- Automatic: Can be configured to run periodically (
Settings > Library > Import Interval
).
- How it works: You map a dedicated
Which method to choose?
- For your initial bulk import of existing photos, Indexing is almost always the best choice.
- For adding a few new photos occasionally, the Web UI Upload is very convenient.
- For automated syncing from phones or cameras (using other tools), having them sync directly to the
originals
directory and relying on Indexing (manual or automatic) is common. Alternatively, syncing to theimport
directory can also work if the moving behavior is acceptable.
For this guide, we'll focus on Indexing first, as it leverages the photos prepared in the previous workshop.
Workshop Importing Photos via Indexing
Goal: Use PhotoPrism's indexing feature to add the prepared sample photos to the library.
Prerequisites:
- PhotoPrism running and accessible.
- Admin user logged into the PhotoPrism web UI.
- Sample photos placed in the host
originals
directory (e.g.,/opt/photoprism/originals/2023/11/
) which is mapped to/photoprism/originals
in the container. - Ensure PhotoPrism has read permissions for these files.
Steps:
-
Navigate to Library Section: In the PhotoPrism web UI, find the main navigation menu (usually on the left). Click on "Library" or an icon representing the library/indexing functions. This might also be under a "Settings" submenu depending on the UI version. Look for options like "Index", "Import", "Scan".
-
Initiate Indexing:
- Within the "Library" section, locate the "Index" options.
- You might see options for a "Full Rescan" or to scan specific paths. For the first import, a standard "Index" or "Full Rescan" is appropriate.
- Click the "Start" button for indexing.
-
Monitor Indexing Progress:
- PhotoPrism will likely show a progress indicator or status message indicating that indexing is running. This might appear as a notification, a spinning icon, or progress bars in the "Library" or "Jobs" section (often found under Settings).
- For a small number of photos (10-20), indexing should be relatively quick (seconds to a minute or two), but this depends heavily on your server's resources (CPU, disk speed) and whether AI features (classification, face detection) are enabled.
- You can also monitor the container logs for more detailed progress:
Look for messages related to scanning folders, finding files, extracting metadata, generating thumbnails, and eventually an "index: done" or similar message. Press
Ctrl+C
to stop following logs.
-
Verify Photos Appear:
- Once indexing is complete (the progress indicator finishes, or logs show completion), navigate to the "Browse" or "Search" section in the PhotoPrism UI.
- Your sample photos should now appear. You might see thumbnails displayed chronologically.
- Click on a photo thumbnail to view it larger.
-
Explore Metadata:
- While viewing a single photo, look for a details pane or an "Info" / "Edit" tab/button (often an 'i' icon or pencil icon).
- Explore the information PhotoPrism has extracted:
- File: Filename, path (e.g.,
/originals/2023/11/your_photo.jpg
), size, date taken. - Details: Camera model, exposure settings (aperture, shutter speed, ISO), resolution.
- Location: If the photo had GPS coordinates, you might see a small map or location name (requires map settings configured).
- Labels: If classification is enabled, you might see automatically generated tags (e.g., "nature", "sky", "building"). This might take longer to appear as classification runs in the background.
- People: If face detection is enabled, you might see regions marked as potential faces.
- File: Filename, path (e.g.,
Troubleshooting:
- Photos Not Appearing:
- Double-check that indexing actually completed (check logs/status).
- Permissions: This is the most common issue. Stop PhotoPrism (
docker compose down
), verify again that the files/directories in your hostoriginals
path are readable by the PhotoPrism process inside the container. Usels -l
on the host and consider adjusting permissions (chmod
orchown
). Restart PhotoPrism (docker compose up -d
) and try indexing again. - Volume Mapping: Verify the
volumes
section in yourdocker-compose.yml
correctly maps your hostoriginals
directory to/photoprism/originals
inside the container. - File Types: Ensure the files are in supported formats (common image and video formats usually are). Check PhotoPrism documentation for a list of supported types.
- Indexing Stuck or Very Slow:
- Check server resources (CPU, RAM, disk I/O) using tools like
htop
ordocker stats
on the host. Indexing, especially with AI features, can be demanding. - Check PhotoPrism logs (
docker compose logs photoprism
) for specific errors or repeated warnings. - Consider adjusting the number of
PHOTOPRISM_WORKERS
indocker-compose.yml
if resource contention seems to be an issue (might require stopping and restarting PhotoPrism:docker compose down && docker compose up -d
).
- Check server resources (CPU, RAM, disk I/O) using tools like
Conclusion: You have successfully used PhotoPrism's indexing feature to scan your originals
directory and bring your first batch of photos into the library. You can now browse them and see the basic metadata PhotoPrism has extracted.
Basic Tagging and Albums
While PhotoPrism excels at automatic organization (chronological, location, AI labels, faces), manual organization using Albums and Tags (Labels) is essential for creating meaningful collections and improving searchability based on your own criteria.
Labels (Tags/Keywords):
- Purpose: Labels are keywords or tags you can assign to photos to categorize them (e.g., "Vacation", "Family", "Birthday", "Project X", "Landscape", "Architecture"). They complement the automatic AI labels.
- How they work: Labels are stored in PhotoPrism's database and optionally written to XMP sidecar files. You can add multiple labels to a single photo.
- Benefits: Allows you to find photos based on themes, events, or subjects that AI might not capture or that are specific to your context. Searching for "Label:Vacation" will quickly find all photos you've tagged.
- Adding/Editing Labels:
- Single Photo View: When viewing a single photo, open the Edit/Info pane. There's usually a "Labels" section where you can type new labels (press Enter or comma after each) or select existing ones.
- Batch Editing: In the Search/Browse view, select multiple photos (click the checkmark on thumbnails). An action bar will appear (usually at the top or bottom). Click the "Edit" or "Labels" icon, and you can add/remove labels for all selected photos simultaneously.
- Viewing by Label: Navigate to the "Labels" section in the main menu to see all available labels and click on one to view associated photos.
Albums:
- Purpose: Albums are curated collections of specific photos, often representing an event, a trip, or a theme (e.g., "Italy Trip 2023", "Sarah's Wedding", "Best Sunsets"). Unlike labels (which categorize), albums group specific sets of photos together in a defined order.
- How they work: Albums are essentially ordered lists of photo identifiers stored in the PhotoPrism database. A photo can belong to multiple albums.
- Benefits: Perfect for storytelling, sharing specific events, or creating portfolios. You control exactly which photos are included and in what order.
- Creating Albums:
- From Selection: Select one or more photos in the Search/Browse view. Use the action bar that appears and choose "Add to Album". You can add to an existing album or create a new one by typing its name.
- From Album Section: Navigate to the "Albums" section in the main menu. Click "Create Album" or a similar button. Give the album a name and description. Then, you can add photos to it (often via a search/select interface within the album view).
- Managing Albums: In the "Albums" section, you can view, edit (rename, change description, reorder photos), share (generate public links if enabled), or delete albums. Reordering photos is usually done by drag-and-drop within the album's edit mode.
Labels vs. Albums:
- Use Labels for broad categorization and searchability (What is this photo about?).
- Use Albums for specific, curated collections (Which photos belong together for this event/story?).
Combining both provides a powerful way to organize. You might label all photos from a trip with "Vacation" and "Italy", then create a specific Album called "Best of Rome" containing only the highlights.
Workshop Creating Your First Album and Tags
Goal: Apply manual organization to your sample photos by adding labels and creating an album.
Prerequisites:
- PhotoPrism running with your sample photos indexed and visible in the UI.
- Logged in as the admin user.
Steps:
-
Select Photos for Labeling:
- Navigate to the "Search" or "Browse" view where your sample photos are displayed.
- Hover over the thumbnails of 2-3 photos you want to label (e.g., photos that have buildings in them). Click the checkmark icon that appears on hover to select them.
- An action bar should appear at the top or bottom of the screen indicating the number of selected photos and available actions.
-
Add a Label (Batch Edit):
- In the action bar, find the "Edit" or "Labels" button (often a pencil or tag icon). Click it.
- A dialog or panel will appear for editing selected items. Find the "Labels" field.
- Type a new label, for example,
Architecture
. Press Enter or comma. - Type another label, maybe
Test Batch
. Press Enter or comma. - Click "Save" or "Apply".
-
Verify Labels on a Single Photo:
- Deselect all photos (click outside or find a "Deselect All" option).
- Click on one of the photos you just labeled to open it in the single photo view.
- Open the Info/Edit pane (usually an 'i' or pencil icon).
- Look at the "Labels" section. You should see
Architecture
andTest Batch
listed.
-
Add a Label to a Different Single Photo:
- Navigate to another photo (one you didn't label
Architecture
). - Open its Info/Edit pane.
- In the "Labels" field, type a different label, e.g.,
Sample Image
. Press Enter. - Save the changes for this single photo.
- Navigate to another photo (one you didn't label
-
Explore the Labels Section:
- Navigate to the "Labels" section using the main menu on the left.
- You should now see your created labels listed (e.g.,
Architecture
,Test Batch
,Sample Image
), possibly alongside any AI-generated labels. - Click on the
Architecture
label. You should see only the photos you tagged with this label. - Click on the
Test Batch
label. You should see all the photos you tagged with that label.
-
Select Photos for an Album:
- Go back to the "Search" or "Browse" view.
- Select 4-5 of your sample photos by clicking their checkmarks.
-
Create a New Album:
- With the photos selected, find the "Add to Album" button in the action bar (often an album or plus icon). Click it.
- A dialog will appear asking you to select an existing album or create a new one.
- In the field for the album name, type
My First Album
. - Click the option to "Create" or "Add" to this new album.
-
Explore the Albums Section:
- Navigate to the "Albums" section using the main menu.
- You should see "My First Album" listed. Click on it.
-
View and Manage the Album:
- Inside the album view, you should see the 4-5 photos you selected.
- Look for options to edit the album (e.g., a pencil icon). Click it.
- Try changing the album description (add something like "Sample photos from the initial import").
- Try reordering the photos within the album by dragging and dropping their thumbnails (if the interface supports it in edit mode).
- Save the changes to the album.
Conclusion: You have successfully applied custom organization to your photos using both labels for categorization and an album for creating a specific, curated collection. This demonstrates the basic manual organization tools available in PhotoPrism, complementing its automatic features.
(Intermediate Level Sections Follow)
3. Enhancing Your PhotoPrism Experience
Now that you have PhotoPrism running and know how to import and perform basic organization, let's move on to intermediate topics. This section focuses on securing access to your PhotoPrism instance using a reverse proxy, understanding metadata in more detail, and leveraging PhotoPrism's powerful search capabilities.
Reverse Proxy Setup for Secure Access
Running PhotoPrism directly exposed on its port (2342
) is fine for initial testing on a trusted local network. However, for secure access, especially if you plan to access it from the internet, using a reverse proxy is highly recommended, practically essential.
What is a Reverse Proxy? A reverse proxy is a server that sits in front of one or more web servers (like PhotoPrism), intercepting requests from clients (your browser) and forwarding them to the appropriate backend server. To the client, it appears as if they are directly communicating with the reverse proxy itself.
Why Use a Reverse Proxy with PhotoPrism?
- HTTPS/SSL/TLS Encryption: This is the primary reason. A reverse proxy can handle the termination of SSL/TLS connections. This means communication between your browser and the reverse proxy is encrypted (HTTPS), protecting your login credentials and photo data from eavesdropping, especially over public Wi-Fi. The connection between the reverse proxy and PhotoPrism (running in Docker on the same machine) can remain unencrypted HTTP, simplifying PhotoPrism's configuration. The reverse proxy manages the SSL certificates.
- Centralized Access Point: If you host multiple web services on the same server, a reverse proxy can direct traffic based on domain names (e.g.,
photos.yourdomain.com
goes to PhotoPrism,notes.yourdomain.com
goes to another service), all using the standard web ports (80 for HTTP, 443 for HTTPS). This avoids needing to remember different port numbers for each service. - Load Balancing: For high-traffic sites, a reverse proxy can distribute requests across multiple instances of an application (not typically needed for personal PhotoPrism but a standard proxy feature).
- Caching: Proxies can cache static content (like images, CSS, JavaScript), potentially speeding up access and reducing load on the backend service.
- Security Enhancements: Proxies can provide an additional layer of security, offering features like rate limiting, blocking malicious IPs, or integrating with web application firewalls (WAFs).
- Simplified Configuration: Managing SSL certificates and domain routing in one place (the proxy) is often easier than configuring it within each individual application.
Popular Reverse Proxy Choices for Self-Hosting:
- Nginx: A powerful, high-performance web server and reverse proxy. Very popular and well-documented, but configuration can be manual via text files.
- Apache: Another stalwart web server that can function as a reverse proxy (
mod_proxy
). Configuration is also via text files. - Traefik: A modern reverse proxy specifically designed for containerized environments. It can automatically discover services running in Docker and configure routing and SSL certificates (using Let's Encrypt) based on container labels. Steeper initial learning curve but highly automated once set up.
- Caddy: A modern web server with automatic HTTPS configuration (using Let's Encrypt) built-in. Known for its simple configuration file format.
- Nginx Proxy Manager (NPM): A Docker-based application that provides a web UI for managing Nginx reverse proxy configurations, including SSL certificate management with Let's Encrypt. Excellent choice for beginners as it avoids manual Nginx config file editing.
General Setup Steps (Conceptual):
- Choose and Install Proxy: Decide which proxy you want to use. We'll use Nginx Proxy Manager in the workshop as it's user-friendly. You'd typically run the proxy as another Docker container.
- Obtain a Domain Name (Optional but Recommended for HTTPS): For automatic HTTPS using Let's Encrypt, you need a publicly accessible domain name (e.g.,
myphotos.example.com
) pointing to your server's public IP address. Dynamic DNS services (like DuckDNS, No-IP) can be used if you have a dynamic home IP. - Configure DNS: Point your chosen domain or subdomain to your server's public IP address.
- Configure Port Forwarding: On your router, forward ports 80 (for HTTP validation) and 443 (for HTTPS) to the internal IP address of the machine running the reverse proxy. Do not forward port 2342 directly anymore.
- Configure Proxy:
- Tell the proxy to listen for requests for your domain (e.g.,
photos.yourdomain.com
). - Configure it to forward these requests to PhotoPrism's internal Docker IP address and port (e.g.,
http://photoprism:2342
). Docker Compose networks make this easy, as you can often use the service name (photoprism
) as the hostname. - Configure the proxy to obtain and manage an SSL certificate for your domain (using Let's Encrypt).
- Tell the proxy to listen for requests for your domain (e.g.,
- Update PhotoPrism Configuration: Change
PHOTOPRISM_SITE_URL
in yourdocker-compose.yml
to the new HTTPS URL (e.g.,https://photos.yourdomain.com
). Restart PhotoPrism. - Access via HTTPS: Access PhotoPrism using
https://photos.yourdomain.com
.
Using a reverse proxy like Nginx Proxy Manager significantly enhances the security and usability of your self-hosted PhotoPrism instance.
Workshop Securing PhotoPrism with a Reverse Proxy and HTTPS
Goal: Set up Nginx Proxy Manager (NPM) as a reverse proxy in Docker to provide secure HTTPS access to PhotoPrism using a free Let's Encrypt certificate.
Prerequisites:
- PhotoPrism running via Docker Compose.
- Docker and Docker Compose installed.
- A publicly accessible domain name (or subdomain) pointing to your server's public IP address. (e.g.,
myphotos.duckdns.org
,photoprism.yourdomain.com
). You can get a free domain from services like DuckDNS or Freenom, or use a domain you own. - Ports 80 and 443 forwarded from your router to the internal IP address of the machine running Docker/NPM. Remove any existing port forwarding for port 2342.
- Your PhotoPrism
docker-compose.yml
file.
Steps:
-
Create NPM Data Directory and Compose File: Choose a location for NPM's configuration and data, separate from PhotoPrism's.
Create adocker-compose.yml
file for NPM in/opt/npm
:Explanation:# /opt/npm/docker-compose.yml version: "3.7" services: app: image: 'jc21/nginx-proxy-manager:latest' container_name: npm-app restart: unless-stopped ports: # Public HTTP Port: - '80:80' # Public HTTPS Port: - '443:443' # Admin Web Port: - '81:81' # Map host port 81 to container port 81 for the admin UI environment: # SQLite is recommended for personal use DB_SQLITE_FILE: "/data/database.sqlite" # Uncomment this if IPv6 is not enabled on your host # DISABLE_IPV6: 'true' volumes: - ./data:/data # Persists configuration, database - ./letsencrypt:/etc/letsencrypt # Persists SSL certificates # Optional: Add to a common network with PhotoPrism if they are in separate compose files networks: - proxy-network # Use a custom network # Optional: Define the custom network networks: proxy-network: name: proxy-network # Explicitly name the network
- We map ports 80 and 443 (standard web ports) from the host to the NPM container. These will handle incoming traffic for your proxied services.
- We map port
81
on the host to81
in the container. This is used to access the NPM admin interface. Choose a different host port if 81 is already in use (e.g.,- '8181:81'
). - Volumes are created to persist NPM's configuration (
data
) and SSL certificates (letsencrypt
). - We define a custom Docker network
proxy-network
. This allows NPM to easily communicate with other containers (like PhotoPrism) attached to the same network, using their service names as hostnames.
-
Modify PhotoPrism's
docker-compose.yml
: Edit your PhotoPrismdocker-compose.yml
file (/opt/photoprism/docker-compose.yml
or~/photoprism/docker-compose.yml
) to:- Remove Port Mapping: Comment out or delete the
ports
section for thephotoprism
service. NPM will handle external access. - Add to Network: Add the
photoprism
service to theproxy-network
. - Update
PHOTOPRISM_SITE_URL
: Change it to your final HTTPS URL. - Declare External Network: Tell Compose that
proxy-network
is defined externally (in the NPM compose file).
# /opt/photoprism/docker-compose.yml or ~/photoprism/docker-compose.yml version: "3.7" services: photoprism: image: photoprism/photoprism:latest container_name: photoprism restart: unless-stopped security_opt: - seccomp:unconfined - apparmor:unconfined # depends_on: # - mariadb # ports: # <-- REMOVE OR COMMENT OUT THIS SECTION # - "2342:2342" environment: PHOTOPRISM_ADMIN_USER: "admin" PHOTOPRISM_ADMIN_PASSWORD: "YOUR_STRONG_SECURE_PASSWORD" # Use the one you set! PHOTOPRISM_ORIGINALS_LIMIT: "-1" PHOTOPRISM_HTTP_HOST: "0.0.0.0" PHOTOPRISM_HTTP_PORT: "2342" # !! UPDATE THIS !! Use your domain and https PHOTOPRISM_SITE_URL: "https://photoprism.yourdomain.com/" PHOTOPRISM_DATABASE_DRIVER: "sqlite" # PHOTOPRISM_DATABASE_DSN: "photoprism?cache=shared&mode=rwc&_journal=WAL&_vacuum=incremental" # TZ: "America/New_York" # Keep your timezone volumes: - "./originals:/photoprism/originals" - "./storage:/photoprism/storage" # - "./import:/photoprism/import" working_dir: "/photoprism" networks: # <-- ADD THIS - proxy-network # Add PhotoPrism container to the shared network networks: # <-- ADD THIS proxy-network: external: true # Declare that this network is created elsewhere (by NPM's compose) name: proxy-network # Specify the exact name
- Remove Port Mapping: Comment out or delete the
-
Start/Restart Services:
- Start NPM:
- Restart PhotoPrism (to apply network and port changes):
- Verification: Check both are running and attached to the network:
-
Access NPM Admin UI: Open your browser and navigate to the NPM admin interface using the host IP and the admin port you mapped (e.g.,
http://YOUR_SERVER_IP:81
). -
NPM Initial Login:
- Default Admin User:
admin@example.com
- Default Password:
changeme
- Log in, and immediately change the admin username and password as prompted.
- Default Admin User:
-
Add Proxy Host for PhotoPrism:
- In the NPM UI, navigate to
Hosts
>Proxy Hosts
. - Click
Add Proxy Host
. - Details Tab:
- Domain Names: Enter your public domain name (e.g.,
photoprism.yourdomain.com
). - Scheme:
http
(because NPM talks to PhotoPrism via HTTP internally). - Forward Hostname / IP: Enter the service name of your PhotoPrism container as defined in its
docker-compose.yml
. This is typicallyphotoprism
. Docker's networking allows containers on the same network to resolve each other by service name. - Forward Port: Enter the port PhotoPrism listens on inside the container, which is
2342
. - Cache Assets: You can enable this for potential performance improvement.
- Block Common Exploits: Recommended to enable this.
- Websockets Support: Enable this, as PhotoPrism might use websockets.
- Domain Names: Enter your public domain name (e.g.,
- SSL Tab:
- SSL Certificate: Select
Request a new SSL Certificate
. - Force SSL: Enable this to automatically redirect HTTP requests to HTTPS.
- HTTP/2 Support: Enable this for better performance.
- Email Address for Let's Encrypt: Enter your valid email address (Let's Encrypt uses this for renewal reminders).
- I Agree: Check the box to agree to the Let's Encrypt Terms of Service.
- Click
Save
.
- SSL Certificate: Select
- In the NPM UI, navigate to
-
Wait for Certificate Issuance: NPM will now attempt to contact Let's Encrypt to obtain a certificate. This requires ports 80/443 to be correctly forwarded and your domain's DNS to be propagated. You should see the status change in the NPM UI. It might take a minute or two. If it fails, double-check DNS, port forwarding, and firewall rules. Check the NPM container logs (
docker compose logs -f app
in/opt/npm
) for detailed error messages. -
Access PhotoPrism via HTTPS: Once the SSL certificate is successfully obtained and the host is active in NPM, open your browser and navigate to your secure PhotoPrism URL:
https://photoprism.yourdomain.com
(use your actual domain).- You should see the PhotoPrism login page, served over HTTPS (look for the padlock icon in your browser's address bar).
- Log in as usual.
Troubleshooting:
- NPM UI Inaccessible: Check NPM container logs (
docker compose logs app
in/opt/npm
), verify port mapping (81
or your chosen port), check host firewall. - SSL Certificate Failure:
- DNS: Use
nslookup photoprism.yourdomain.com
(from an external network if possible) to verify it resolves to your correct public IP. DNS propagation can take time. - Port Forwarding: Ensure ports 80 and 443 are forwarded correctly to the host running NPM, and not blocked by a firewall on the host or router. Let's Encrypt needs to reach your server on these ports.
- Rate Limits: Let's Encrypt has rate limits. If you try too many times too quickly, you might be temporarily blocked. Check NPM logs.
- DNS: Use
- 502 Bad Gateway Error: This usually means NPM can reach the proxy host, but the proxy cannot reach the backend service (PhotoPrism).
- Network: Verify both NPM and PhotoPrism containers are running and attached to the same Docker network (
proxy-network
). Usedocker network inspect proxy-network
. - Hostname: Double-check you used the correct service name (
photoprism
) as the "Forward Hostname" in NPM. - Port: Ensure the "Forward Port" in NPM matches the internal port PhotoPrism listens on (
2342
). - PhotoPrism Status: Check if the PhotoPrism container is running and healthy (
docker compose ps
in the PhotoPrism directory,docker compose logs photoprism
).
- Network: Verify both NPM and PhotoPrism containers are running and attached to the same Docker network (
Conclusion: You have successfully configured Nginx Proxy Manager to act as a reverse proxy for PhotoPrism, enabling secure HTTPS access with a valid Let's Encrypt certificate. This significantly improves the security and professionalism of your PhotoPrism setup. Remember to keep NPM updated (docker compose pull
and docker compose up -d
in /opt/npm
periodically).
Understanding Metadata (EXIF, XMP) and Sidecar Files
Metadata is "data about data." In the context of digital photos, it refers to information embedded within the image file or stored in accompanying files that describes the photo, such as camera settings, location, date, keywords, and much more. PhotoPrism heavily relies on metadata for organizing, searching, and displaying your photos.
Common Metadata Standards:
-
EXIF (Exchangeable Image File Format):
- Origin: Primarily generated by digital cameras and smartphones at the time of capture.
- Content: Stores technical details about the image capture process. Common fields include:
- Camera make and model
- Date and time taken (often crucial for sorting)
- Exposure settings (shutter speed, aperture, ISO)
- Focal length
- Flash information
- GPS coordinates (if the camera/phone has GPS enabled)
- Orientation (which way is up)
- Thumbnail image
- Storage: Embedded directly within JPEG, TIFF, and some RAW file formats.
- Modification: While some tools can modify EXIF data, it's often considered best practice to leave the original capture information intact.
-
IPTC (International Press Telecommunications Council):
- Origin: Developed for the news industry to describe and manage photos.
- Content: Focuses on descriptive information, rights management, and administrative details. Common fields include:
- Title/Headline
- Caption/Description
- Keywords (tags)
- Creator/Photographer
- Copyright information
- Location (City, State, Country)
- Source/Credit
- Storage: Can be embedded within JPEG and TIFF files.
-
XMP (Extensible Metadata Platform):
- Origin: Developed by Adobe, designed to be extensible and standardize metadata embedding across different file types and applications.
- Content: Can store information from EXIF and IPTC standards, plus much more. It's highly flexible and allows for custom metadata schemas. It's the preferred standard for storing user-added metadata like:
- Keywords/Tags (often synchronizing with IPTC keywords)
- Ratings (e.g., 1-5 stars)
- Color labels
- Titles, descriptions
- Face regions (coordinates and names)
- Hierarchical keywords
- Edit history (in some applications)
- Storage: Can be embedded directly in formats like JPEG, TIFF, PSD, DNG, PDF, and some video formats. Crucially, it can also be stored in a separate
.xmp
file (a "sidecar" file) alongside the original image.
Sidecar Files (.xmp):
- Purpose: When working with file formats that cannot embed XMP directly (like many proprietary RAW formats - .CR2, .NEF, etc.) or when you want to ensure the original file remains absolutely untouched (non-destructive workflow), metadata changes are saved to a separate text-based XMP file.
- Naming: The sidecar file typically has the same base name as the original image file but with an
.xmp
extension (e.g.,IMG_1234.CR2
andIMG_1234.xmp
). - PhotoPrism and Sidecars:
- By default (
PHOTOPRISM_READONLY=false
), when you edit metadata (title, labels, description, etc.) in PhotoPrism, it saves this information in its database and typically writes it to an XMP sidecar file. - Location: PhotoPrism usually stores these sidecar files in the
/photoprism/storage/sidecar
directory, mirroring the folder structure of youroriginals
. This keeps youroriginals
directory clean. PHOTOPRISM_WRITE_SIDECARS: "true"
(default) enables writing sidecars.PHOTOPRISM_SIDECAR_PATH: "sidecar"
(default) uses the central storage location. Setting it to"originals"
would write sidecars next to the original files.- Reading Sidecars: During indexing, PhotoPrism reads metadata not only from the image file itself (EXIF, embedded IPTC/XMP) but also looks for corresponding
.xmp
sidecar files. Information from the sidecar often takes precedence over embedded metadata if there are conflicts, especially for fields like keywords and ratings.
- By default (
- Benefits of Sidecars:
- Non-Destructive: Your original image files are never modified.
- Compatibility: XMP is a widely supported standard. Metadata added in PhotoPrism can potentially be read by other software like Adobe Lightroom, Darktable, digiKam, etc., if they have access to both the original and the sidecar file.
- Works with RAW: Essential for adding metadata to many RAW file types.
How PhotoPrism Uses Metadata:
- Timeline/Sorting: Uses the
DateTimeOriginal
(EXIF) or similar date fields to place photos on the timeline and in the Calendar view. It has sophisticated logic to find the best available date/time field. - Places/Map: Uses embedded GPS coordinates (EXIF) to plot photos on the map. It can also use reverse geocoding services (if configured) to find place names based on coordinates.
- Camera/Technical Info: Displays EXIF information like camera model, lens, exposure settings in the photo details view.
- Labels/Keywords: Reads existing keywords from IPTC/XMP (embedded or sidecar) and allows you to add new ones (saved to database and sidecar). TensorFlow AI labels are stored internally.
- Search: You can search based on almost any metadata field (date, camera, keyword, location, title, etc.).
Understanding metadata and how PhotoPrism interacts with it (especially via sidecar files) is key to maintaining a well-organized and interoperable photo library.
Workshop Exploring and Editing Metadata
Goal: Examine the metadata of your sample photos within PhotoPrism and practice editing metadata fields, observing the potential creation or modification of sidecar files.
Prerequisites:
- PhotoPrism running, secured via NPM (optional but recommended).
- Sample photos indexed in PhotoPrism.
- Access to the PhotoPrism web UI.
- (Optional but helpful) Terminal access to the host machine to inspect the
storage/sidecar
directory.
Steps:
-
View Existing Metadata:
- Log into PhotoPrism via your secure URL (
https://photoprism.yourdomain.com
). - Navigate to "Search" or "Browse".
- Click on one of your sample photos (preferably a JPEG from a digital camera or phone, as they usually have rich EXIF data).
- Open the Info/Edit pane (look for an 'i' icon, pencil icon, or a sidebar).
- Examine the Sections:
- File: Note the filename, path (
/originals/...
), date added/modified. - Details: Look for Camera Make/Model, Lens, Shutter Speed, Aperture, ISO, Focal Length, Resolution, Date Taken. Observe how much information your camera recorded.
- Location: If the photo had GPS data, you might see a map or coordinates here. If not, it will likely be empty or show "Unknown Location".
- Labels: Note any existing labels (manual ones like
Test Batch
or potential AI labels if classification ran).
- File: Note the filename, path (
- Log into PhotoPrism via your secure URL (
-
Edit Basic Metadata Fields:
- Ensure you are in the Edit mode of the Info pane (you might need to click a pencil icon).
- Title: Find the "Title" field and add a descriptive title, e.g.,
Sample Building Shot
. - Description: Find the "Description" or "Caption" field and add more detail, e.g.,
Testing metadata editing in PhotoPrism. This building was seen during the workshop setup.
. - Keywords/Labels: Add another specific keyword/label relevant to the photo, e.g.,
Building
. Press Enter. - Rating: Find a star rating widget (if available) and assign a rating (e.g., 4 stars).
- Save: Click the "Save" or checkmark button to apply the changes. The UI should update.
-
Verify Changes:
- Close and reopen the Info/Edit pane for the same photo. Verify that your added Title, Description, new Label (
Building
), and Rating are still present.
- Close and reopen the Info/Edit pane for the same photo. Verify that your added Title, Description, new Label (
-
(Optional) Inspect Sidecar File Creation:
- This step requires terminal access to your server.
- Identify Original Path: Note the file path shown in the PhotoPrism UI's "File" section (e.g.,
/originals/2023/11/your_photo.jpg
). - Navigate to Host Storage Directory: Open a terminal on your server and go to the PhotoPrism
storage
directory: - Navigate to Mirrored Sidecar Path: Navigate into the
sidecar
directory, mirroring the path of your original photo: If the directories don't exist, PhotoPrism might not have created the sidecar yet, or there might be a permission issue. - Look for the XMP File: List the files in this directory. You should see an
.xmp
file corresponding to the photo you just edited (e.g.,your_photo.xmp
). - Examine XMP Content (Optional): View the content of the XMP file. It's XML-based text.
Look for tags related to the information you edited, such as
<dc:title>
,<dc:description>
,<dc:subject>
(for keywords/labels), and<xmp:Rating>
. You should see the values you entered in the PhotoPrism UI reflected here. (Note:dc:
refers to the Dublin Core metadata schema, commonly used within XMP).
-
Batch Edit Metadata (Example - Adding Copyright):
- Go back to the "Search" or "Browse" view.
- Select multiple photos (e.g., all your sample photos).
- Click the "Edit" action button in the action bar.
- Find a field like "Copyright" or add a generic Label like
Copyright Your Name 2023
. (Note: Proper copyright embedding often uses specific IPTC/XMP fields which might have dedicated inputs depending on the UI version, or might need to be done via Labels). - Add the information to the selected photos.
- Save the changes.
- Verification: Check the Info/Edit pane for one of the edited photos to see if the copyright information or label was applied. Check the sidecar directory again - you might see new
.xmp
files created for the other photos you just batch-edited.
Conclusion: You have explored the metadata PhotoPrism extracts from your photos and successfully edited various fields like Title, Description, Labels, and Rating. You've seen how these changes are saved within PhotoPrism and (optionally) how they correspond to the creation or modification of XMP sidecar files in the storage
volume, demonstrating PhotoPrism's non-destructive metadata workflow.
Leveraging Search and Filtering Capabilities
One of PhotoPrism's most powerful features is its comprehensive search and filtering capability. It allows you to quickly find specific photos or groups of photos within potentially vast libraries based on a wide range of criteria. Mastering search is key to efficiently navigating your collection.
Search Interface:
- The main search bar is typically located prominently at the top of the UI.
- As you type, PhotoPrism usually provides auto-suggestions based on existing metadata, labels, locations, etc.
- You can combine multiple search terms.
Common Search Categories (Filters):
PhotoPrism allows searching by various facets of your photos. You can often access these as dedicated filters or by using specific search query syntax (often filter:value
).
- Keywords/Labels:
label:Vacation
or justVacation
(often searches titles, descriptions, and labels)label:\"Family Reunion\"
(use quotes for multi-word labels)ai:dog
(prefixai:
might be needed to search specifically for AI-generated labels, depending on version)
- Dates & Time:
2023
(finds photos from the year 2023)2023-11
orNovember 2023
(finds photos from a specific month)2023-11-21
orToday
orYesterday
date:2023-01-01~2023-03-31
(finds photos within a date range)year:2023 month:11
(combine filters)
- Location:
country:it
orcountry:Italy
(searches by country code or name)city:"New York"
place:Colosseum
(searches specific landmarks or locations identified)- Requires photos to have GPS metadata and potentially geocoding configured.
- Camera & Technical Details:
camera:"Canon EOS R5"
(use quotes if the name has spaces)lens:"RF 24-105mm"
iso:1600
f:2.8
(aperture)mm:50
(focal length)
- File Properties:
type:raw
(finds RAW files)type:video
type:jpeg
filename:IMG_1234.jpg
path:2023/11
(searches within a specific folder inoriginals
)original:IMG_1234.CR2
(searches by original filename, useful if names change)
- Content:
color:red
(finds photos with red as a dominant color)person:\"John Doe\"
(searches for recognized faces - requires face recognition enabled and faces named)
- Metadata Status:
archived:true
(finds photos you've archived/hidden)private:true
(finds photos marked as private)location:false
(finds photos without location data)quality:3+
(finds photos with a rating of 3 stars or higher)review:true
(finds photos marked as needing review)
Combining Filters:
You can combine multiple filters to narrow down your search significantly. PhotoPrism usually treats spaces between terms as an "AND" operator.
label:Vacation country:it year:2023
(Finds photos labeled "Vacation" taken in Italy during 2023)camera:Sony type:raw quality:4+
(Finds RAW photos taken with a Sony camera with a rating of 4 stars or more)ai:dog ai:park -label:Fido
(Finds photos automatically tagged as containing a dog and a park, but excludes photos manually labeled "Fido") - Note: The exact syntax for negation (-
orNOT
) might vary.
Saving Searches (Smart Albums):
Some versions of PhotoPrism or similar applications allow you to save complex search queries as "Smart Albums" or "Saved Searches." These are dynamic collections that automatically update as new photos match the criteria. This is extremely useful for frequently accessed views (e.g., "5-star photos from last year", "Photos needing location tags"). Check the "Albums" section or search documentation for this feature.
Exploration is Key:
The best way to learn the search capabilities is to experiment. Try typing different terms, use the filter suggestions, and combine criteria to see how the results change. The specific syntax and available filters might evolve slightly between PhotoPrism versions, so consulting the official documentation for your version is always helpful.
Workshop Advanced Search Queries
Goal: Practice using various search filters and combining them to find specific photos within your sample set.
Prerequisites:
- PhotoPrism running with indexed sample photos.
- Metadata edited in the previous workshop (titles, labels, ratings applied to some photos). At least one photo should have the label
Architecture
andBuilding
, some should have the labelTest Batch
, and some should have a star rating.
Steps:
-
Basic Keyword Search:
- Go to the main "Search" page in PhotoPrism.
- In the search bar, type the label you added earlier:
Architecture
. Press Enter. - Result: You should see only the photo(s) you explicitly labeled
Architecture
. - Clear the search bar. Type the title you added:
Sample Building Shot
(or parts of it). Press Enter. - Result: The photo(s) matching that title should appear.
-
Filtering by Label:
- Clear the search bar.
- Type
label:Building
. Press Enter. - Result: Only photos explicitly labeled
Building
should appear. - Clear the search. Type
label:"Test Batch"
(use quotes if needed, though maybe not for this specific label). Press Enter. - Result: All photos labeled
Test Batch
should appear.
-
Filtering by Rating:
- Clear the search bar.
- Assume you rated one photo as 4 stars. Type
quality:4
. Press Enter. - Result: Only the photo(s) with exactly 4 stars should appear.
- Clear the search. Type
quality:3+
. Press Enter. - Result: Photos with 3, 4, or 5 stars should appear. (You might only have a 4-star photo from the previous workshop).
-
Filtering by Type:
- Clear the search bar.
- Type
type:jpeg
. Press Enter. - Result: All JPEG photos should appear.
- If you included a RAW file (e.g., .CR2, .NEF) or a video (.MP4, .MOV) in your samples, try
type:raw
ortype:video
. - Result: Only files of the specified type should appear.
-
Filtering by Date:
- Clear the search bar.
- Type the year your sample photos were taken (e.g.,
2023
). Press Enter. - Result: All photos from that year should appear.
- Refine it by adding the month:
2023-11
(oryear:2023 month:11
). Press Enter. - Result: Only photos from that specific month and year should appear.
-
Combining Filters:
- Let's find high-quality JPEG photos labeled
Test Batch
. Clear the search bar. - Type
type:jpeg quality:3+ label:"Test Batch"
. Press Enter. - Result: You should see only the JPEG photos that have a rating of 3 stars or more AND are labeled
Test Batch
. - Let's find photos from November 2023 that are not labeled
Architecture
. - Type
2023-11 -label:Architecture
(oryear:2023 month:11 -label:Architecture
). The exact syntax for negation might vary; tryNOT label:Architecture
if-label:
doesn't work. - Result: You should see photos from Nov 2023, excluding the one(s) you labeled
Architecture
.
- Let's find high-quality JPEG photos labeled
-
Searching by Camera (If Applicable):
- If your photos have camera EXIF data, try searching for it. Open the Info pane for one photo to see the exact camera model name.
- Clear the search. Type
camera:"Your Camera Model Name"
(use quotes!). Press Enter. - Result: Only photos taken with that specific camera should appear.
-
Experiment:
- Try searching for other terms based on the metadata you observed in the previous workshop (ISO, aperture, filename parts, etc.).
- Combine different filters in various ways to see how the results change. Use the auto-suggestions if PhotoPrism offers them.
Conclusion: You have practiced using PhotoPrism's search bar with specific filter syntax (label:
, quality:
, type:
, year:
, month:
, camera:
, negation -
) and combined multiple filters to perform targeted searches. This demonstrates the power and flexibility of PhotoPrism's search engine for navigating your photo library efficiently.
(Advanced Level Sections Follow)
4. Automation and Workflow Integration
Moving into more advanced usage, this section explores how to automate tasks within PhotoPrism, integrate it with external tools like mobile upload apps, and establish robust backup strategies to protect your valuable photo library.
Automatic Indexing and Importing
Manually triggering indexing or importing works, but for a truly seamless experience, you'll want PhotoPrism to automatically detect and process new photos added to your library. PhotoPrism provides built-in mechanisms for this.
Automatic Indexing (Scanning originals
):
- Purpose: Periodically scans the
/photoprism/originals
directory (and its subdirectories) for any new files, deleted files, or updated sidecar files. This is the most common method for keeping the library in sync with photos added directly to theoriginals
structure (e.g., via network shares, Syncthing, etc.). - Configuration:
- Environment Variable:
PHOTOPRISM_SCAN_INTERVAL
in yourdocker-compose.yml
. - Value: Specifies the interval between scans. Examples:
15m
(every 15 minutes)1h
(every hour - a reasonable default for many)6h
(every 6 hours)1d
(once a day)0
(disabled - manual indexing only)
- UI Setting: Can also often be configured in
Settings > Library > Scan Interval
. Settings here might override the environment variable unless PhotoPrism is configured to prioritize environment variables.
- Environment Variable:
- How it Works: PhotoPrism runs a background job at the specified interval. It compares the files found in
originals
with its database index.- New Files: Found files not in the index are added and processed (metadata extraction, thumbnail generation, etc.).
- Deleted Files: Files in the index but missing from
originals
are marked as missing or removed from the index (behavior might be configurable). - Updated Files/Sidecars: If a file's modification time or a corresponding sidecar file has changed since the last scan, PhotoPrism re-reads its metadata.
- Resource Usage: Frequent scanning (e.g., every few minutes) on very large libraries can consume resources. Choose an interval that balances freshness with system load. Hourly or multi-hourly scans are generally sufficient unless you need near real-time updates.
Automatic Importing (Processing import
):
- Purpose: Periodically checks the
/photoprism/import
directory for new files. If files are found, PhotoPrism moves them into theoriginals
directory (typically organizing them intoYYYY/MM
subfolders based on EXIF date) and then indexes them. - Configuration:
- Volume Mapping: Requires a host directory mapped to
/photoprism/import
indocker-compose.yml
. - Environment Variable:
PHOTOPRISM_IMPORT_INTERVAL
indocker-compose.yml
. - Value: Similar format to
PHOTOPRISM_SCAN_INTERVAL
(e.g.,30m
,2h
,0
for disabled). - UI Setting: Often available in
Settings > Library > Import Interval
. - Import Path:
PHOTOPRISM_IMPORT_PATH
environment variable (defaults to/photoprism/import
). - Move Files: Ensure
PHOTOPRISM_IMPORT_MOVE: "true"
(usually the default behavior for the import action) if you want files moved fromimport
tooriginals
.
- Volume Mapping: Requires a host directory mapped to
- Workflow:
- An external process (e.g., a script, a mobile sync app configured to use WebDAV if
import
is shared) places files into the host directory mapped to/photoprism/import
. - PhotoPrism's import job runs at the specified interval.
- It finds the new files in
/photoprism/import
. - It reads the EXIF date from each file.
- It moves the file to the appropriate location within
/photoprism/originals
(e.g.,/photoprism/originals/2023/11/your_photo.jpg
). - It indexes the newly moved file.
- The
/photoprism/import
directory is left empty.
- An external process (e.g., a script, a mobile sync app configured to use WebDAV if
- Use Cases: Useful when you want PhotoPrism to handle the organization of incoming files automatically based on date, or when the tool adding photos can only drop them into a single designated folder.
Choosing Between Auto-Index and Auto-Import:
- Use Auto-Indexing (
PHOTOPRISM_SCAN_INTERVAL
) if you manage your own folder structure withinoriginals
or use tools that sync directly into that structure. This is generally the preferred and more common method. - Use Auto-Importing (
PHOTOPRISM_IMPORT_INTERVAL
) if you want PhotoPrism to organize incoming files by date automatically, or if your upload method requires dropping files into a single 'inbox' folder. Be aware that it moves files from the import source.
Enabling automatic scanning or importing significantly reduces manual effort in keeping your PhotoPrism library up-to-date.
Workshop Setting Up Automated Photo Imports
Goal: Configure PhotoPrism to automatically index new photos added to the originals
directory.
Prerequisites:
- PhotoPrism running via Docker Compose.
- Access to modify your PhotoPrism
docker-compose.yml
file. - Some new sample photos (different from the ones already indexed) ready in a temporary location (e.g.,
~/new_samples
).
Steps:
-
Configure Auto-Indexing Interval:
- Open your PhotoPrism
docker-compose.yml
file (e.g.,/opt/photoprism/docker-compose.yml
) in a text editor. - Locate the
environment:
section under thephotoprism
service. - Add or modify the
PHOTOPRISM_SCAN_INTERVAL
variable. Let's set it to scan every 5 minutes for testing purposes (you can increase this later). - Ensure other necessary variables like
PHOTOPRISM_ADMIN_USER
,PHOTOPRISM_ADMIN_PASSWORD
,PHOTOPRISM_SITE_URL
,TZ
are still correctly set. - Save the
docker-compose.yml
file.
- Open your PhotoPrism
-
Restart PhotoPrism to Apply Changes:
- Open a terminal on your server and navigate to the directory containing your PhotoPrism
docker-compose.yml
. - Apply the configuration change by stopping and restarting the container:
- Verification: Check the logs briefly to ensure PhotoPrism starts correctly without errors related to the new environment variable. Look for lines indicating the scan interval being recognized.
- Open a terminal on your server and navigate to the directory containing your PhotoPrism
-
Prepare New Photos:
- Gather 2-3 new sample photos in a temporary directory (e.g.,
~/new_samples
). Make sure these are different from the ones already in PhotoPrism.
- Gather 2-3 new sample photos in a temporary directory (e.g.,
-
Add New Photos to
originals
:- Copy the new sample photos into your host
originals
directory structure. You can put them in the same2023/11
folder or create a new one (e.g.,originals/2023/12
). Make sure PhotoPrism will have read permissions.# Example: Copying to the existing folder sudo cp ~/new_samples/* /opt/photoprism/originals/2023/11/ # Example: Copying to a new folder # sudo mkdir -p /opt/photoprism/originals/2023/12 # sudo cp ~/new_samples/* /opt/photoprism/originals/2023/12/ # sudo chown -R appropriate_user:group /opt/photoprism/originals/2023/12 # If needed
- Copy the new sample photos into your host
-
Wait for Automatic Scan:
- Do not manually trigger an index in the UI.
- Wait for the configured interval (
5m
in this case) to pass. - You can monitor the PhotoPrism logs during this time:
After approximately 5 minutes (since the container started or the last scan finished), you should see log entries indicating that the indexer is starting a scan (
index: starting scan...
or similar). It should then report finding and processing the new files you added.
-
Verify New Photos in UI:
- Once the logs indicate the scan is complete, refresh the PhotoPrism "Search" or "Browse" page in your web browser.
- The new sample photos you added should now appear in the library alongside the originals.
- Click on one of the new photos and check its details to ensure metadata was processed correctly.
-
(Optional) Adjust Scan Interval:
- Once you've confirmed auto-indexing works, you might want to set a less frequent interval for normal use.
- Edit
docker-compose.yml
again, changePHOTOPRISM_SCAN_INTERVAL
to1h
or6h
. - Save the file.
- Restart PhotoPrism:
docker compose down && docker compose up -d
.
Conclusion: You have successfully configured PhotoPrism to automatically scan the originals
directory for new files at a regular interval. This automates the process of adding new photos to your library, making it much more convenient to keep your collection up-to-date.
Using Mobile Apps for Uploads
Manually copying photos from your phone to your PhotoPrism server can be tedious. Several mobile applications are designed to automatically upload photos and videos from your phone to various destinations, including self-hosted services via protocols like WebDAV. PhotoPrism includes a built-in WebDAV server, making it compatible with many of these apps.
WebDAV (Web Distributed Authoring and Versioning):
- An extension of the HTTP protocol that allows clients to perform remote Web content authoring operations.
- In this context, it allows compatible mobile apps to browse directories and upload files to your PhotoPrism server securely over HTTPS (if you've set up a reverse proxy).
PhotoPrism's Built-in WebDAV Server:
- Purpose: Provides a way for external applications to interact with your PhotoPrism library's file structure, primarily for uploads.
- Activation: Usually enabled by default but might require specific configuration or user permissions. Check PhotoPrism's documentation or settings regarding WebDAV.
- Access Point: The WebDAV server is typically accessible via your main PhotoPrism URL, often at a specific path like
/dav
or/remote.php/dav
(the exact path can vary, check documentation). For example:https://photoprism.yourdomain.com/dav
- Authentication: Uses standard PhotoPrism user accounts and passwords for authentication.
Popular Compatible Mobile Apps:
- PhotoSync (iOS/Android): A highly regarded, versatile app specifically designed for transferring photos and videos between devices and services. It supports numerous protocols, including WebDAV, and offers features like background uploads, configurable filenames, subfolder creation, and deletion after transfer. (Often requires a one-time purchase for full features).
- FolderSync (Android): Another popular Android app for syncing files between device folders and various cloud/protocol endpoints, including WebDAV. Offers detailed scheduling and configuration options.
- Others: Many other sync apps or even some file manager apps might have WebDAV client capabilities.
General Setup Workflow (using PhotoSync as an example):
- Install the App: Install PhotoSync (or your chosen app) on your smartphone.
-
Configure New Connection (WebDAV):
- Open PhotoSync and go to
Configure
>WebDAV
. - Tap
Add New Connection
(or similar). - Server Address/URL: Enter the full HTTPS URL to your PhotoPrism's WebDAV endpoint. This is critical. It will be something like
photoprism.yourdomain.com
or the specific path if required (e.g.,photoprism.yourdomain.com/dav
). Check PhotoPrism docs for the exact endpoint. - Port:
443
(for HTTPS). - Use SSL/HTTPS: Ensure this is enabled.
- Username: Your PhotoPrism username.
- Password: Your PhotoPrism password.
- Directory/Path: This is important. You need to tell PhotoSync where on the WebDAV server to upload files. You have two main options:
- Upload to
import
: If you want PhotoPrism's auto-import feature to handle sorting files by date, set the target directory to/import
(or whatever path corresponds to your mapped import volume). Remember, this moves files. - Upload directly to
originals
: If you want PhotoSync to organize files (e.g., intoYYYY/MM
folders) and place them directly where PhotoPrism's auto-indexing will find them, set the target directory to/originals
or a subdirectory within it (e.g.,/originals/MobileUploads
). PhotoSync often has options to create subdirectories based on date/time automatically. This requires PhotoPrism's auto-indexing (PHOTOPRISM_SCAN_INTERVAL
) to be active. This is often the preferred method if the app supports dynamic subfolder creation.
- Upload to
- Test Connection: Most apps have a button to test the connection details.
- Open PhotoSync and go to
-
Configure Auto-Transfer (Optional):
- In PhotoSync, go to
Autotransfer
. - Set up a trigger (e.g., new photos taken, charging, specific Wi-Fi network).
- Select the source (e.g., Camera Roll, specific albums).
- Select the target (the WebDAV connection you just configured).
- Configure options like deleting after transfer (use with caution!), Wi-Fi only uploads, etc.
- In PhotoSync, go to
-
Initiate Upload/Sync:
- Perform a manual sync/upload initially to test the configuration. Select some photos in PhotoSync and choose the WebDAV target.
- Monitor the upload progress in the app and check if the files appear in the expected location on your server (either the
import
directory or theoriginals
directory, depending on your configuration). - If uploading directly to
originals
, wait for PhotoPrism's next auto-index scan (or trigger one manually) to see the photos appear in the UI. If uploading toimport
, wait for the auto-import interval (or trigger manually).
Using a mobile app with WebDAV provides a convenient, automated way to back up photos from your phone directly to your self-hosted PhotoPrism instance.
Workshop Configuring PhotoSync for Auto-Uploads
Goal: Configure the PhotoSync mobile app (or a similar WebDAV-capable app) to automatically upload new photos from your phone to your PhotoPrism instance via WebDAV, placing them directly into the originals
directory for auto-indexing.
Prerequisites:
- PhotoPrism running and accessible via HTTPS through a reverse proxy (NPM setup from previous workshop).
- PhotoPrism's auto-indexing (
PHOTOPRISM_SCAN_INTERVAL
) configured and working. - A smartphone (iOS or Android) on the same network as your server (for initial setup/testing, though it can work over the internet if your domain is public).
- PhotoSync app installed (or another WebDAV sync app like FolderSync). Note: PhotoSync may require a premium purchase for WebDAV auto-transfer features. This workshop describes the general steps; exact UI elements may vary.
- Your PhotoPrism username and password.
- Knowledge of your PhotoPrism WebDAV URL. Check the official PhotoPrism documentation for the correct WebDAV endpoint path for your version. Common paths might be
/dav
or/remote.php/webdav/
. For this workshop, we'll assumehttps://photoprism.yourdomain.com/dav
. Verify this path!
Steps:
-
Verify PhotoPrism WebDAV Access (Conceptual):
- Ensure WebDAV is likely enabled in PhotoPrism (it usually is by default for authenticated users). There might not be an explicit UI toggle; it often just works if the user has permissions.
-
Configure WebDAV Target in PhotoSync:
- Open the PhotoSync app on your phone.
- Navigate to
Configure
(usually a settings/gear icon). - Select
WebDAV
under theConfigure Targets
section. - Tap
Add WebDAV configuration
or similar. - Title/Name: Give it a recognizable name, e.g.,
PhotoPrism Server
. - Server: Enter the hostname of your PhotoPrism instance (e.g.,
photoprism.yourdomain.com
). Do NOT includehttps://
here. - WebDAV Path: Enter the correct path for the WebDAV endpoint (e.g.,
/dav
or/remote.php/webdav/
). Verify this carefully! - Port:
443
. - Use SSL: Enable/toggle this ON.
- Login / Username: Enter your PhotoPrism username.
- Password: Enter your PhotoPrism password.
- Directory: This specifies the target folder on the server where photos will be uploaded. To integrate with auto-indexing, we want to upload directly into
originals
, preferably organized by date.- Enter
/originals/Mobile/
initially. We'll add date-based subfolders next. - PhotoSync allows dynamic placeholders. Tap on the
Directory
field (or an associated settings icon) to find options for creating subdirectories. Configure it to create folders based on year and month. The syntax might look something like/originals/Mobile/%Y/%m
or similar (consult PhotoSync's help for exact placeholders). This tells PhotoSync to upload photos into/photoprism/originals/Mobile/YYYY/MM/
.
- Enter
- Create Sub-Directories: Ensure the option to automatically create needed subdirectories is enabled.
- Filename Options (Optional): You can configure PhotoSync to rename files on upload (e.g.,
YYYY-MM-DD_HH-MM-SS.jpg
) if desired. - Tap
Done
orSave
. - Test Connection: PhotoSync will likely attempt to connect. Ensure it succeeds. If not, double-check Server, WebDAV Path, Port, SSL, Username, Password, and network connectivity. Check NPM logs if errors occur server-side.
-
Configure Auto-Transfer:
- Go back to the main PhotoSync screen and select
Autotransfer
. - Tap
Add Autotransfer
or configure an existing trigger. - Trigger: Choose when uploads should happen (e.g.,
New photos & videos
,On charging
,Location based
). SelectingNew photos & videos
is common. You might restrict it toWi-Fi connection
>Selected Wi-Fis
(your home network) to avoid using mobile data. - From (Source): Select which photos/videos to upload (e.g.,
Camera Roll
,All photos/videos
, specific albums). - To (Target): Select the
PhotoPrism Server
(WebDAV) target you just configured. - Options: Review settings like
Delete after transfer
(use CAUTION - ensure uploads are verified before enabling),Transfer quality
,Allow cellular data
. - Enable the Autotransfer trigger.
- Go back to the main PhotoSync screen and select
-
Perform Initial Manual Upload:
- To test the target configuration immediately, go to the main PhotoSync screen (showing your phone's photos).
- Select one or two new photos that aren't yet in PhotoPrism.
- Tap the
Sync/Transfer
button (often red arrows). - Select
New
(to transfer only selected new photos). - Choose the
PhotoPrism Server
(WebDAV) target. - Tap
Sync
. - Monitor the transfer progress in PhotoSync's
Activity
log.
-
Verify File Arrival and Indexing:
- Check Server Filesystem (Optional): Access your server via terminal. Navigate to
/opt/photoprism/originals/Mobile/YYYY/MM
(use the actual year/month). You should see the uploaded photo file(s). Check permissions if needed. - Wait for Auto-Index: Wait for PhotoPrism's
PHOTOPRISM_SCAN_INTERVAL
to pass. - Check PhotoPrism UI: Refresh the PhotoPrism web UI. The newly uploaded photo(s) should appear in the "Search" or "Browse" view.
- Check Server Filesystem (Optional): Access your server via terminal. Navigate to
-
Test Auto-Transfer:
- Take a new photo with your phone's camera.
- Ensure the Autotransfer trigger conditions are met (e.g., you are on the correct Wi-Fi, or charging).
- PhotoSync should detect the new photo and automatically upload it in the background (this might take a few minutes depending on configuration and app behavior).
- Check the PhotoSync activity log and eventually PhotoPrism UI (after the next auto-index scan) to confirm the automated upload worked.
Troubleshooting:
- Connection Failed: Double-check all WebDAV parameters in PhotoSync (Server, Path, Port 443, SSL on, credentials). Verify the WebDAV path from PhotoPrism docs. Check NPM logs for connection attempts/errors. Ensure your phone can reach
https://photoprism.yourdomain.com
. - Uploads Fail (Permission Denied): PhotoPrism (running inside Docker) needs write permission to the
/originals/Mobile/YYYY/MM
directories on the host. The WebDAV server process handles the writing. You might need to adjust ownership/permissions on the/opt/photoprism/originals/Mobile
base directory on the host to allow the user running PhotoPrism inside the container (or a group it belongs to) to create subdirectories and files. For example:sudo chown -R <photoprism_user_id>:<photoprism_group_id> /opt/photoprism/originals/Mobile
(finding the correct IDs might require inspecting the container) or a more permissivesudo chmod -R 775 /opt/photoprism/originals/Mobile
if the user is in the correct group. - Files Uploaded but Don't Appear in PhotoPrism: Auto-indexing interval hasn't passed yet, or the index scan failed (check PhotoPrism logs). Ensure
PHOTOPRISM_SCAN_INTERVAL
is set and PhotoPrism was restarted after setting it. - Auto-Transfer Not Triggering: Review PhotoSync's Autotransfer settings (trigger conditions, Wi-Fi selection, source selection). Check phone battery optimization settings (sometimes Android/iOS kill background apps aggressively).
Conclusion: You have successfully configured a mobile app (PhotoSync) to upload photos to your PhotoPrism server using WebDAV. By targeting the originals
directory with date-based subfolders and relying on PhotoPrism's auto-indexing, you've created a largely automated workflow for getting photos from your phone into your self-hosted library.
Backup Strategies for PhotoPrism Data and Photos
Self-hosting gives you control, but it also means you are solely responsible for backups. Losing your photo library due to hardware failure, accidental deletion, or other disasters can be devastating. A robust backup strategy is non-negotiable.
What Needs Backing Up?
You need to back up two distinct sets of data:
-
Original Photos (
originals
directory):- Content: Your actual, irreplaceable photo and video files. This is the most critical part.
- Location: The directory on your host machine that is mapped to
/photoprism/originals
(e.g.,/opt/photoprism/originals
or/path/to/my/photos
).
-
PhotoPrism Application Data (
storage
directory):- Content:
- Database (e.g.,
storage/database/index.sqlite
or external MariaDB data) - Contains all metadata, albums, tags, users, settings. - Sidecar files (
storage/sidecar
) - Contains metadata edits, RAW previews. - Cache (
storage/cache
) - Thumbnails, previews. While technically regenerable by re-indexing, backing up the cache can save significant time during a restore. However, it can also be very large. Some users choose to exclude the cache from backups to save space/time, accepting the need for regeneration after a restore. - Configuration (
storage/config/options.yml
).
- Database (e.g.,
- Location: The directory on your host machine mapped to
/photoprism/storage
(e.g.,/opt/photoprism/storage
).
- Content:
-
Configuration Files:
- Content: Your
docker-compose.yml
files (for PhotoPrism, NPM, any other related services) and any custom scripts or notes related to your setup. - Location: Wherever you store them (e.g.,
/opt/photoprism/
,/opt/npm/
).
- Content: Your
The 3-2-1 Backup Rule (Highly Recommended):
- 3 Copies: Keep at least three copies of your important data. (1 primary + 2 backups).
- 2 Different Media: Store the copies on at least two different types of storage media (e.g., internal drive + external USB drive + NAS).
- 1 Offsite Location: Keep at least one copy offsite (e.g., external drive stored at a friend's house, cloud backup service, another server in a different physical location). This protects against local disasters like fire, flood, or theft.
Backup Methods and Tools:
-
Manual Copy:
- Method: Simply copy the
originals
andstorage
directories to an external drive periodically. - Pros: Simple to understand.
- Cons: Prone to human error (forgetting), time-consuming, doesn't handle versioning well, requires PhotoPrism to be stopped for consistency (especially for the database).
- Method: Simply copy the
-
Rsync:
- Method: A powerful command-line utility for synchronizing files and directories. Can be used to efficiently copy changes to a backup destination (local or remote over SSH).
rsync -avh --delete /opt/photoprism/originals/ /mnt/backup_drive/photoprism_backup/originals/
rsync -avh --delete /opt/photoprism/storage/ /mnt/backup_drive/photoprism_backup/storage/
(Run while PhotoPrism is stopped for database consistency!)- Pros: Efficient (only copies changes), widely available, scriptable.
- Cons: Still requires stopping PhotoPrism for database integrity unless using database-specific dump tools. Doesn't inherently provide point-in-time recovery beyond the last sync unless combined with snapshotting or other tools.
-
Dedicated Backup Software:
- Examples: Duplicati, BorgBackup, Restic, Kopia, Vorta (GUI for Borg), UrBackup.
- Method: These tools offer more advanced features like:
- Scheduling: Automated backups at regular intervals.
- Encryption: Encrypt backups at the destination.
- Compression: Reduce backup size.
- Deduplication: Store identical data blocks only once, saving significant space, especially for the
storage
volume. - Versioning/Snapshots: Keep multiple historical versions of your backup, allowing you to restore to a specific point in time.
- Cloud Storage Integration: Many can back up directly to cloud services (Backblaze B2, AWS S3, Google Cloud Storage, OneDrive, etc.) for offsite storage.
- Pros: Automation, efficiency (deduplication), security (encryption), versioning. Often the best approach for robust backups.
- Cons: Steeper learning curve than manual copy or basic rsync. Requires installing and configuring the backup software (often as another Docker container or directly on the host).
-
Database Specific Backups (for MariaDB/PostgreSQL):
- Method: If using an external database like MariaDB, you should use the database's native dump tools (
mysqldump
) to create a logical backup (.sql
file). This can often be done while the database is running. docker compose exec -T mariadb-service mysqldump --user=photoprism --password=YourPassword photoprism > /path/on/host/photoprism_db_backup.sql
- This SQL dump should be backed up alongside the
originals
and the rest of thestorage
directory (excluding the live database files themselves). - Pros: Ensures database consistency without stopping the application entirely. Standard practice for database backups.
- Cons: Adds complexity; you need to back up the SQL file and the filesystem data. Restoring requires importing the SQL file.
- Method: If using an external database like MariaDB, you should use the database's native dump tools (
Key Considerations for PhotoPrism Backups:
- Consistency: File-level backups (like rsync or Duplicati) of a live database (like
index.sqlite
or MariaDB's data files) can result in a corrupt backup if the database is being written to during the copy.- Safest Method: Stop the PhotoPrism container (
docker compose down
) before backing up thestorage
directory (especially the database file). Then restart it (docker compose up -d
) after the backup completes. This guarantees consistency but involves downtime. - Alternative (SQLite): For SQLite, some backup tools might integrate with SQLite's backup API, or you might script copying the
index.sqlite
file quickly while PhotoPrism is running (less safe, potential for minor inconsistencies). A brief stop is usually better. - Alternative (MariaDB): Use
mysqldump
as described above.
- Safest Method: Stop the PhotoPrism container (
- Frequency: How often should you back up? Depends on how often your library changes and how much data you're willing to potentially lose. For active libraries, daily backups are common. For static archives, weekly or monthly might suffice. Back up originals immediately after adding large batches.
- Retention: How long should you keep old backups? Depends on storage space and recovery needs. Keep several daily, weekly, and monthly snapshots if using versioning tools.
- Testing: Regularly test your restore process! A backup is useless if you can't restore from it. Periodically try restoring your
originals
andstorage
(and database dump if applicable) to a separate test environment to ensure the backups are valid and you know the procedure.
A good starting strategy might involve using a tool like Duplicati or BorgBackup running on a schedule:
- (Optional but recommended) A pre-backup script stops PhotoPrism.
- The backup tool backs up
originals
,storage
, and configuration files to an external drive and/or cloud storage, using encryption and deduplication. - A post-backup script restarts PhotoPrism.
Workshop Implementing a Basic Backup Routine
Goal:
Create a simple, manual backup script using rsync
to copy the originals
and storage
directories to an external drive, including stopping and starting PhotoPrism for data consistency.
Prerequisites:
- PhotoPrism running via Docker Compose (e.g., from
/opt/photoprism/docker-compose.yml
). - An external backup drive mounted on your host system (e.g., at
/mnt/backup_drive
). Make sure your user has write permissions to this drive, or run the script withsudo
. rsync
installed on your host system (sudo apt install rsync
on Debian/Ubuntu if not present).- Terminal access to the host machine.
Steps:
-
Create Backup Destination Directory: On your external drive, create a specific directory to hold the PhotoPrism backups.
Explanation: We create a# Adjust the mount point and directory name as needed BACKUP_BASE="/mnt/backup_drive/photoprism_backups" mkdir -p "${BACKUP_BASE}/latest/originals" mkdir -p "${BACKUP_BASE}/latest/storage" mkdir -p "${BACKUP_BASE}/latest/config"
photoprism_backups
directory, and inside it, alatest
subdirectory. This structure allows for potential future versioning (e.g., keeping dated copies alongsidelatest
). We pre-create the targetoriginals
,storage
, andconfig
subdirectories withinlatest
. -
Create the Backup Script: Create a new file for your backup script, for example,
Paste the following script content into the file. Carefully review and adjust the paths (~/photoprism_backup.sh
.PHOTOPRISM_DIR
,BACKUP_DEST
,NPM_DIR
if applicable) to match your specific setup.#!/bin/bash # --- Configuration --- # Adjust these paths to match YOUR setup! PHOTOPRISM_DIR="/opt/photoprism" # Directory containing PhotoPrism's docker-compose.yml NPM_DIR="/opt/npm" # Directory containing Nginx Proxy Manager's docker-compose.yml (if used) BACKUP_DEST="/mnt/backup_drive/photoprism_backups/latest" # Base backup destination path # Optional: Path to PhotoPrism directories if they are NOT inside PHOTOPRISM_DIR # ORIGINALS_SRC="${PHOTOPRISM_DIR}/originals" # STORAGE_SRC="${PHOTOPRISM_DIR}/storage" # Or if they are elsewhere: ORIGINALS_SRC="/path/to/my/actual/photos" # Example: if originals are outside /opt/photoprism STORAGE_SRC="${PHOTOPRISM_DIR}/storage" # Assuming storage is still with the compose file # Backup directories within BACKUP_DEST BACKUP_ORIGINALS_DEST="${BACKUP_DEST}/originals" BACKUP_STORAGE_DEST="${BACKUP_DEST}/storage" BACKUP_CONFIG_DEST="${BACKUP_DEST}/config" # Log file LOG_FILE="/var/log/photoprism_backup.log" # Ensure this path is writable or run with sudo # --- Functions --- log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "${LOG_FILE}" } # --- Pre-Checks --- log_message "Starting PhotoPrism backup script." # Check if backup destination is mounted/accessible if [ ! -d "${BACKUP_DEST}" ]; then log_message "ERROR: Backup destination '${BACKUP_DEST}' not found or not accessible. Aborting." exit 1 fi # Check if source directories exist if [ ! -d "${ORIGINALS_SRC}" ]; then log_message "ERROR: Originals source directory '${ORIGINALS_SRC}' not found. Aborting." exit 1 fi if [ ! -d "${STORAGE_SRC}" ]; then log_message "ERROR: Storage source directory '${STORAGE_SRC}' not found. Aborting." exit 1 fi # --- Main Backup Process --- log_message "Stopping PhotoPrism container for consistent backup..." cd "${PHOTOPRISM_DIR}" || { log_message "ERROR: Could not change to PhotoPrism directory '${PHOTOPRISM_DIR}'."; exit 1; } docker compose down if [ $? -ne 0 ]; then log_message "WARNING: Failed to stop PhotoPrism gracefully. Proceeding with backup, but consistency might be affected." # Decide if you want to exit here or proceed with caution # exit 1 else log_message "PhotoPrism container stopped successfully." fi # Backup Originals using rsync log_message "Backing up Originals from '${ORIGINALS_SRC}' to '${BACKUP_ORIGINALS_DEST}'..." rsync -avh --delete --info=progress2 "${ORIGINALS_SRC}/" "${BACKUP_ORIGINALS_DEST}/" if [ $? -ne 0 ]; then log_message "ERROR: Rsync failed for Originals directory. Check permissions and space." # Consider not restarting PhotoPrism if originals backup fails # exit 1 # Or just log and continue else log_message "Originals backup completed." fi # Backup Storage using rsync log_message "Backing up Storage from '${STORAGE_SRC}' to '${BACKUP_STORAGE_DEST}'..." rsync -avh --delete --info=progress2 "${STORAGE_SRC}/" "${BACKUP_STORAGE_DEST}/" if [ $? -ne 0 ]; then log_message "ERROR: Rsync failed for Storage directory. Check permissions and space." # Consider implications before restarting else log_message "Storage backup completed." fi # Backup Configuration Files log_message "Backing up configuration files..." cp "${PHOTOPRISM_DIR}/docker-compose.yml" "${BACKUP_CONFIG_DEST}/photoprism-docker-compose.yml" # Backup NPM config if used if [ -d "${NPM_DIR}" ] && [ -f "${NPM_DIR}/docker-compose.yml" ]; then cp "${NPM_DIR}/docker-compose.yml" "${BACKUP_CONFIG_DEST}/npm-docker-compose.yml" # Optionally backup NPM data/letsencrypt folders (can be large, consider if needed) # rsync -avh --delete "${NPM_DIR}/data/" "${BACKUP_CONFIG_DEST}/npm_data/" # rsync -avh --delete "${NPM_DIR}/letsencrypt/" "${BACKUP_CONFIG_DEST}/npm_letsencrypt/" fi log_message "Configuration backup completed." log_message "Restarting PhotoPrism container..." cd "${PHOTOPRISM_DIR}" # Ensure we are in the correct directory docker compose up -d if [ $? -ne 0 ]; then log_message "ERROR: Failed to restart PhotoPrism container. Check 'docker compose logs photoprism'." exit 1 else log_message "PhotoPrism container restarted successfully." fi log_message "Backup script finished successfully." exit 0
-
Understanding the Script:
#!/bin/bash
: Shebang line, specifies the script should be executed with bash.- Configuration: Sets variables for key paths. Modify these carefully. It includes paths for PhotoPrism's compose directory, the backup destination, and optionally the NPM directory. It also defines the source paths for
originals
andstorage
, allowing them to be different from the compose file directory if needed. - Log Function: Creates a simple function
log_message
to print messages to the console and append them to a log file (/var/log/photoprism_backup.log
). You might need to create this log file initially and ensure it's writable (sudo touch /var/log/photoprism_backup.log; sudo chown your_user /var/log/photoprism_backup.log
or run the script withsudo
). - Pre-Checks: Verifies that the backup destination and source directories exist before proceeding.
- Stop PhotoPrism: Navigates to the PhotoPrism directory and runs
docker compose down
to stop the container gracefully. This is crucial for ensuring thestorage
directory (especially the SQLite database) is in a consistent state. Includes basic error checking. - Rsync Originals: Uses
rsync
to copy theoriginals
directory.-a
: Archive mode (preserves permissions, ownership, timestamps, etc.).-v
: Verbose output.-h
: Human-readable numbers.--delete
: Deletes files in the destination that no longer exist in the source (keeps the backup synchronized). Use with caution if you want to keep deleted files in the backup.--info=progress2
: Shows overall progress.${ORIGINALS_SRC}/
: Source directory (trailing slash copies contents).${BACKUP_ORIGINALS_DEST}/
: Destination directory.
- Rsync Storage: Performs the same
rsync
operation for thestorage
directory. This happens after PhotoPrism is stopped. - Backup Config: Copies the relevant
docker-compose.yml
files to the config backup location. Optionally includes commands to back up NPM data/certs (commented out by default). - Restart PhotoPrism: Navigates back to the PhotoPrism directory and runs
docker compose up -d
to restart the container in detached mode. Includes error checking. - Logging & Exit: Logs completion messages and exits.
-
Make Script Executable:
-
Perform Initial Manual Backup: Run the script manually for the first time. You might need
sudo
depending on permissions for Docker, log file location, and the backup drive mount point.- Watch the output carefully. It will show:
- Stopping PhotoPrism.
- Rsync progress for
originals
(can take a long time initially). - Rsync progress for
storage
. - Copying config files.
- Restarting PhotoPrism.
- Check the log file:
tail -n 30 /var/log/photoprism_backup.log
. - Verify the backup files exist on your external drive in
/mnt/backup_drive/photoprism_backups/latest/
.
- Watch the output carefully. It will show:
-
Scheduling the Backup (Optional but Recommended): Use
cron
to run this script automatically on a schedule (e.g., daily).- Edit the crontab for the root user (as
docker compose down/up
often requires root):sudo crontab -e
- Add a line to run the script. For example, to run it every day at 3:00 AM:
(Adjust the path
/root/photoprism_backup.sh
if you saved the script elsewhere accessible by root.> /dev/null 2>&1
suppresses normal output/errors from cron emails, relying solely on the script's log file). - Save and exit the crontab editor.
- Edit the crontab for the root user (as
Conclusion: You have created and tested a basic rsync
-based backup script that safely backs up your PhotoPrism originals
, storage
, and configuration files after stopping the container for consistency. While simple, this provides a significant improvement over no backups. For more advanced features like versioning, deduplication, and encryption, consider implementing tools like BorgBackup or Duplicati, potentially adapting this script's stop/start logic. Remember to also implement the offsite part of the 3-2-1 rule.
5. Database Management and Performance Tuning
This advanced section delves into managing PhotoPrism's database, particularly when scaling up, and explores various techniques to optimize the performance of your PhotoPrism instance, ensuring a smooth experience even with large libraries.
Using MariaDB Instead of SQLite
While PhotoPrism's default embedded SQLite database is convenient for single users and smaller libraries, performance can degrade with very large collections (hundreds of thousands of items) or multiple concurrent users. MariaDB (a popular open-source fork of MySQL) is a more robust relational database management system (RDBMS) designed for scalability and concurrent access. PhotoPrism fully supports using MariaDB as its backend database.
Why Switch to MariaDB?
- Performance at Scale: MariaDB generally handles larger datasets and higher query loads more efficiently than SQLite due to its client-server architecture, more sophisticated query optimizer, and caching mechanisms.
- Concurrency: Better designed to handle simultaneous read/write operations from multiple users or background processes (like indexing and web UI access) without locking issues that can sometimes affect SQLite under heavy load.
- Dedicated Resources: Runs as a separate process/container, allowing you to allocate specific CPU/RAM resources to the database, independent of the main PhotoPrism application.
- Advanced Features: Offers more advanced database administration features, replication, and clustering options (though typically overkill for a personal PhotoPrism setup).
- Standard Practice: Using a dedicated RDBMS like MariaDB or PostgreSQL is standard practice for web applications expected to handle significant data or traffic.
Drawbacks of Using MariaDB:
- Increased Complexity: Requires setting up and managing an additional container (the MariaDB server).
- Higher Resource Usage: Consumes more RAM than the embedded SQLite database, as the MariaDB server process needs its own memory allocation.
- Configuration: Requires careful configuration of connection details (hostname, user, password, database name) in PhotoPrism's settings.
Steps to Migrate/Set Up with MariaDB:
-
Add MariaDB Service to
docker-compose.yml
: Modify your PhotoPrismdocker-compose.yml
to include a service definition for MariaDB.# /opt/photoprism/docker-compose.yml (Example addition) version: "3.7" services: photoprism: image: photoprism/photoprism:latest container_name: photoprism restart: unless-stopped # --- Add depends_on --- depends_on: mariadb: condition: service_healthy # Wait for MariaDB to be ready # --- Remove/Comment out ports --- # ports: # - "2342:2342" security_opt: - seccomp:unconfined - apparmor:unconfined environment: # --- Change Database Driver --- PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use 'mysql' driver for MariaDB # --- Configure Database Connection (DSN) --- # Format: username:password@tcp(hostname:port)/database?charset=utf8mb4,utf8&parseTime=true # Use 'mariadb' as hostname (service name below) PHOTOPRISM_DATABASE_DSN: "photoprism:YOUR_MARIADB_PASSWORD@tcp(mariadb:3306)/photoprism?charset=utf8mb4,utf8" # --- Other PhotoPrism environment variables --- PHOTOPRISM_ADMIN_USER: "admin" PHOTOPRISM_ADMIN_PASSWORD: "YOUR_PHOTOPRISM_ADMIN_PASSWORD" PHOTOPRISM_SITE_URL: "https://photoprism.yourdomain.com/" PHOTOPRISM_READONLY: "false" # If migrating, set to true initially? See notes. TZ: "Your/Timezone" # PHOTOPRISM_SCAN_INTERVAL: "1h" volumes: - "./originals:/photoprism/originals" - "./storage:/photoprism/storage" # Still needed for cache, sidecars working_dir: "/photoprism" networks: - proxy-network # Assuming still using NPM network # --- Add MariaDB Service Definition --- mariadb: image: mariadb:latest # Use official MariaDB image container_name: photoprism-db restart: unless-stopped security_opt: # Optional: Enhance security if needed - 'no-new-privileges:true' environment: # --- Set MariaDB Root Password (choose a strong one) --- MARIADB_ROOT_PASSWORD: "YOUR_STRONG_ROOT_PASSWORD" # --- Create PhotoPrism Database and User --- MARIADB_DATABASE: "photoprism" MARIADB_USER: "photoprism" MARIADB_PASSWORD: "YOUR_MARIADB_PASSWORD" # Use the same password as in PHOTOPRISM_DATABASE_DSN volumes: # --- Map host directory for persistent database data --- - "./database:/var/lib/mysql" # Store MariaDB data in ./database on host # --- Healthcheck ensures PhotoPrism waits until DB is ready --- healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--user=photoprism", "--password=YOUR_MARIADB_PASSWORD", "--database=photoprism"] interval: 10s timeout: 5s retries: 5 networks: - proxy-network # Connect to the same network networks: proxy-network: external: true name: proxy-network
-
Explanation of Changes:
photoprism
service:depends_on
: Tells Docker Compose to start MariaDB first and wait until its healthcheck passes before starting PhotoPrism.PHOTOPRISM_DATABASE_DRIVER
: Changed fromsqlite
tomysql
.PHOTOPRISM_DATABASE_DSN
: This is the crucial connection string.photoprism
: The username MariaDB will use.YOUR_MARIADB_PASSWORD
: The password for the MariaDB user. Must match theMARIADB_PASSWORD
below.mariadb
: The hostname. Docker Compose networking allows containers on the same network to reach each other using their service name (mariadb
in this case).3306
: Default MariaDB port.photoprism
: The database name. Must matchMARIADB_DATABASE
below.?charset=utf8mb4,utf8
: Important for proper character encoding (supports emojis, etc.).
mariadb
service:image: mariadb:latest
: Uses the official MariaDB image.environment
:MARIADB_ROOT_PASSWORD
: Sets the password for the MariaDB root user (needed for administration, keep it secure).MARIADB_DATABASE
: Tells the MariaDB image to automatically create a database namedphotoprism
on first run.MARIADB_USER
: Creates a user namedphotoprism
.MARIADB_PASSWORD
: Sets the password for thephotoprism
user.
volumes
: Maps./database
on the host to/var/lib/mysql
inside the container. This is where MariaDB stores its actual data files. This directory must be persistent and backed up.healthcheck
: A command Docker runs periodically to check if the database is ready to accept connections.depends_on
uses this.networks
: Connects the MariaDB container to the same network as PhotoPrism.
-
Create Host Database Directory: Before starting, create the directory on the host where MariaDB data will be stored:
-
Start the Services:
Docker Compose will start MariaDB first, wait for the healthcheck, and then start PhotoPrism. Monitor the logs (# Navigate to the directory containing the updated docker-compose.yml cd /opt/photoprism # Pull new images and start services docker compose pull # Get mariadb image docker compose up -d
docker compose logs -f mariadb
anddocker compose logs -f photoprism
) for errors. -
Initial Setup / Migration:
- New Instance: If this is a brand new PhotoPrism setup, it should connect to the new MariaDB database, create the necessary tables, and be ready for initial configuration and indexing.
- Migrating Existing Instance (Advanced): Migrating from SQLite to MariaDB requires exporting data from SQLite and importing it into MariaDB. This is a complex process not fully covered here. The general steps involve:
- Stopping PhotoPrism.
- Using specialized tools or scripts (potentially provided by PhotoPrism or the community, or custom-developed) to dump the relevant data from
index.sqlite
into a format MariaDB can understand (like SQL statements). - Setting up the new MariaDB container (as above).
- Importing the dumped data into the new MariaDB
photoprism
database. - Reconfiguring PhotoPrism's
docker-compose.yml
to use MariaDB (as above). - Starting PhotoPrism, ensuring it connects to MariaDB.
- Potentially running a
photoprism migrations
command if needed (docker compose exec photoprism photoprism migrations
). - Thoroughly checking if all data (metadata, albums, users) is present. Note: Due to the complexity, starting fresh with MariaDB and re-indexing might be simpler unless you have extensive manual metadata/albums you absolutely need to preserve. The PhotoPrism documentation or community forums are the best resources for detailed migration steps if required.
-
Backup: Remember to adjust your backup strategy! You now need to back up:
- The MariaDB host volume (
./database
in the example). The safest way is still to stop themariadb
container before backing up these files, or usemysqldump
to create a logical backup while it's running:This SQL file should then be backed up along with# Example mysqldump command docker compose exec -T mariadb mysqldump --user=photoprism --password=YOUR_MARIADB_PASSWORD --databases photoprism > "${BACKUP_DEST}/config/photoprism_db_backup.sql"
originals
and the rest of thestorage
directory (cache, sidecars).
- The MariaDB host volume (
Switching to MariaDB provides a more scalable and robust backend for larger PhotoPrism libraries, at the cost of slightly increased complexity and resource usage.
Workshop Switching to MariaDB Backend
Goal: Configure a new PhotoPrism instance to use MariaDB as its database backend from the start. (Note: This workshop assumes a fresh start, not a migration.)
Prerequisites:
- Docker and Docker Compose installed.
- Access to the host terminal.
- Directory prepared for PhotoPrism configuration (e.g.,
/opt/photoprism-mariadb
). - (Optional) Nginx Proxy Manager running and a shared network (
proxy-network
) available. If not using NPM, you'll need to expose PhotoPrism's port differently.
Steps:
-
Create Project Directory:
-
Create
docker-compose.yml
: Create a file nameddocker-compose.yml
in/opt/photoprism-mariadb
and paste the following content. Replace placeholder passwords and adjust settings likePHOTOPRISM_SITE_URL
,TZ
, and network name.# /opt/photoprism-mariadb/docker-compose.yml version: "3.7" services: photoprism: image: photoprism/photoprism:latest container_name: photoprism-mariadb-app restart: unless-stopped depends_on: mariadb: condition: service_healthy # No 'ports' section needed if using NPM/reverse proxy security_opt: - seccomp:unconfined - apparmor:unconfined environment: # --- Database Configuration --- PHOTOPRISM_DATABASE_DRIVER: "mysql" # !! Replace YOUR_MARIADB_PASSWORD with a strong password !! PHOTOPRISM_DATABASE_DSN: "photoprism:YOUR_MARIADB_PASSWORD@tcp(mariadb:3306)/photoprism?charset=utf8mb4,utf8" # --- Basic PhotoPrism Settings --- PHOTOPRISM_ADMIN_USER: "admin" # !! Replace YOUR_PHOTOPRISM_ADMIN_PASSWORD with a strong password !! PHOTOPRISM_ADMIN_PASSWORD: "YOUR_PHOTOPRISM_ADMIN_PASSWORD" # !! Replace with your actual URL !! PHOTOPRISM_SITE_URL: "https://photoprism.yourdomain.com/" # Or http://<IP>:port if not using proxy PHOTOPRISM_READONLY: "false" # !! Replace with your timezone !! TZ: "Europe/Berlin" # PHOTOPRISM_SCAN_INTERVAL: "1h" # Uncomment to enable auto-scan # PHOTOPRISM_WORKERS: "0" # Auto-detect workers volumes: - "./originals:/photoprism/originals" - "./storage:/photoprism/storage" - "./import:/photoprism/import" # Optional import folder working_dir: "/photoprism" networks: - proxy-network # Use your shared proxy network or create a default one mariadb: image: mariadb:latest container_name: photoprism-mariadb-db restart: unless-stopped security_opt: - 'no-new-privileges:true' environment: # !! Replace YOUR_STRONG_ROOT_PASSWORD with a strong password !! MARIADB_ROOT_PASSWORD: "YOUR_STRONG_ROOT_PASSWORD" # --- PhotoPrism Database/User Credentials --- MARIADB_DATABASE: "photoprism" MARIADB_USER: "photoprism" # !! Use the SAME password as in PHOTOPRISM_DATABASE_DSN !! MARIADB_PASSWORD: "YOUR_MARIADB_PASSWORD" volumes: - "./database:/var/lib/mysql" # Persist MariaDB data healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--user=photoprism", "--password=YOUR_MARIADB_PASSWORD", "--database=photoprism"] interval: 10s timeout: 5s retries: 5 networks: - proxy-network # Use the same network as PhotoPrism networks: proxy-network: # Adjust if using a different network setup external: true # Assumes 'proxy-network' is defined elsewhere (e.g., by NPM) name: proxy-network
-
Review and Set Passwords:
- Go through the
docker-compose.yml
file. - Replace
YOUR_MARIADB_PASSWORD
with a strong, unique password in both thePHOTOPRISM_DATABASE_DSN
line and theMARIADB_PASSWORD
line. - Replace
YOUR_STRONG_ROOT_PASSWORD
with a secure password for MariaDB's root user. - Replace
YOUR_PHOTOPRISM_ADMIN_PASSWORD
with the desired initial admin password for the PhotoPrism UI. - Verify
PHOTOPRISM_SITE_URL
andTZ
.
- Go through the
-
Launch the Stack:
- Make sure you are in the
/opt/photoprism-mariadb
directory. - Pull the images:
- Start the services:
- Make sure you are in the
-
Monitor Startup:
- Check the logs for both containers to ensure they start correctly and that PhotoPrism successfully connects to MariaDB.
- You might see messages like
photoprism migrations: applying...
which is normal on first startup with a new database.
-
Configure Reverse Proxy (If Applicable):
- If using Nginx Proxy Manager, add a new proxy host for your
photoprism.yourdomain.com
. - Forward to the service name
photoprism
(orphotoprism-mariadb-app
if you used thatcontainer_name
or service name) on port2342
(PhotoPrism's internal HTTP port). - Configure SSL as before.
- If using Nginx Proxy Manager, add a new proxy host for your
-
Access PhotoPrism:
- Navigate to your PhotoPrism URL (
https://photoprism.yourdomain.com
orhttp://YOUR_SERVER_IP:2342
if not using a proxy and you mapped the port - which you'd need to add back to the compose file). - Log in using the
PHOTOPRISM_ADMIN_USER
(admin
) and thePHOTOPRISM_ADMIN_PASSWORD
you set.
- Navigate to your PhotoPrism URL (
-
Verify Setup:
- Navigate through the UI. Add some photos to the
./originals
directory and trigger an index (Library > Index > Start
). - Everything should function as before, but now the metadata and library information are being stored in the MariaDB database (
./database
on the host) instead of an SQLite file within the./storage
directory.
- Navigate through the UI. Add some photos to the
Conclusion: You have successfully deployed a fresh PhotoPrism instance configured to use a MariaDB backend via Docker Compose. This setup is better prepared for handling larger libraries and potentially higher concurrency compared to the default SQLite backend. Remember to include the ./database
host directory and/or MariaDB SQL dumps in your backup routine.
Optimizing Performance (Workers, Cache, Hardware)
Even with a robust database, PhotoPrism's performance depends on various factors, especially during resource-intensive tasks like initial indexing, importing large batches, RAW conversion, AI tagging, and face recognition. Here's how to approach performance tuning:
1. Adjusting Workers:
- What: PhotoPrism uses background "workers" to perform parallel processing tasks (thumbnail generation, RAW conversion, indexing metadata).
- Configuration:
PHOTOPRISM_WORKERS
environment variable indocker-compose.yml
.0
(Default): Auto-detect based on the number of CPU cores available to the container. This is often a good starting point.1
,2
,3
, ...: Set a specific number of workers.
- Tuning:
- Too Few Workers: Indexing/importing might be slow as tasks are processed sequentially or with limited parallelism.
- Too Many Workers: Can overwhelm the system, leading to high CPU load, excessive RAM usage, and disk I/O bottlenecks. This can actually slow down overall performance and make the system unresponsive.
- Recommendation: Start with
0
(auto). If indexing seems slow and your CPU usage is consistently low during indexing, try manually setting it to the number of physical cores your CPU has, or slightly less (e.g.,cores - 1
). If your system becomes unresponsive or disk I/O is maxed out during indexing, reduce the number of workers (e.g., to2
or4
, even if you have more cores). Finding the sweet spot requires monitoring system resources (htop
,docker stats
) during intensive tasks.
2. Managing the Cache:
- What: The
/photoprism/storage/cache
directory stores generated thumbnails, previews, and index data. A warm cache (already populated) significantly speeds up browsing. - Size: The cache can grow very large, potentially consuming hundreds of gigabytes for large libraries, as it stores multiple sizes for each photo/video.
- Impact:
- Disk Space: Ensure the drive hosting the
storage
volume has ample free space. - Disk Speed: A fast SSD (especially NVMe) for the
storage
volume dramatically improves cache read/write speeds, impacting thumbnail loading and indexing performance. Using a slow HDD for the cache volume will bottleneck performance. - Backup: Backing up the cache can be time/space-consuming. Some users exclude it (
--exclude '/photoprism/storage/cache'
) from backups, accepting that PhotoPrism will need to regenerate it after a restore (which can take many hours or days). Others back it up to speed up recovery.
- Disk Space: Ensure the drive hosting the
- Clearing Cache: You can technically stop PhotoPrism and delete the contents of the
cache
directory. PhotoPrism will regenerate it on the next start/index. This can sometimes resolve issues related to corrupted cache files but will result in a period of slow performance as thumbnails are rebuilt. Use the "Purge" option underSettings > Library > Cache
in the UI for a safer way to clear specific parts of the cache if needed.
3. Hardware Considerations:
- CPU:
- Indexing/AI: Multi-core CPUs significantly speed up parallel tasks. Faster clock speeds also help. TensorFlow (AI tagging/face recognition) benefits greatly from modern CPUs with AVX2 instruction set support.
- General Browsing: Less CPU-intensive once the cache is generated.
- RAM:
- Requirement: PhotoPrism itself needs RAM, as does the database (especially MariaDB), and the worker processes. TensorFlow can also be RAM-hungry.
- Recommendation: 4GB is often cited as a minimum for decent performance, but 8GB+ is recommended for larger libraries, especially if using MariaDB and AI features concurrently. Insufficient RAM leads to swapping to disk, drastically reducing performance. Monitor RAM usage with
htop
ordocker stats
.
- Storage:
originals
: Can be on slower, larger HDDs if necessary, as reads are sequential during indexing and direct viewing.storage
(Database, Cache, Sidecars): Strongly recommended to be on an SSD. The random read/write performance of an SSD is crucial for database operations and cache access, significantly impacting both indexing speed and UI responsiveness (thumbnail loading). An NVMe SSD is even better than SATA SSD.- I/O Bottleneck: If your disk I/O wait time is high during indexing (check with
htop
oriostat
), your storage is likely the bottleneck, even with sufficient CPU/RAM.
4. Database Tuning (MariaDB):
- Configuration: MariaDB itself has numerous configuration parameters (e.g., buffer pool size, cache sizes) that can be tuned for performance. This is usually done by mounting a custom configuration file (e.g.,
my.cnf
) into the MariaDB container. - Key Parameters:
innodb_buffer_pool_size
: One of the most critical settings. Controls how much RAM MariaDB uses to cache data and indexes. Setting this appropriately (e.g., 50-70% of the RAM dedicated to the MariaDB container, ensuring enough RAM remains for the OS and PhotoPrism) can drastically improve performance. Requires careful calculation based on available system RAM.- Other parameters like
innodb_log_file_size
,max_connections
, query cache settings.
- Tools: Use tools like
MySQLTuner
ortuning-primer.sh
(runnable against the MariaDB container) to get recommendations based on current usage statistics, but apply changes cautiously. - Complexity: Advanced database tuning requires significant understanding and research. Often, ensuring sufficient RAM and SSD storage provides the biggest gains for typical PhotoPrism use cases.
5. Network:
- Local Access: Ensure your server and client devices have a fast, stable network connection (Gigabit Ethernet is preferred over Wi-Fi if possible) for smooth UI loading.
- Remote Access: Upload/download speeds will be limited by your internet connection if accessing remotely.
Summary of Recommendations:
- SSD for
storage
volume: This often provides the biggest performance boost. - Sufficient RAM: Monitor usage; aim for 8GB+ for larger libraries/AI features.
- Tune Workers: Start with auto (
0
), monitor resources, adjust manually if needed (often downwards if hitting I/O limits, upwards only if CPU is underutilized). - Consider MariaDB: For very large libraries or multi-user scenarios.
- (Advanced) Tune MariaDB: If using MariaDB and still facing bottlenecks, investigate
innodb_buffer_pool_size
.
Performance tuning is an iterative process involving monitoring, making changes, and measuring the impact. Address the most likely bottlenecks (often storage I/O and RAM) first.
Workshop Monitoring Resources and Adjusting Workers
Goal: Monitor system resource usage during a PhotoPrism indexing task and adjust the number of workers to observe the impact on performance and resource consumption.
Prerequisites:
- PhotoPrism running (either SQLite or MariaDB backend).
- A moderate batch of new photos (e.g., 50-100 JPEGs, including some larger files if possible) ready to be added for indexing. Place them in a temporary location first, not yet in
originals
. - Terminal access to the host machine.
htop
installed (sudo apt install htop
) anddocker stats
command available.
Steps:
-
Check Current Worker Setting:
- Examine your PhotoPrism
docker-compose.yml
file. Note the current value ofPHOTOPRISM_WORKERS
(it might be0
for auto, commented out implying auto, or a specific number). Let's assume it's0
(auto) initially.
- Examine your PhotoPrism
-
Prepare Monitoring Tools:
- Open two terminal windows connected to your server.
- Terminal 1: Run
htop
. This provides a real-time overview of CPU usage per core, RAM usage, swap usage, and running processes. Familiarize yourself: Note the CPU bars at the top, Memory/Swap usage, and the process list. PressF6
to sort by CPU or Memory. - Terminal 2: Run
docker stats
. This shows real-time resource usage specifically for your running Docker containers (CPU %, Memory Usage/Limit, Network I/O, Disk I/O). Familiarize yourself: Find the row for yourphotoprism
container (andmariadb
if applicable).
-
Add Photos and Start Indexing (Auto Workers):
- Copy the batch of 50-100 new photos into your PhotoPrism
originals
directory (into an appropriate subfolder). Ensure permissions are correct. - Go to the PhotoPrism Web UI -> Library -> Index.
- Click "Start" to begin indexing the new batch.
- Copy the batch of 50-100 new photos into your PhotoPrism
-
Observe Resources (Auto Workers):
- Switch quickly between your
htop
anddocker stats
terminals. htop
:- Observe the CPU usage bars. Are all cores being utilized? Is usage very high (close to 100% on multiple cores)?
- Check Memory usage. Is it increasing significantly? Are you close to using all available RAM? Is swap being used (this indicates RAM pressure)?
- Look for
photoprism
processes or related threads consuming resources. Note theCPU%
andMEM%
. Check theI/O wait
percentage (often shown in CPU bars or configurable) - high I/O wait suggests a disk bottleneck.
docker stats
:- Look at the
CPU %
for thephotoprism
container. Is it high (e.g., 300% might mean it's using 3 full cores)? - Check the
MEM USAGE / LIMIT
. How much RAM is the container using? - Observe
BLOCK I/O
. Are there significant read/write numbers, potentially indicating heavy disk usage?
- Look at the
- Time the Index: Roughly time how long it takes for the indexing task to complete in the PhotoPrism UI or logs (
docker compose logs -f photoprism
).
- Switch quickly between your
-
Change Worker Count (Example: Reduce):
- Once indexing is finished, let's manually set the workers to a lower number, e.g.,
2
. - Edit your PhotoPrism
docker-compose.yml
. - Add or modify the environment variable:
- Save the file.
- Restart PhotoPrism:
- Once indexing is finished, let's manually set the workers to a lower number, e.g.,
-
Clear Indexed Photos (Simulate Re-indexing):
- To re-index the same batch for comparison, you need to remove them from PhotoPrism's index first. The easiest (though drastic) way for this test is to stop PhotoPrism, delete the database file (if SQLite) or clear the DB tables (if MariaDB - complex!), and delete the
cache
contents. Alternatively, and more simply for this test: Rename the folder containing the test batch withinoriginals
. Trigger a "Cleanup" or "Purge" in PhotoPrism (Settings > Library
), then rename the folder back. Or, just use a different batch of 50-100 photos for the second test. Let's assume you use a new, similar batch for simplicity.
- To re-index the same batch for comparison, you need to remove them from PhotoPrism's index first. The easiest (though drastic) way for this test is to stop PhotoPrism, delete the database file (if SQLite) or clear the DB tables (if MariaDB - complex!), and delete the
-
Add New Photos and Start Indexing (Workers=2):
- Copy a new batch of 50-100 photos into
originals
. - Trigger indexing again from the PhotoPrism UI.
- Copy a new batch of 50-100 photos into
-
Observe Resources (Workers=2):
- Again, monitor
htop
anddocker stats
. - Compare:
- Is the peak CPU usage lower than before? Are fewer cores being heavily utilized?
- Is the peak RAM usage different?
- Is the
BLOCK I/O
or disk I/O wait percentage lower or higher? - How does the indexing time compare to the first run with auto workers? Is it faster or slower?
- Again, monitor
-
(Optional) Change Worker Count (Example: Increase):
- If the previous tests showed low CPU usage and you have many cores, try setting
PHOTOPRISM_WORKERS
to a higher number (e.g., number of physical cores). - Restart PhotoPrism.
- Use another new batch of photos and index again.
- Observe resources and timing. Does increasing workers further improve speed, or does it cause resource contention (high I/O wait, high RAM usage, slower overall time)?
- If the previous tests showed low CPU usage and you have many cores, try setting
-
Analyze and Choose:
- Based on your observations (CPU load, RAM usage, I/O wait, completion time), decide which worker setting provides the best balance for your specific hardware.
- If
0
(auto) performed well without maxing out resources, stick with that. - If auto caused high I/O wait or instability, a lower fixed number (like
2
or4
) might be better. - If auto showed low CPU usage and indexing was slow, a higher fixed number might help, but only if you aren't bottlenecked by disk I/O or RAM.
- Set your preferred value in
docker-compose.yml
and restart PhotoPrism one last time.
Conclusion: You have monitored system resources using htop
and docker stats
while PhotoPrism performed indexing tasks. By adjusting the PHOTOPRISM_WORKERS
setting and observing the impact on CPU, RAM, disk I/O, and overall time, you've gained practical insight into how worker configuration affects performance and how to choose a setting appropriate for your hardware limitations. Remember that the optimal setting might vary depending on the task (indexing vs. face recognition) and your specific hardware.
6. Conclusion
This guide has taken you through the process of setting up, configuring, securing, and optimizing your own self-hosted PhotoPrism instance. Starting with the fundamentals of Docker, you learned how to launch PhotoPrism, import your initial photos, and perform basic organization using labels and albums.
We then progressed to intermediate topics, securing your instance with HTTPS using Nginx Proxy Manager, understanding the crucial role of metadata (EXIF, XMP) and sidecar files, and mastering PhotoPrism's powerful search capabilities.
Finally, we explored advanced techniques, including automating imports with mobile apps via WebDAV, implementing robust backup strategies using rsync
and considering tools like BorgBackup or Duplicati, switching to a more scalable MariaDB backend, and tuning performance by adjusting workers and considering hardware impacts, particularly the importance of SSDs for the storage volume.
Self-hosting PhotoPrism offers significant advantages in terms of privacy, control, and cost-effectiveness compared to relying solely on cloud providers. While it demands a degree of technical engagement for setup and maintenance (especially backups and updates), the reward is complete ownership of your digital memories. The practical workshops provided hands-on experience with each step, from installation and initial configuration to advanced automation and performance monitoring.
Key Takeaways:
- Docker Simplifies Deployment: Containerization makes installing and managing PhotoPrism and its dependencies (like MariaDB or NPM) much easier.
- Reverse Proxies are Essential: Use Nginx Proxy Manager, Traefik, or Caddy for secure HTTPS access.
- Metadata Matters: Understand EXIF, XMP, and sidecar files for effective organization and interoperability.
- Backups are Non-Negotiable: Implement the 3-2-1 rule. Regularly back up both
originals
and thestorage
volume (including the database), and test your restore process. Automate backups using scripts or dedicated software. - Storage Performance is Key: Use an SSD for the
storage
volume (cache, database, sidecars) for the best performance. - Monitor and Tune: Pay attention to CPU, RAM, and Disk I/O during intensive tasks and adjust settings like
PHOTOPRISM_WORKERS
accordingly.
Your journey into self-hosting doesn't end here. The PhotoPrism documentation is an excellent resource for exploring further features, advanced configuration options, and troubleshooting. The self-hosting community (forums, Reddit, etc.) is also a valuable place to seek help and share experiences. Keep your system and PhotoPrism updated, maintain your backups diligently, and enjoy the freedom and control of managing your own photo library!