The PhotoPrism® Portal is a central management server for running several PhotoPrism® instances as a cluster. Instead of configuring and maintaining each instance on its own, the Portal provides shared single sign-on, centralized access control, consistent branding, and a single place to register and manage instances.

Running a Portal-managed cluster is only available with our team plans, not the personal editions.

What the Portal Does

A Portal combines several roles that would otherwise have to be set up separately for every instance:

  • Identity provider — users sign in once at the Portal, which then logs them in to the instances they are allowed to use. See Cluster Authentication & Access Control.
  • Node registry — keeps track of every registered instance, its address, role, and database, and issues the credentials each instance uses to talk to the Portal.
  • Theme distributor — stores a single branding theme that instances download and keep in sync automatically.
  • Optional reverse proxy — can serve several instances under one shared domain using /i/<name>/ paths, so you do not need a separate proxy or a certificate per instance.

Cluster Architecture

A cluster consists of one Portal and one or more nodes. Each node has a role:

  • instance — a regular PhotoPrism® instance that serves photos to end users.
  • service — a supporting service node (for example, a shared computer-vision worker) that is not a user-facing instance.

The Portal itself is also a node, with the reserved portal role. Nodes never talk to each other directly; they communicate only with the Portal over HTTPS, authenticated with credentials issued when they join the cluster.

You can run a cluster in one of two network layouts:

LayoutHow it worksWhen to choose it
Separate hostnamesEvery instance has its own hostname and TLS certificate (e.g. acme.example.com).Maximum isolation between instances; strict per-host separation of cookies and storage.
Shared domainThe Portal proxies instances under one hostname via /i/<name>/ paths.Fewer certificates and DNS entries, a single entry point, and simpler testing.

See Shared Domain Routing for details on the second option.

Requirements

  • A dedicated hostname for the Portal (for example, portal.example.com) reachable by all instances.
  • HTTPS with valid certificates on the Portal and on every public instance — secure connections are a strict requirement for single sign-on. Instances may talk to the Portal over plain HTTP only on a trusted, cluster-internal network.
  • A MariaDB server the Portal can use to provision per-instance databases (when you want the Portal to manage instance databases automatically).
  • A lowercase DNS cluster domain (1–63 characters per label) that identifies the cluster and is used to derive default URLs.

Setting Up the Portal

The Portal is started from the photoprism/portal Docker image. At a minimum it needs the cluster domain and, if it should provision instance databases, an administrative database connection:

services:
  portal:
    image: photoprism/portal:latest
    environment:
      PHOTOPRISM_SITE_URL: "https://portal.example.com/"
      PHOTOPRISM_CLUSTER_DOMAIN: "example.com"
      ## Administrative database connection used to create per-instance
      ## databases and users (kept on the Portal only):
      PHOTOPRISM_DATABASE_PROVISION_DSN: "root:[admin-password]@tcp(mariadb:3306)/"
    ...

When the Portal starts for the first time, it creates a superadmin account and generates a join token that instances use to register (see Adding Instances). The Portal acts as the cluster’s identity provider out of the box; the issuer URL and token lifetimes can be tuned with the PHOTOPRISM_PORTAL_OIDC_* config options.

Provisioned databases and users are named automatically from the cluster and node identifiers, with a configurable prefix (PHOTOPRISM_DATABASE_PROVISION_PREFIX, default cluster_). The administrative connection is used only to create and rotate these credentials and is never shared with instances.

For Kubernetes deployments, the photoprism-pro Helm chart can register instances with a Portal automatically. See Getting Started with Rancher and Kubernetes for cluster networking and firewall requirements.

Adding Instances

Instances join the cluster by registering with the Portal using the join token. Registration is idempotent and safe to repeat on every start: a new instance receives its credentials on first boot, and an existing instance simply confirms its registration.

Zero-Touch Registration

The recommended approach is to let each instance register itself on startup. Provide the cluster domain, the Portal URL, and the join token as environment variables, and the instance registers automatically the first time it boots and on every restart:

services:
  photoprism:
    image: photoprism/pro:latest
    environment:
      PHOTOPRISM_CLUSTER_DOMAIN: "example.com"
      PHOTOPRISM_PORTAL_URL: "https://portal.example.com/"
      PHOTOPRISM_JOIN_TOKEN: "[join-token]"
      PHOTOPRISM_NODE_ROLE: "instance"
      PHOTOPRISM_NODE_NAME: "acme"
      PHOTOPRISM_SITE_URL: "https://acme.example.com/"
    ...

If PHOTOPRISM_NODE_NAME is omitted, the instance derives a name from its hostname. If PHOTOPRISM_PORTAL_URL is omitted, it defaults to https://portal.<cluster-domain>. The join token must be at least 24 characters long.

On first boot the instance receives its own OAuth credentials from the Portal, and — when it uses a MariaDB database without existing credentials — a provisioned database. Database changes require a restart to take effect. The instance never migrates an existing SQLite database to MariaDB automatically.

Registering from a Terminal

You can also register a node explicitly with the photoprism cluster register command, for example to preview the request or to write the returned credentials to the local configuration:

photoprism cluster register --name acme --role instance --write-config

Learn more ›

Shared Domain Routing

Instead of giving every instance its own hostname, the Portal can serve them all under a single domain and forward requests based on the first path segment:

https://media.example.com/i/acme/
https://media.example.com/i/contoso/

The Portal resolves the name after /i/ to the matching instance and proxies the request to it. Unknown names return a generic not found response so the cluster does not reveal which instances exist.

To use shared-domain routing:

  1. Enable path routing on the Portal (PHOTOPRISM_PORTAL_PROXY: "true"; the path prefix defaults to /i/ and can be changed with PHOTOPRISM_PORTAL_PROXY_URI).
  2. Register each instance with a unique name and set its PHOTOPRISM_SITE_URL to the matching path, for example https://media.example.com/i/acme/.
  3. Point each instance’s advertise URL at an address the Portal can reach internally.

Because all instances share one origin in this layout, browser cookies and storage are scoped per instance path. For the strictest isolation between instances, use separate hostnames instead.

Theme & Branding Sync

The Portal stores a single branding theme (logos, colors, login background) and distributes it to instances. On startup, each instance compares its installed theme with the Portal’s version and downloads the current theme when it is missing or out of date, so a branding change made once on the Portal propagates across the cluster. Administrator customizations made directly on an instance are preserved.

You can also pull the theme on demand with photoprism cluster theme pull.

Managing the Cluster

Once the cluster is running, you manage it from the Portal:

  • Web interface — the Portal management UI lists registered instances, lets you edit their details, and manages which users can access which instances.
  • Command line — the photoprism cluster commands cover registration, listing and inspecting nodes, rotating credentials, granting user access, and theme distribution.

For how users sign in and how access to instances is granted, see Cluster Authentication & Access Control.

PhotoPrism® Documentation

For more information on specific features, services and related resources, please refer to the other documentation available in our Knowledge Base and User Guide: