Cards / photoprism

App card

photoprism

Fit 4/5

Photo Galleries · passed 2 Nov 2026

  • Open door Anyone can reach it, behind the app's own sign-in.
  • Keeps it safe 4 volumes of your data, backed up and checked after a move.
  • Keeps secrets Its passwords are made on your machine, seen by nobody.

PhotoPrism, a private photo library with face, place and label search, on MariaDB

Memory
2 GB
Disk
5 GB
Runs on
Intel · ARM

Stewarded by edgible-org · AGPL-3.0-onlyEdgible cards 49/53

passed 2026-11-02, Edgible 1.4.29Added 1 November 2026License AGPL-3.0-onlyStewarded by edgible-org (opens in a new tab)App home page (opens in a new tab)Source on GitHub (opens in a new tab)

The apps, ports, auth modes, and places in the photoprism card

Apps

AppWhatWho can reach itPlace
photoprismPhotoPrism, the web interface and WebDAV phone uploadsopen to anyonephotoprism

Machine

A place is one serving device. Minimum recommended for each:

PlaceMemoryDiskArchitectureGPU
photoprism2 GB5 GBamd64, arm64none

First start

The first start downloads the app's images: about 1.1 GB, a few minutes on a typical home connection. That time is the download from the app's registry, not Edgible, and it happens once: later starts and upgrades reuse the images and fetch only what changed.

What it keeps

VolumeWhat it is
photoprism-originalsyours alone: backed up, and checked after a restore or a move
photoprism-storageyours alone: backed up, and checked after a restore or a move
photoprism-db-datayours alone: backed up, and checked after a restore or a move
photoprism-secretsyours alone: backed up, and checked after a restore or a move

After a restore or a move, a quick count shows the data arrived, with nothing read but numbers and dates.

What it protects

Self-hosting fit

4 of 5 checks passed. Each is a fact about the app, not an opinion: how they are decided (opens in a new tab).

Needs it answers

Setting it up by hand? Install Edgible from edgible.com (opens in a new tab), then follow the steps below.

Why

You want your phone photos and your family's in one private place, searchable by face, place, and what is in them, without handing them to a cloud service. PhotoPrism (opens in a new tab) is a photo library that indexes pictures on a server you own and finds them by people, places, and labels. This card runs it on a machine you control, through Edgible, with its own sign-in.

What

One app, photoprism, with its MariaDB database. It is published on one hostname with auth mode none: the web interface and the WebDAV address that phone apps such as PhotoSync upload to are the same address, and a phone app cannot get past an Edgible sign-in, so PhotoPrism's own login is the protection. PhotoPrism has no public sign-up: it makes one admin at its first start, from a password made on the machine, and you add family under Settings, Users. If you only browse from the web, or your photos are sensitive, change the hostname to org after Publish with edgible app update, and upload from home Wi-Fi or by copying files in, or do not publish it at all. Add disk encryption and an encrypted off-site backup of the volumes. Photos of patients, clients, or children carry legal duties: use this card as a prototype with consented or test photos only, and take real data to compliant hosting with advice.

The photos are in the volume photoprism-originals; the library's index, with faces, places and labels, is in photoprism-db-data; settings, sidecar files and thumbnails are in photoprism-storage; the passwords are in photoprism-secrets. The photos grow with your library, so give the machine room for it: the card's 5 GB is the application and its first data, not your photos. Minimum recommended for the place photoprism: 2 GB of memory and 5 GB of disk, on an arm64 or amd64 machine, with no GPU.

The Compose file is docker-compose.yml (opens in a new tab), the settings card.env (opens in a new tab), the card card.yml (opens in a new tab).

How

Five steps. Edit card.env (opens in a new tab) before you start.

1. Fetch

mkdir -p photoprism
curl -fsSL https://github.com/edgible-org/cards/archive/refs/heads/main.tar.gz \
  | tar -xz --strip-components=2 -C photoprism cards-main/photoprism

2. Edit card.env

Set DEVICE and ORG_LABEL. PHOTOPRISM_ADMIN_USER is the admin's name.

nano photoprism/card.env

3. Check

curl -fsSLo check-env.py https://raw.githubusercontent.com/edgible-org/card-kit/main/check-env.py
python3 check-env.py photoprism

It moves a taken port, as lines to paste. Run it again until it says no conflicts.

4. Start

docker compose --env-file photoprism/card.env -f photoprism/docker-compose.yml pull
docker compose --env-file photoprism/card.env -f photoprism/docker-compose.yml up -d --wait
docker compose --env-file photoprism/card.env -f photoprism/docker-compose.yml ps

The first start downloads the app's images from the registries named in the Compose file, which takes longer for a larger app. pull does that download on its own, so you can see it. The time is the download, not Edgible, and it happens once: later starts and upgrades reuse the images on the machine and fetch only what changed. --wait returns when each service is running, and healthy when it has a healthcheck. PhotoPrism makes the admin, with the password the card made, the first time it starts, so there is no setup page for a stranger to reach and no prepare.sh. The first start also prepares the index, so allow a minute or two before it is healthy.

5. Publish

set -euo pipefail
set -a
. photoprism/card.env
set +a
device_id=$(edgible device list --json | jq -er --arg name "$DEVICE" '
  map(select(.name == $name))
  | if length == 1 then .[0].id
    else error("need exactly one device named " + $name + " (" + (map(.status + " " + .id) | join(", ")) + ")")
    end
')
edgible app create existing \
  --non-interactive \
  --name photoprism \
  --port "$PHOTOPRISM_PORT" \
  --protocol https \
  --auth-modes none \
  --device-id "$device_id"
edgible app list

Without Edgible: only Publish is Edgible's. The app listens on 127.0.0.1 at the port in card.env, so any reverse proxy or tunnel on the machine, such as Caddy, nginx, Cloudflare Tunnel or Tailscale, can publish it instead, and sign-in is then that tool's to provide. Every other step stays the same.

Verify

photoprism uses none.

curl -sS -o /dev/null -w '%{http_code}\n' "https://<photoprism hostname>"

Answers with PhotoPrism's sign-in page, open to the internet, so the sign-in is the protection. Sign in as PHOTOPRISM_ADMIN_USER with the password photoprism-secrets made. To upload from a phone, add the WebDAV address https://<photoprism hostname>/originals/ in a phone app, with that sign-in or, better, an app password made under Settings, Account.

The rest of the setup is in the PhotoPrism user guide docs (opens in a new tab).

Tear down

Four steps, in this order. Step 1 runs wherever edgible is logged in. Steps 2 to 4 run on the machine that runs the containers. Steps 2 and 3 read card.env, so keep it until step 4.

1. Unpublish

edgible app delete photoprism --yes

2. Stop

docker compose --env-file photoprism/card.env -f photoprism/docker-compose.yml down

3. Delete the data

Skip this step to keep the data. The loop copies each volume to a .tgz file in this directory first.

for volume in $(docker volume ls -q --filter label=com.docker.compose.project=photoprism); do
  docker run --rm -v "$volume:/data:ro" -v "$PWD:/backup" alpine tar -czf "/backup/$volume.tgz" -C /data .
done
docker compose --env-file photoprism/card.env -f photoprism/docker-compose.yml down --volumes

4. Remove the card

rm -rf photoprism