Merge branch 'develop' into feature/oidc-v2

This commit is contained in:
Michael Mayer 2021-10-23 18:52:44 +02:00
commit 1b2e60a7eb
21 changed files with 976 additions and 206 deletions

55
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,55 @@
---
name: Bug Report
about: Create a report to help us improve
title: 'Bug: Short Issue Description'
labels: bug
assignees: ''
---
PLEASE USE GITHUB ISSUES ONLY TO REPORT CLEARLY IDENTIFIED BUGS - THANK YOU!
Use GitHub Discussions or our Community Chat if you need assistance and for general questions:
- https://github.com/photoprism/photoprism/discussions
- https://gitter.im/browseyourlife/community
Sponsors receive direct technical support via email:
- https://photoprism.app/contact
**What does not work as expected?**
A clear and concise description of what the bug is.
**How can we reproduce it?**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**What behavior do you expect?**
A clear and concise description of what you expected to happen.
**Can you provide us with example files for testing or screenshots?**
Please add example files or screenshots that help to reproduce your problem.
You may also send files via email or share a download link:
https://photoprism.app/contact
**What version you are using?**
Your app version / build number can be found in *Settings* when you scroll to the bottom.
**Any other helpful information?**
If you are reporting a UI or performance issue, please always provide details about your...
- Web browsers
- operating systems
- installed memory
- and processors

View file

@ -0,0 +1,29 @@
---
name: Feature Request
about: Suggest a new feature or improvement
title: " "
labels: idea
assignees: ''
---
PLEASE ONLY SUBMIT A NEW IDEA AFTER YOU HAVE VERIFIED THAT NO SIMILAR ISSUE ALREADY EXISTS - THANK YOU!
- Roadmap: https://github.com/photoprism/photoprism/projects/5
- Open Issues: https://github.com/photoprism/photoprism/issues
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -0,0 +1,19 @@
---
name: Support Request
about: You have general questions or need assistance
title: " "
labels: question
assignees: ''
---
PLEASE USE GITHUB ISSUES ONLY TO REPORT CLEARLY IDENTIFIED BUGS - THANK YOU!
Use GitHub Discussions or our Community Chat if you need assistance and for general questions:
- https://github.com/photoprism/photoprism/discussions
- https://gitter.im/browseyourlife/community
Sponsors receive direct technical support via email:
- https://photoprism.app/contact

View file

@ -1,20 +1,21 @@
# Security Policy
**Please contact us at [security@photoprism.app](mailto:security@photoprism.app) when you've discovered a potential security issue.**
When you think you've discovered a security issue, please contact us at hello@photoprism.app.
At a minimum, your report should include the following:
Your report should at least include the following:
* Version and architecture
* Vulnerability description
* Reproduction steps
- Version and architecture
- Vulnerability description
- Reproduction steps
We will then try to reproduce the problem, determine the impact and get back to you as soon as possible.
We will then try to reproduce it, determine the impact, and get back to you as soon as possible.
Avoid activities that disrupt, degrade, or interrupt our services or compromise other users' data, such as spam, brute force attacks, denial of service attacks, and malicious file distribution.
Please also report vulnerabilities in third-party applications.
You are welcome to also report vulnerabilities in third-party applications that we may not be able to fix directly.
### Responsible Disclosure ###
- Only test for vulnerabilities on your own PhotoPrism instance
- Confirm the vulnerability applies to a supported version
- Share vulnerability details with us first
- Wait for a fix before publicly sharing details
1. Confirm that the vulnerability applies to a current version
2. First share the vulnerability details with us
3. Wait for resolution before sharing details
**Thank you!** 👍

View file

@ -14,9 +14,9 @@ to a folder of your choice, change it as needed, and run "docker-compose up":
wget https://dl.photoprism.org/docker/arm64/docker-compose.yml
sudo docker-compose up -d
Please always change PHOTOPRISM_ADMIN_PASSWORD so that PhotoPrism starts with a secure initial password.
Never use "photoprism", or other easy-to-guess passwords, on a public server.
A minimum length of 4 characters is required.
Always change PHOTOPRISM_ADMIN_PASSWORD so that the app starts with a secure initial password.
Never use easy-to-guess passwords or default values like insecure on publicly accessible servers.
There is no default in case no password was provided. A minimum length of 4 characters is required.
For more details, see:
- https://docs.photoprism.org/getting-started/docker-compose/
@ -50,8 +50,10 @@ Use the --help flag to see a detailed command info like
| Re-index | docker-compose exec photoprism photoprism index -f
| Import | docker-compose exec photoprism photoprism import
Note: "photoprism index -f" will re-index all originals, including already indexed and unchanged files.
This may be necessary after upgrading, especially to new major versions.
For more examples, see https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface
NOTE: "photoprism index -f" will re-index all originals, including already indexed and unchanged files.
This may be necessary after upgrading, especially to new major versions.
## System Requirements ##

View file

@ -2,18 +2,18 @@ version: '3.5'
# Example Docker Compose config file for PhotoPrism (Raspberry Pi and other ARM-based devices)
#
# ATTENTION: It's important that you boot your Raspberry Pi 3 / 4 with the parameter "arm_64bit=1"
# in config.txt to use our ARM64 image.
#
# Documentation : https://docs.photoprism.org/getting-started/raspberry-pi/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# ATTENTION: You have to boot your Raspberry Pi 3 / 4 with the parameter "arm_64bit=1"
# in config.txt to use our ARM64 image.
#
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# -------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# -------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -28,19 +28,23 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
# Note: All commands may have to be prefixed with "sudo" when not running as root.
# This will change the home directory "~" to "/root" in your configuration.
#
# NOTE: All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory placeholder ~ to /root in volume mounts.
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Our stable version and development preview now come as a single multi-arch image for AMD64, ARM64, and ARMv7.
# Use photoprism/photoprism:preview instead for testing preview builds:
# NOTE: photoprism/photoprism-arm64 has been replaced by a single multi-arch image for AMD64,
# ARM64, and ARMv7. Use photoprism/photoprism:preview for testing preview builds or
# photoprism/photoprism:latest for the stable release.
image: photoprism/photoprism:latest
# Owners of ARMv7-based devices may have to explicitly specify the image architecture:
# platform: "linux/arm/v7"
# platform: "linux/arm"
depends_on:
- mariadb
# Only enable automatic restarts once your installation is properly
@ -56,6 +60,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "none" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_WORKERS: 2 # Limits the number of indexing workers to reduce system load
@ -75,12 +80,11 @@ services:
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
# PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -105,9 +109,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# ATTENTION: Owners of ARMv7-based devices have to revert to an alternative image if they want to use MariaDB.
# The official image is available for AMD64 and ARM64 only. Pay close attention to changed directory and
# environment variable names.
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: unless-stopped
image: arm64v8/mariadb:10.6
@ -123,14 +125,33 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Owners of ARMv7-based devices have to revert to an alternative image if they want to use MariaDB.
# The official image is available for AMD64 and ARM64 only. Pay close attention to changed directory
# and environment variable names.
#
# mariadb:
# restart: unless-stopped
# image: lscr.io/linuxserver/mariadb:latest
# security_opt:
# - seccomp:unconfined
# - apparmor:unconfined
# command: mysqld --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:
# - "./mariadb:/config" # Never remove
# environment:
# MYSQL_ROOT_PASSWORD: insecure
# MYSQL_DATABASE: photoprism
# MYSQL_USER: photoprism
# MYSQL_PASSWORD: insecure
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account

View file

@ -5,12 +5,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/raspberry-pi/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# -------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# -------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -25,16 +25,20 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
# Note: All commands may have to be prefixed with "sudo" when not running as root.
# This will change the home directory "~" to "/root" in your configuration.
#
# NOTE: All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory placeholder ~ to /root in volume mounts.
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Our stable version and development preview now come as a single multi-arch image for AMD64, ARM64, and ARMv7.
# Use photoprism/photoprism:preview instead for testing preview builds:
# NOTE: photoprism/photoprism-arm64 has been replaced by a single multi-arch image for AMD64,
# ARM64, and ARMv7. Use photoprism/photoprism:preview for testing preview builds or
# photoprism/photoprism:latest for the stable release.
image: photoprism/photoprism:latest
platform: "linux/arm"
depends_on:
@ -52,6 +56,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "none" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_WORKERS: 1 # Limits the number of indexing workers to reduce system load
@ -70,12 +75,11 @@ services:
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
# PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -100,6 +104,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: unless-stopped
image: lscr.io/linuxserver/mariadb:latest
@ -115,14 +120,14 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account

View file

@ -46,7 +46,7 @@ version: '3.5'
# See jobs.ini for details.
#
# SYSTEM REQUIREMENTS
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
#
# We recommend hosting PhotoPrism on a server with at least 2 cores and
# 4 GB of memory. Beyond these minimum requirements, the amount of RAM
@ -57,7 +57,7 @@ version: '3.5'
# will be disabled on servers with less than 2 GB of physical memory.
#
# DOCKER COMPOSE COMMAND REFERENCE
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -72,11 +72,13 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
#
# USING LET'S ENCRYPT HTTPS
# -------------------------------------------------------------------------
# --------------------------------------------------------------------------
#
# If your server has a public domain name, please disable the self-signed
# certificate and enable domain based routing in docker-compose.yml and
@ -90,12 +92,12 @@ version: '3.5'
# docker-compose up -d
#
# You should now be able to access your instance without security warnings.
# -------------------------------------------------------------------------
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
restart: always
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
container_name: photoprism
depends_on:
@ -145,11 +147,11 @@ services:
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Enables Darktable presets and disables concurrent RAW conversion
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "_admin_password_" # MariaDB database user password
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "_admin_password_" # MariaDB or MySQL database user password
PHOTOPRISM_INIT: "tensorflow-amd64-avx2"
HOME: "/photoprism"
working_dir: "/photoprism"
@ -162,6 +164,7 @@ services:
- "./storage:/photoprism/storage"
- "./backup:/var/lib/photoprism"
# REQUIRED: Traefik Reverse Proxy, see https://docs.photoprism.org/getting-started/proxies/traefik/
traefik:
restart: always
image: traefik:v2.4
@ -178,6 +181,7 @@ services:
- "./traefik.yaml:/etc/traefik/traefik.yaml"
- "./certs/:/certs/"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: always
image: mariadb:10.6
@ -194,6 +198,7 @@ services:
MYSQL_USER: "photoprism"
MYSQL_PASSWORD: "_admin_password_"
# RECOMMENDED: Ofelia Job Runner, see https://github.com/mcuadros/ofelia
ofelia:
restart: always
image: mcuadros/ofelia:latest
@ -202,6 +207,7 @@ services:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./jobs.ini:/etc/ofelia/config.ini"
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
watchtower:
restart: always
image: containrrr/watchtower

View file

@ -5,12 +5,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# ------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# ------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -25,15 +25,18 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
# Note: All commands may have to be prefixed with "sudo" when not running as root.
# This will change the home directory "~" to "/root" in your configuration.
#
# NOTE: All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory placeholder ~ to /root in volume mounts.
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
depends_on:
- mariadb
@ -50,6 +53,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
@ -66,12 +70,11 @@ services:
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
# PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -106,6 +109,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: unless-stopped
image: mariadb:10.6
@ -121,14 +125,14 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account

View file

@ -5,12 +5,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# ------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# ------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -25,13 +25,15 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
depends_on:
- mariadb
@ -46,6 +48,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
@ -61,12 +64,11 @@ services:
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Enables Darktable presets and disables concurrent RAW conversion
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -85,6 +87,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysqll
mariadb:
restart: unless-stopped
image: mariadb:10.6
@ -100,17 +103,17 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
volumes:
mariadb_data:

View file

@ -7,12 +7,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# ------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# ------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -27,15 +27,18 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
# Note: All commands may have to be prefixed with "sudo" when not running as root.
# This will change the home directory "~" to "/root" in your configuration.
#
# NOTE: All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory placeholder ~ to /root in volume mounts.
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
container_name: photoprism
depends_on:
@ -53,6 +56,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
@ -69,12 +73,11 @@ services:
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
# PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server (hostname:port)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -98,6 +101,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: unless-stopped
image: mariadb:10.6
@ -114,6 +118,7 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# REQUIRED: Ofelia Job Runner, see https://github.com/mcuadros/ofelia
ofelia:
restart: unless-stopped
image: mcuadros/ofelia:latest
@ -122,15 +127,14 @@ services:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./jobs.ini:/etc/ofelia/config.ini"
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# container_name: watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account

View file

@ -5,12 +5,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# ------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# ------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -25,15 +25,18 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
# Note: All commands may have to be prefixed with "sudo" when not running as root.
# This will change the home directory "~" to "/root" in your configuration.
#
# NOTE: All commands may have to be prefixed with "sudo" when not running as root.
# This will point the home directory placeholder ~ to /root in volume mounts.
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
# Only enable automatic restarts once your installation is properly
# configured as it otherwise may get stuck in a restart loop:
@ -48,6 +51,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # Run in debug mode (shows additional log messages)
@ -64,7 +68,6 @@ services:
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DATABASE_DRIVER: "sqlite" # SQLite is an embedded database that doesn't require a server
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -88,14 +91,14 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account

View file

@ -8,12 +8,12 @@ version: '3.5'
# Documentation : https://docs.photoprism.org/getting-started/docker-compose/
# Docker Hub URL: https://hub.docker.com/r/photoprism/photoprism/
#
# Please run behind a reverse proxy like Caddy, Traefik or Nginx if you need HTTPS / SSL support
# e.g. when running PhotoPrism on a public server outside your home network.
# IMPORTANT: When installing PhotoPrism on a public server outside your home network, please
# always run it behind a secure HTTPS reverse proxy like Traefik, Caddy, or NGINX.
# Your files and passwords will be transmitted in clear text otherwise.
#
# ------------------------------------------------------------------
# DOCKER COMPOSE COMMAND REFERENCE
# ------------------------------------------------------------------
# --------------------------------------------------------------------------
# Start | docker-compose up -d
# Stop | docker-compose stop
# Update | docker-compose pull
@ -28,13 +28,15 @@ version: '3.5'
# Reindex | docker-compose exec photoprism photoprism index -f
# Import | docker-compose exec photoprism photoprism import
#
# See https://docs.photoprism.org/getting-started/docker-compose/#command-line-interface for more examples.
#
# To search originals for faces without a complete rescan:
# docker-compose exec photoprism photoprism faces index
# -------------------------------------------------------------------
services:
# REQUIRED: PhotoPrism Application Server
photoprism:
# Use photoprism/photoprism:preview instead for testing preview builds:
# Use photoprism/photoprism:preview for testing preview builds:
image: photoprism/photoprism:latest
depends_on:
- mariadb
@ -49,6 +51,7 @@ services:
- "2342:2342" # [server]:[container]
environment:
PHOTOPRISM_ADMIN_PASSWORD: "insecure" # PLEASE CHANGE: Your initial admin password (min 4 characters)
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public URL incl http:// or https:// and /path, :port is optional
PHOTOPRISM_ORIGINALS_LIMIT: 5000 # File size limit for originals in MB (increase for high-res video)
PHOTOPRISM_HTTP_COMPRESSION: "gzip" # Improves transfer speed and bandwidth utilization (none or gzip)
PHOTOPRISM_DEBUG: "false" # Run in debug mode, shows additional log messages
@ -64,12 +67,11 @@ services:
PHOTOPRISM_DARKTABLE_PRESETS: "false" # Enables Darktable presets and disables concurrent RAW conversion
PHOTOPRISM_DETECT_NSFW: "false" # Flag photos as private that MAY be offensive (requires TensorFlow)
PHOTOPRISM_UPLOAD_NSFW: "true" # Allow uploads that MAY be offensive
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB (or MySQL) instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB database server hostname (:port is optional)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB database user password
PHOTOPRISM_SITE_URL: "http://localhost:2342/" # Public PhotoPrism URL
PHOTOPRISM_DATABASE_DRIVER: "mysql" # Use MariaDB 10.5+ or MySQL 8+ instead of SQLite for improved performance
PHOTOPRISM_DATABASE_SERVER: "mariadb:3306" # MariaDB or MySQL database server hostname (:port is optional)
PHOTOPRISM_DATABASE_NAME: "photoprism" # MariaDB or MySQL database schema name
PHOTOPRISM_DATABASE_USER: "photoprism" # MariaDB or MySQL database user name
PHOTOPRISM_DATABASE_PASSWORD: "insecure" # MariaDB or MySQL database user password
PHOTOPRISM_SITE_TITLE: "PhotoPrism"
PHOTOPRISM_SITE_CAPTION: "Browse Your Life"
PHOTOPRISM_SITE_DESCRIPTION: ""
@ -87,6 +89,7 @@ services:
# Cache, session, thumbnail, and sidecar files will be created in the *storage* folder (never remove):
- "./storage:/photoprism/storage"
# RECOMMENDED: MariaDB Server, see https://docs.photoprism.org/getting-started/faq/#should-i-use-sqlite-mariadb-or-mysql
mariadb:
restart: unless-stopped
image: mariadb:10.6
@ -102,17 +105,17 @@ services:
MYSQL_USER: photoprism
MYSQL_PASSWORD: insecure
# Uncomment the following lines to upgrade automatically, whenever there is a new Docker image available:
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
# OPTIONAL: Upgrades services automatically, see https://docs.photoprism.org/getting-started/updates/#watchtower
#
# watchtower:
# restart: unless-stopped
# image: containrrr/watchtower
# environment:
# WATCHTOWER_CLEANUP: "true"
# WATCHTOWER_POLL_INTERVAL: 7200 # Checks for updates every two hours
# volumes:
# - "/var/run/docker.sock:/var/run/docker.sock"
# - "~/.docker/config.json:/config.json" # Optional, for authentication if you have a Docker Hub account
volumes:
mariadb_data:

View file

@ -197,6 +197,30 @@ var AlbumFixtures = AlbumMap{
UpdatedAt: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
DeletedAt: nil,
},
"september-2021": {
ID: 1000007,
AlbumUID: "at1lxuqipogaabj9",
AlbumSlug: "september-2021",
AlbumPath: "",
AlbumType: AlbumMonth,
AlbumTitle: "September 2021",
AlbumLocation: "",
AlbumCategory: "",
AlbumCaption: "",
AlbumDescription: "",
AlbumNotes: "",
AlbumFilter: "public:true year:2021 month:9",
AlbumOrder: "newest",
AlbumTemplate: "",
AlbumCountry: UnknownID,
AlbumYear: 0,
AlbumMonth: 0,
AlbumDay: 0,
AlbumFavorite: false,
CreatedAt: time.Date(2019, 7, 1, 0, 0, 0, 0, time.UTC),
UpdatedAt: time.Date(2020, 2, 1, 0, 0, 0, 0, time.UTC),
DeletedAt: nil,
},
}
// CreateAlbumFixtures inserts known entities into the database for testing.

View file

@ -0,0 +1,83 @@
package form
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestNewFaceSearch(t *testing.T) {
r := NewFaceSearch("yes")
assert.IsType(t, FaceSearch{}, r)
}
func TestFaceSearch_GetQuery(t *testing.T) {
form := &FaceSearch{Query: "test"}
assert.Equal(t, "test", form.GetQuery())
}
func TestFaceSearch_SetQuery(t *testing.T) {
form := &FaceSearch{Query: "test"}
form.SetQuery("new query")
assert.Equal(t, "new query", form.GetQuery())
}
func TestFaceSearch_ParseQueryString(t *testing.T) {
t.Run("valid query", func(t *testing.T) {
form := &FaceSearch{Query: "subject:test count:10 offset:1"}
err := form.ParseQueryString()
// log.Debugf("%+v\n", form)
if err != nil {
t.Fatal("err should be nil")
}
assert.Equal(t, "test", form.Subject)
assert.Equal(t, 10, form.Count)
assert.Equal(t, 1, form.Offset)
})
t.Run("valid query with umlauts", func(t *testing.T) {
form := &FaceSearch{Query: "query:\"tübingen\""}
err := form.ParseQueryString()
// log.Debugf("%+v\n", form)
if err != nil {
t.Fatal("err should be nil")
}
assert.Equal(t, "tübingen", form.Query)
})
t.Run("query for invalid filter", func(t *testing.T) {
form := &FaceSearch{Query: "xxx:false"}
err := form.ParseQueryString()
if err == nil {
t.FailNow()
}
// log.Debugf("%+v\n", form)
assert.Equal(t, "unknown filter: Xxx", err.Error())
})
t.Run("query for count with invalid type", func(t *testing.T) {
form := &FaceSearch{Query: "count:cat"}
err := form.ParseQueryString()
if err == nil {
t.FailNow()
}
// log.Debugf("%+v\n", form)
assert.Equal(t, "strconv.Atoi: parsing \"cat\": invalid syntax", err.Error())
})
}

View file

@ -57,6 +57,13 @@ func TestAlbumCoverByUID(t *testing.T) {
assert.Error(t, err, "record not found")
t.Log(file)
})
t.Run("existing uid empty month album", func(t *testing.T) {
file, err := AlbumCoverByUID("at1lxuqipogaabj9")
assert.EqualError(t, err, "no cover found", err)
assert.Equal(t, "", file.FileName)
})
}
func TestUpdateAlbumDates(t *testing.T) {

View file

@ -223,3 +223,13 @@ func TestResolveFaceCollisions(t *testing.T) {
assert.LessOrEqual(t, 3, c)
assert.LessOrEqual(t, 3, r)
}
func TestRemoveAutoFaceClusters(t *testing.T) {
removed, err := RemoveAutoFaceClusters()
if err != nil {
t.Fatal(err)
}
assert.Equal(t, int64(3), removed)
}

View file

@ -32,7 +32,7 @@ func TestFaces(t *testing.T) {
assert.LessOrEqual(t, 1, len(results))
})
t.Run("Exclude Unknown & Hidden", func(t *testing.T) {
results, err := Faces(form.FaceSearch{Unknown: "no", Hidden: "yes", Order: "added", Markers: true})
results, err := Faces(form.FaceSearch{Unknown: "no", Hidden: "yes", Order: "samples", Markers: true})
assert.NoError(t, err)
t.Logf("Faces: %#v", results)
assert.LessOrEqual(t, 0, len(results))

View file

@ -265,6 +265,31 @@ func TestGeo(t *testing.T) {
assert.GreaterOrEqual(t, len(photos), 4)
})
t.Run("face:yes", func(t *testing.T) {
var f form.PhotoSearchGeo
f.Face = "Yes"
photos, err := PhotosGeo(f)
if err != nil {
t.Fatal(err)
}
assert.GreaterOrEqual(t, len(photos), 4)
})
t.Run("f.Faces:new", func(t *testing.T) {
var f form.PhotoSearchGeo
f.Faces = "New"
f.Face = ""
photos, err := PhotosGeo(f)
if err != nil {
t.Fatal(err)
}
assert.GreaterOrEqual(t, len(photos), 3)
})
t.Run("faces:no", func(t *testing.T) {
var f form.PhotoSearchGeo
f.Faces = "No"
@ -289,6 +314,18 @@ func TestGeo(t *testing.T) {
assert.GreaterOrEqual(t, len(photos), 1)
})
t.Run("face: TOSCDXCS4VI3PGIUTCNIQCNI6HSFXQVZ", func(t *testing.T) {
var f form.PhotoSearchGeo
f.Face = "TOSCDXCS4VI3PGIUTCNIQCNI6HSFXQVZ"
photos, err := PhotosGeo(f)
if err != nil {
t.Fatal(err)
}
assert.GreaterOrEqual(t, len(photos), 2)
})
t.Run("day", func(t *testing.T) {
var f form.PhotoSearchGeo
f.Day = "18"
@ -369,6 +406,97 @@ func TestGeo(t *testing.T) {
assert.Equal(t, "video", r.PhotoType)
}
})
t.Run("query: video", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "video"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "video", r.PhotoType)
}
})
t.Run("query: live", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "live"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "live", r.PhotoType)
}
})
t.Run("query: raws", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "raws"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "raw", r.PhotoType)
}
})
t.Run("query: panoramas", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "panoramas"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("query: scans", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "scans"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("query: faces", func(t *testing.T) {
var frm form.PhotoSearchGeo
@ -462,6 +590,24 @@ func TestGeo(t *testing.T) {
}
assert.Greater(t, len(photos), len(photos2))
})
t.Run("f.Album = uid", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Album = "at9lxuqxpogaaba9"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("people and and or search", func(t *testing.T) {
var f form.PhotoSearchGeo
f.People = "Actor A|Actress A"
@ -524,5 +670,125 @@ func TestGeo(t *testing.T) {
assert.Equal(t, len(photos3), len(photos4))
assert.Equal(t, len(photos), len(photos4))
var f5 form.PhotoSearchGeo
f5.Subject = "jqy1y111h1njaaad"
photos5, err5 := PhotosGeo(f5)
if err5 != nil {
t.Fatal(err5)
}
assert.Equal(t, len(photos5), len(photos4))
})
t.Run("f.Scan = true", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Scan = true
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("f.Panorama = true", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Panorama = true
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("f.Raw = true", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Raw = true
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("f.Live = true", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Live = true
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("f.Title = phototobebatchapproved2", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Title = "phototobebatchapproved2"
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
t.Run("f.Query = p", func(t *testing.T) {
var frm form.PhotoSearchGeo
frm.Query = "p"
frm.Title = ""
photos, err := PhotosGeo(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, GeoResult{}, r)
assert.NotEmpty(t, r.ID)
}
})
}

View file

@ -632,6 +632,18 @@ func TestPhotos(t *testing.T) {
}
assert.LessOrEqual(t, 1, len(photos))
})
t.Run("f.album", func(t *testing.T) {
var f form.PhotoSearch
f.Query = ""
f.Album = "Berlin"
photos, _, err := Photos(f)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
})
t.Run("search for state", func(t *testing.T) {
var f form.PhotoSearch
f.State = "KwaZulu-Natal"
@ -864,6 +876,18 @@ func TestPhotos(t *testing.T) {
assert.GreaterOrEqual(t, len(photos), 9)
})
t.Run("f.face yes", func(t *testing.T) {
var f form.PhotoSearch
f.Face = "yes"
photos, _, err := Photos(f)
if err != nil {
t.Fatal(err)
}
assert.GreaterOrEqual(t, len(photos), 9)
})
t.Run("faces:2", func(t *testing.T) {
var f form.PhotoSearch
f.Faces = "2"
@ -943,6 +967,138 @@ func TestPhotos(t *testing.T) {
}
}
})
t.Run("query: video", func(t *testing.T) {
var frm form.PhotoSearch
frm.Query = "video"
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "video", r.PhotoType)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("query: live", func(t *testing.T) {
var frm form.PhotoSearch
frm.Query = "live"
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "live", r.PhotoType)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("f.live", func(t *testing.T) {
var frm form.PhotoSearch
frm.Live = true
frm.Query = ""
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "live", r.PhotoType)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("query: raws", func(t *testing.T) {
var frm form.PhotoSearch
frm.Query = "raws"
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "raw", r.PhotoType)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("f.Raw", func(t *testing.T) {
var frm form.PhotoSearch
frm.Raw = true
frm.Query = ""
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.Equal(t, "raw", r.PhotoType)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("query: faces", func(t *testing.T) {
var frm form.PhotoSearch
@ -968,6 +1124,32 @@ func TestPhotos(t *testing.T) {
}
}
})
t.Run("query: faces", func(t *testing.T) {
var frm form.PhotoSearch
frm.Query = "faces:new"
frm.Face = ""
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.LessOrEqual(t, 1, r.PhotoFaces)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("query: people", func(t *testing.T) {
var frm form.PhotoSearch
@ -1122,6 +1304,31 @@ func TestPhotos(t *testing.T) {
}
}
})
t.Run("query: mono", func(t *testing.T) {
var frm form.PhotoSearch
frm.Query = "mono"
frm.Count = 10
frm.Offset = 0
photos, _, err := Photos(frm)
if err != nil {
t.Fatal(err)
}
assert.LessOrEqual(t, 1, len(photos))
for _, r := range photos {
assert.IsType(t, Photo{}, r)
assert.NotEmpty(t, r.ID)
assert.NotEmpty(t, r.LensID)
if fix, ok := entity.PhotoFixtures[r.PhotoName]; ok {
assert.Equal(t, fix.PhotoName, r.PhotoName)
}
}
})
t.Run("filename", func(t *testing.T) {
var f form.PhotoSearch
f.Filename = "1990/04/Quality1FavoriteTrue.jpg"
@ -1260,4 +1467,22 @@ func TestPhotos(t *testing.T) {
assert.Equal(t, len(photos3), len(photos4))
assert.Equal(t, len(photos), len(photos4))
})
t.Run("Search in Title", func(t *testing.T) {
var f form.PhotoSearch
f.Query = "N"
f.Title = ""
f.Count = 10
f.Offset = 0
photos, _, err := Photos(f)
if err != nil {
t.Fatal(err)
}
t.Logf("results: %+v", photos)
assert.Equal(t, 1, len(photos))
assert.Equal(t, photos[0].PhotoTitle, "Neckarbrücke")
})
}

View file

@ -64,13 +64,13 @@ func TestSubjects(t *testing.T) {
assert.Equal(t, 0, len(results))
})
t.Run("search file count >2", func(t *testing.T) {
results, err := Subjects(form.SubjectSearch{Type: entity.SubjPerson, Files: 2})
results, err := Subjects(form.SubjectSearch{Type: entity.SubjPerson, Files: 2, Excluded: "no"})
assert.NoError(t, err)
//t.Logf("Subjects: %#v", results)
assert.LessOrEqual(t, 1, len(results))
})
t.Run("search for alias", func(t *testing.T) {
results, err := Subjects(form.SubjectSearch{Type: entity.SubjPerson, Query: "Powell"})
results, err := Subjects(form.SubjectSearch{Type: entity.SubjPerson, Query: "Powell", Favorite: "no", Private: "no"})
assert.NoError(t, err)
//t.Logf("Subjects: %#v", results)
assert.Equal(t, "Dangling Subject", results[0].SubjName)