Media & Entertainment Azure

PhotoPrism on Ubuntu 24.04 on Azure User Guide

| Product: PhotoPrism 260601 on Ubuntu 24.04 LTS on Azure

Overview

PhotoPrism is an AI-powered, self-hosted application for browsing, organising and sharing your photos and videos. It indexes your collection into a fast, searchable library, automatically tags what is in each picture and groups faces, places and moments, so you can find any shot in seconds - all on infrastructure you control rather than a third-party photo service. The cloudimg image installs PhotoPrism 260601 as the official container paired with MariaDB, runs it behind nginx as a systemd service, and even indexes a small demo library on first boot, so your photo library is online and ready to explore within minutes of launch.

What is included:

  • PhotoPrism 260601 (AGPL-3.0) deployed from the official photoprism/photoprism Docker image, pinned so the image never silently upgrades at build time
  • Docker Engine (Docker CE) + the Docker Compose plugin, installed from the official Docker package repository
  • The PhotoPrism stack: the photoprism container (the Go application with bundled TensorFlow models, ffmpeg, libheif and RAW converters) and mariadb (mariadb:11, PhotoPrism's recommended index database), run together via Docker Compose on a private network
  • Automatic tagging and face recognition powered by the bundled TensorFlow models, running entirely on CPU - no GPU instance required
  • A system nginx reverse proxy on port 80 forwarding to PhotoPrism on 127.0.0.1:2342, with the WebSocket upgrade headers and a raised upload limit for large photos and videos
  • All stateful data - the MariaDB database, your imported originals and the thumbnail and sidecar storage tree - on a dedicated 64 GiB data disk mounted at /var/lib/photoprism (Docker's data-root is relocated there), independently resizable and re-provisioned on every VM
  • A per-VM administrator account and fresh MariaDB user and root passwords, all generated at first boot, plus a small public-domain demo library indexed so the grid is populated on your first sign-in
  • Four systemd units: docker.service, nginx.service, photoprism.service (a wrapper around docker compose up -d) and photoprism-firstboot.service
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key, and a VNet plus subnet. Standard_B2ms (2 vCPU / 8 GB RAM) is the recommended size - PhotoPrism loads the TensorFlow classification and face models into memory and MariaDB adds its buffer pool, so 8 GB gives comfortable headroom for indexing. NSG inbound rules: allow 22/tcp from your management CIDR for SSH and 80/tcp from the CIDR that needs the PhotoPrism web app (add 443/tcp if you enable HTTPS).

Step 1: Connect over SSH

Replace <vm-ip> with the public IP of your VM. The default login user is azureuser.

ssh azureuser@<vm-ip>

Step 2: Confirm the services are active

sudo systemctl is-active docker.service photoprism-firstboot.service photoprism.service nginx.service
sudo ss -tlnp | grep -E ':80 |2342'

You should see active printed four times. The ss output shows nginx listening publicly on port 80, while PhotoPrism is bound to the loopback interface only on 127.0.0.1:2342 - nginx is the only service exposed on the public interface.

Docker, first-boot, PhotoPrism and nginx systemd services active, with nginx public on port 80 and PhotoPrism on loopback 2342

Step 3: Confirm the PhotoPrism containers are running

grep image /opt/photoprism/compose.yaml
cd /opt/photoprism && sudo docker compose --env-file .env -f compose.yaml ps --format "table {{.Name}}\t{{.Image}}\t{{.Status}}"

You should see the pinned image tags and the two containers - photoprism-photoprism-1 and photoprism-mariadb-1 - both in the Up state (MariaDB reports healthy).

The pinned PhotoPrism Compose stack running: the PhotoPrism app and MariaDB

Step 4: Confirm the data disk and read the per-VM credentials

All stateful PhotoPrism data - the MariaDB database, your imported originals and the thumbnail and sidecar storage - lives on a dedicated data disk mounted at /var/lib/photoprism. A unique administrator password and fresh database secrets are generated for your instance on its first boot and written to a root-only file.

df -h /var/lib/photoprism
sudo cat /root/photoprism-credentials.txt

The credentials file lists PHOTOPRISM_URL (where to sign in), PHOTOPRISM_ADMIN_USER (admin) and PHOTOPRISM_ADMIN_PASSWORD. Store the password somewhere safe.

The dedicated PhotoPrism data disk mounted at /var/lib/photoprism and the root-only per-VM credentials file with the password redacted

Step 5: Check the endpoint and the security model

The nginx reverse proxy serves PhotoPrism's unauthenticated /api/v1/status readiness endpoint on port 80, and every protected action requires the per-VM administrator credentials.

curl -s http://localhost/api/v1/status
U=admin
P=$(sudo grep '^PHOTOPRISM_ADMIN_PASSWORD=' /root/photoprism-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w "wrong password -> HTTP %{http_code}\n" -X POST http://localhost/api/v1/session \
  -H 'Content-Type: application/json' -d "{\"username\":\"$U\",\"password\":\"wrong\"}"
curl -s -X POST http://localhost/api/v1/session -H 'Content-Type: application/json' \
  -d "{\"username\":\"$U\",\"password\":\"$P\"}" | grep -o '"access_token"' | head -1

/api/v1/status returns {"status":"operational"}, a wrong password is rejected with HTTP 401, and the correct per-VM password returns an access_token - confirming the appliance is up and that there is no default or shared login.

PhotoPrism serving through nginx: the status endpoint operational, a wrong password rejected and the per-VM admin authenticated end to end

Step 6: Sign in to PhotoPrism

Open http://<vm-ip>/ in your browser. Enter admin as the username and the PHOTOPRISM_ADMIN_PASSWORD from Step 4, then click Sign in.

The PhotoPrism sign-in page

Step 7: Browse your photo library

After signing in you land on the library grid. A small demo library of public-domain photos has already been indexed for you, so the grid shows real thumbnails from the moment you arrive. Each tile shows the picture, its file name and its dimensions.

The PhotoPrism library grid showing the indexed demo photos with rendered thumbnails

Click any picture to open it full screen in the viewer, where you can page through your photos, zoom, and open the details panel for the metadata, labels and location extracted on indexing:

A photo opened full screen in the PhotoPrism viewer

Step 8: Explore places, search and albums

The left navigation gives you the full PhotoPrism experience: search across your whole library, an interactive Places map that plots geotagged photos, a Calendar view, Albums, Labels (the automatic AI tags), Faces and more.

The PhotoPrism interactive places map view

To add your own photos, either upload them from the web UI with the Upload button, or copy files into /var/lib/photoprism on the data disk and start an index from the Library menu - PhotoPrism extracts the metadata, generates thumbnails, tags the content with machine learning and recognises faces. The demo photos are just sample content; you can select and delete them at any time.

Managing the stack

The PhotoPrism stack is wrapped by the photoprism.service systemd unit, which runs docker compose up -d from /opt/photoprism.

sudo systemctl restart photoprism.service
sudo systemctl status photoprism.service --no-pager

To inspect the application logs, tail the PhotoPrism container:

cd /opt/photoprism
sudo docker compose --env-file .env -f compose.yaml logs --tail 50 photoprism

PhotoPrism configuration lives in /opt/photoprism/compose.yaml and the per-VM secrets in /opt/photoprism/.env. By default this image disables PhotoPrism's quality-review filter so all indexed photos appear in the main library view immediately; you can re-enable review under Settings > Library if you prefer to approve lower-quality pictures before they show.

Enabling HTTPS

The image serves plain HTTP on port 80. For any public deployment, put TLS in front with your own domain. Point a DNS A record at the VM public IP, then install a certificate with certbot's nginx plugin. Outline:

  • Install certbot and the nginx plugin from the Ubuntu repositories.
  • Run certbot against your domain to obtain and install a certificate into the nginx site.
  • Once TLS is terminating at nginx, set PHOTOPRISM_SITE_URL=https://your-domain/ in /opt/photoprism/.env, then restart the stack with sudo systemctl restart photoprism.service so PhotoPrism generates correct https:// links and share URLs.

Use your own registered domain in place of any example placeholder.

Maintenance

The OS receives unattended security updates. To update PhotoPrism itself, edit the pinned image tag in /opt/photoprism/compose.yaml, then from /opt/photoprism run sudo docker compose --env-file .env -f compose.yaml pull followed by sudo systemctl restart photoprism.service. Always snapshot the /var/lib/photoprism data disk before a major version upgrade.

Support

Backed by 24/7 cloudimg support. PhotoPrism and MariaDB are trademarks of their respective owners. This image is provided by cloudimg and is not affiliated with or endorsed by the PhotoPrism project or MariaDB.