# How to self-host PhotoPrism with Docker Compose

> Deploy PhotoPrism with Docker Compose and MariaDB: originals folder, admin password, indexing, HTTPS reverse proxy, backups and upgrades in 20 minutes.

## Key facts

| Fact | Value |
|---|---|
| App | PhotoPrism (https://appsgit.com/apps/photoprism) |
| Difficulty | beginner |
| Time | about 20 minutes |
| Requirements | 2 vCPU / 4 GB RAM (plus swap for large libraries); Docker + Docker Compose v2; Your existing photo library on local or NAS storage; A domain name (optional, for HTTPS) |
| Last updated | 2026-10-06 |

## What is PhotoPrism?

PhotoPrism is an AI-powered photo management app for browsing, organising and sharing your photo and video collection. It is open source under the AGPL-3.0 license and indexes existing folders without moving them, then adds automatic tagging, face recognition, places on a world map and powerful search. It works in any browser and can be installed as a progressive web app.

## Requirements

- A Linux server with 2 CPU cores and 4 GB of RAM, plus swap. More cores make indexing faster.
- Docker Engine and Docker Compose v2.
- Your photo library in a folder on the server or a mounted NAS share.
- Local SSD storage for the database and the cache folder.

## Step 1: Prepare the server

This guide assumes Ubuntu 24.04 with Docker installed. If you need Docker, follow the [official install guide](https://docs.docker.com/engine/install/ubuntu/). Create a project folder and check that you have swap:

```bash
mkdir -p ~/photoprism/{storage,database} && cd ~/photoprism
free -h
```

If `Swap` shows 0, add a 4 GB swap file before indexing a large library.

## Step 2: Create the Docker Compose file

This is a trimmed version of the official Compose file with MariaDB, which the developers recommend over SQLite. Save as `docker-compose.yml`:

```yaml
services:
  photoprism:
    image: photoprism/photoprism:latest
    restart: unless-stopped
    stop_grace_period: 15s
    depends_on:
      - mariadb
    security_opt:
      - seccomp:unconfined
      - apparmor:unconfined
    ports:
      - "2342:2342"
    environment:
      PHOTOPRISM_ADMIN_USER: "admin"
      PHOTOPRISM_ADMIN_PASSWORD: "${ADMIN_PASSWORD}"
      PHOTOPRISM_AUTH_MODE: "password"
      PHOTOPRISM_SITE_URL: "https://photos.example.com/"
      PHOTOPRISM_DISABLE_TLS: "true"
      PHOTOPRISM_ORIGINALS_LIMIT: 5000
      PHOTOPRISM_DATABASE_DRIVER: "mysql"
      PHOTOPRISM_DATABASE_SERVER: "mariadb:3306"
      PHOTOPRISM_DATABASE_NAME: "photoprism"
      PHOTOPRISM_DATABASE_USER: "photoprism"
      PHOTOPRISM_DATABASE_PASSWORD: "${DB_PASSWORD}"
      PHOTOPRISM_SIDECAR_YAML: "true"
      PHOTOPRISM_BACKUP_DATABASE: "true"
      PHOTOPRISM_BACKUP_SCHEDULE: "daily"
    working_dir: "/photoprism"
    volumes:
      - "/srv/photos:/photoprism/originals"
      - "./storage:/photoprism/storage"

  mariadb:
    image: mariadb:12.3
    restart: unless-stopped
    stop_grace_period: 15s
    security_opt:
      - seccomp:unconfined
      - apparmor:unconfined
    command: --innodb-buffer-pool-size=512M --transaction-isolation=READ-COMMITTED --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --max-connections=512 --innodb-rollback-on-timeout=OFF --innodb-lock-wait-timeout=120
    volumes:
      - "./database:/var/lib/mysql"
    environment:
      MARIADB_AUTO_UPGRADE: "1"
      MARIADB_INITDB_SKIP_TZINFO: "1"
      MARIADB_DATABASE: "photoprism"
      MARIADB_USER: "photoprism"
      MARIADB_PASSWORD: "${DB_PASSWORD}"
      MARIADB_ROOT_PASSWORD: "${DB_ROOT_PASSWORD}"
```

Create `.env`:

```bash
ADMIN_PASSWORD=CHANGE_ME
DB_PASSWORD=CHANGE_ME
DB_ROOT_PASSWORD=CHANGE_ME
```

Generate each value with `openssl rand -hex 32`. The admin password must be 8 to 72 characters, which a 64-character hex string meets. Change `/srv/photos` to the folder holding your library. `PHOTOPRISM_SITE_URL` must match the public URL, including the trailing slash. The [official Compose file](https://dl.photoprism.app/docker/compose.yaml) lists every other option, including hardware transcoding and an optional Ollama service for AI captions.

## Step 3: Start and open the app

```bash
docker compose up -d
docker compose logs -f photoprism
```

Open `http://YOUR_SERVER_IP:2342` and sign in as `admin` with the password from `.env`. The admin password variable only applies on first start; change it later in Settings, Account. Then go to Library, Index and click "Start" to scan your originals. The first index of a large library can take hours because PhotoPrism creates thumbnails and runs image classification and face detection.

## Step 4: Put it behind HTTPS

With [Caddy](https://caddyserver.com/docs/):

```caddyfile
photos.example.com {
    reverse_proxy 127.0.0.1:2342
}
```

PhotoPrism uses WebSockets for live updates, which Caddy passes through. With Nginx Proxy Manager, enable "Websockets Support" and raise the upload size limit. After HTTPS works, change the port mapping to `"127.0.0.1:2342:2342"`.

## Backups and upgrades

Back up your originals folder (your photos) and `./storage`, which holds settings, sidecar YAML files with your edits and labels, and the automatic daily database dumps in `storage/backup`. The thumbnail cache in `storage/cache` can be regenerated and may be excluded to save space. You can also create a database dump manually with `docker compose exec photoprism photoprism backup -i -f`.

Upgrade with:

```bash
docker compose pull && docker compose up -d
```

`MARIADB_AUTO_UPGRADE` updates the database system tables automatically when the MariaDB image changes.

## Troubleshooting

- **Indexing stops or the container restarts:** the server is running out of memory. Add swap or RAM, or lower `PHOTOPRISM_WORKERS`.
- **Login fails after changing the password in `.env`:** the variable is only used on first start. Reset it with `docker compose exec photoprism photoprism passwd admin`.
- **Broken links or wrong URLs in shares:** `PHOTOPRISM_SITE_URL` does not match the address you use.
- **Database connection errors on first start:** MariaDB was still initialising. Run `docker compose restart photoprism`.

## Next steps

Name people in the People section, create albums and share links, set up WebDAV or the PhotoSync app for phone uploads, and schedule regular indexing with `PHOTOPRISM_INDEX_SCHEDULE`.

## FAQ

### What port does PhotoPrism use?

PhotoPrism listens on port 2342. The official Compose file serves it with a self-signed certificate by default; this guide disables built-in TLS and lets a reverse proxy handle HTTPS.

### Is PhotoPrism free?

Yes. PhotoPrism Community Edition is free and open source under the AGPL-3.0 license. Paid memberships add extras such as higher-detail maps and support the developers.

### Does PhotoPrism modify my original photos?

No. PhotoPrism reads your originals folder and writes thumbnails, sidecar files and the index to a separate storage folder. You can also set PHOTOPRISM_READONLY to true to guarantee it never writes to originals.

### PhotoPrism vs Immich?

PhotoPrism excels at indexing and browsing an existing library on a NAS through the browser. Immich is built around automatic phone backup with native mobile apps, closer to a Google Photos replacement.

### How much RAM does PhotoPrism need?

The developers recommend at least 4 GB of RAM and enough swap, because indexing large RAW files and videos can briefly use a lot of memory. Too little memory makes indexing crash or restart.

Prefer not to do it yourself? [appsgit installation help](https://appsgit.com/services/install) installs it on your server for a fixed quote.

---

Canonical page: https://appsgit.com/guides/photoprism
Source: appsgit (https://appsgit.com), the app store for github. Data from the GitHub API, refreshed nightly.
Machine access: JSON API https://appsgit.com/api/v1/apps (OpenAPI: https://appsgit.com/openapi.json), MCP server https://mcp.appsgit.com/mcp, full index https://appsgit.com/llms-full.txt.
