A PhotoPrism® Portal and its tenant instances share one database server. This guide describes how to use MariaDB Enterprise Server as that database — including running it under the MariaDB Enterprise Operator on Kubernetes/OpenShift — and how to connect it to the Portal.

PhotoPrism connects with the standard MariaDB/MySQL wire protocol and imposes no Enterprise-specific requirements. Any MariaDB 11.4+ server works; MariaDB Enterprise Server 11.8 (LTS) is the recommended baseline for production clusters.

Database Baseline

PropertyDetail
VersionMariaDB Enterprise Server 11.8, a long-term-support release with regular maintenance releases.
ProtocolWire- and SQL-compatible drop-in for the community server; PhotoPrism’s Go driver connects unchanged.
Character setutf8mb4. PhotoPrism pins collation utf8mb4_unicode_ci for table creation, so it only needs that collation to remain available.
AuthenticationPhotoPrism supports mysql_native_password and caching_sha2_password. Keep PhotoPrism/Portal accounts on one of these — do not assign the PARSEC plugin to application accounts.
Storage engineInnoDB (ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci).

Deployment Topologies

Both topologies connect through the same Portal database settings:

  • External MariaDB Enterprise. The database runs as a managed service or a separately operated cluster. Point the Portal’s PHOTOPRISM_DATABASE_SERVER at that endpoint. This keeps the database lifecycle independent of the PhotoPrism release.
  • In-cluster, operator-managed. MariaDB Enterprise runs inside Kubernetes/OpenShift, declared as a MariaDB custom resource and managed by the MariaDB Enterprise Operator (provisioning, failover, backups, TLS). The Portal connects to the operator-created Service, directly or via MaxScale. This is recommended when you want platform-native lifecycle management.

Installing the Operator

On OpenShift, the MariaDB Enterprise (Kubernetes) Operator is Red Hat-certified and published on OperatorHub under the certified-operators catalog (OLM package mariadb-enterprise-operator, channel stable). A Helm install is also offered by MariaDB for plain Kubernetes.

  • Pre-check (OpenShift): oc get packagemanifests -n openshift-marketplace mariadb-enterprise-operator.
  • Install: create a Subscription (cluster-wide via openshift-operators, or scoped via a custom OperatorGroup with targetNamespaces).
  • Images come from the credentialed registry docker.mariadb.com (operator, enterprise-server, maxscale, optional LDAP sidecar) and require a MariaDB Customer Download Token. Provide it via the cluster global pull secret or an imagePullSecret. Air-gapped installs mirror these images to a private registry.
  • SCC (OpenShift): the operator and its operands run under restricted-v2 — non-root, arbitrary UID, dropped capabilities — so no privileged SCC grant is needed. Do not deploy the database into default or kube-system.

Operator field names, resource-naming conventions, and TLS defaults vary by operator release. Confirm them against the exact operator version installed in your cluster before a production rollout.

Declaring the Database

The operator exposes custom resources (confirm the API group/version against your installed operator):

KindPurpose
MariaDBDeploys a server or cluster (standalone, primary/replica, or Galera). Seeds root plus an initial user/database.
DatabaseA logical database (schema).
UserA database user; password supplied via a Secret reference.
GrantPrivilege grants binding a user to a database.
MaxScaleQuery router/proxy with read-write splitting and automated failover.

Generated passwords are stored in Kubernetes Secrets. Applications discover the endpoint through the operator-created Service DNS name (<service>.<namespace>.svc.cluster.local:3306); confirm the exact Service and Secret names with oc get svc,secret -n <db-namespace>.

Provisioning Models

The Portal can either provision tenant databases itself, or consume databases the operator provisions. Choose one.

Preserves dynamic tenant onboarding: when a new tenant registers, the Portal creates its schema and user on demand.

  1. Create a privileged provisioning account in MariaDB Enterprise (a User + Grant with CREATE USER, CREATE, and GRANT OPTION, or the root account from the MariaDB CR’s root Secret) on a driver-compatible auth plugin.
  2. Set the Portal’s PHOTOPRISM_DATABASE_PROVISION_DSN to that account’s DSN in Go mysql form: user:password@tcp(<db-service>.<namespace>.svc.cluster.local:3306)/.
  3. Leave PHOTOPRISM_DATABASE_PROVISION_PREFIX at cluster_, or set a per-environment value when staging and production share one server.
  4. The Portal’s own database (PHOTOPRISM_DATABASE_NAME, default photoprism_portal) must already exist — create it with a Database CR. Tenants leave their database settings blank and receive Portal-provisioned credentials at registration.

Model 2 — Operator-Provisioned (Static / GitOps)

Pre-create every database and user with Database / User / Grant CRs, set explicit database name, user, and password per release, and leave the provisioning DSN empty so the Portal does not attempt to create schemas. This trades dynamic onboarding for fully declarative, auditable database resources and avoids granting the Portal a privileged account.

Mapping Database Settings

SettingSource from the operator
PHOTOPRISM_DATABASE_SERVERMariaDB (or MaxScale) Service DNS + port, e.g. <svc>.<namespace>.svc.cluster.local:3306
PHOTOPRISM_DATABASE_NAMEThe Database CR for this release (Portal default photoprism_portal)
PHOTOPRISM_DATABASE_USER/PASSWORDThe User CR + its password Secret (or blank on tenants for Portal provisioning)
PHOTOPRISM_DATABASE_PROVISION_DSNDSN built from the privileged provisioning User/root Secret (Portal, Model 1)

See Config Options for the full set of database variables.

Connection Routing & Proxy

Connect either directly to the MariaDB Service or through MaxScale, MariaDB Enterprise’s native router:

  • Standalone (no proxy): point PHOTOPRISM_DATABASE_SERVER directly at the MariaDB Service on 3306.
  • MaxScale (recommended for HA topologies): point PHOTOPRISM_DATABASE_SERVER at the MaxScale Service (SQL listener on 3306; admin/REST API on 8989). MaxScale routes provisioned accounts to the backend automatically — there is no separate account-sync step.

ProxySQL is not used with MariaDB Enterprise — MaxScale is the proxy. Leave any ProxySQL account-sync settings empty.

Transport Security (TLS)

The MariaDB Enterprise Operator can issue and rotate TLS certificates or consume a cert-manager issuer. Whether TLS is enforced by default depends on the operator version.

When PhotoPrism connects using the discrete server/user/password fields, it builds its DSN without a tls= parameter, so client-side TLS is not configured on that path. Options, in order of preference:

  1. In-cluster network security (default). Keep Portal↔database traffic on the pod network within one namespace and restrict access with NetworkPolicies. This is the pragmatic baseline for a single-namespace operator deployment.
  2. Encrypted client connections via a full DSN. PhotoPrism honors a complete PHOTOPRISM_DATABASE_DSN (with a ? query string) including a tls= parameter. tls=skip-verify encrypts without verifying the server certificate; verified TLS (tls=custom) additionally requires registering the operator CA bundle in-process.
  3. Terminate at MaxScale. Enable TLS between MaxScale and the backend while the Portal connects to MaxScale. MaxScale cannot serve TLS and non-TLS on the same listener simultaneously.

Recommendation: start with option 1 plus NetworkPolicies, and move to a full DSN with a tls= parameter if you require verified client-to-database encryption.

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: