fix(photoprism): Switch to SQLite database for simpler LXC setup

- Replace MariaDB with SQLite (no external database needed)
- Update LXC config with proper device permissions and capabilities
- Install libvips42 instead of mariadb-server
- Fix binary path to ./bin/photoprism
- Use environment variables instead of options.yml
- Simplify backup to just archive storage directory
- Update WIP.md with SQLite note

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
CyberMind-FR 2026-03-06 11:18:03 +01:00
parent 26519e7619
commit 7bcd09b81d
2 changed files with 94 additions and 117 deletions

View File

@ -16,7 +16,8 @@ _Last updated: 2026-03-06 (PhotoPrism Gallery)_
- LuCI: `luci-app-photoprism` KISS dashboard with stats and actions
- Features: AI face recognition, object detection, places/maps
- HAProxy integration via mitmproxy (WAF-safe, no bypass)
- MariaDB database, FFmpeg transcoding, HEIC support
- SQLite database (simpler, no external DB), FFmpeg transcoding, HEIC support
- Dependencies: libvips42 for image processing
- **AI Gateway `/login` Command**
- CLI: `aigatewayctl login [provider]` - Interactive or scripted provider authentication

View File

@ -10,7 +10,7 @@ LXC_PATH="/srv/lxc"
LXC_ROOTFS="${LXC_PATH}/${LXC_NAME}/rootfs"
LXC_CONFIG="${LXC_PATH}/${LXC_NAME}/config"
DATA_PATH="/srv/photoprism"
PHOTOPRISM_VERSION="240915-ce"
PHOTOPRISM_VERSION="260305-fad9d5395"
HOST_IP="192.168.255.1"
# Detect architecture
@ -110,6 +110,11 @@ create_lxc_config() {
# PhotoPrism LXC Configuration
lxc.uts.name = ${LXC_NAME}
lxc.rootfs.path = dir:${LXC_ROOTFS}
lxc.arch = aarch64
# Auto-start on boot
lxc.start.auto = 1
lxc.start.delay = 5
# Network - use host network
lxc.net.0.type = none
@ -122,89 +127,88 @@ lxc.mount.entry = ${DATA_PATH}/originals opt/photoprism/originals none bind,crea
lxc.mount.entry = ${DATA_PATH}/storage opt/photoprism/storage none bind,create=dir 0 0
lxc.mount.entry = ${DATA_PATH}/import opt/photoprism/import none bind,create=dir 0 0
# Resource limits
lxc.cgroup2.memory.max = ${mem_bytes}
# Startup command
lxc.init.cmd = /opt/start-photoprism.sh
# TTY
lxc.tty.max = 4
lxc.pty.max = 128
# Capabilities
lxc.cap.drop = sys_admin
# Character devices
lxc.cgroup2.devices.allow = c 1:* rwm
lxc.cgroup2.devices.allow = c 5:* rwm
lxc.cgroup2.devices.allow = c 136:* rwm
# Resource limits
lxc.cgroup2.memory.max = ${mem_bytes}
# Security
lxc.cap.drop = sys_module mac_admin mac_override sys_time sys_rawio
# Startup command (uses SQLite, no external DB)
lxc.init.cmd = /opt/init.sh
EOF
log "LXC config created"
}
# Create startup script inside container
# Create startup script inside container (uses SQLite - no external DB needed)
create_startup_script() {
cat > "${LXC_ROOTFS}/opt/start-photoprism.sh" << 'SCRIPT'
cat > "${LXC_ROOTFS}/opt/init.sh" << 'SCRIPT'
#!/bin/bash
set -e
# Start MariaDB
service mariadb start
sleep 2
# Setup environment
export HOME=/opt/photoprism
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
export TERM=linux
# Wait for MariaDB to be ready
for i in $(seq 1 30); do
if mysqladmin ping >/dev/null 2>&1; then
break
fi
sleep 1
done
# Create directories
mkdir -p /opt/photoprism/storage/cache
mkdir -p /opt/photoprism/storage/sidecar
mkdir -p /opt/photoprism/originals
mkdir -p /opt/photoprism/import
mkdir -p /run /var/run
# PhotoPrism environment - SQLite config (no external DB)
export PHOTOPRISM_CONFIG_PATH=/opt/photoprism
export PHOTOPRISM_DATABASE_DRIVER=sqlite
export PHOTOPRISM_DATABASE_DSN=/opt/photoprism/storage/photoprism.db
export PHOTOPRISM_ORIGINALS_PATH=/opt/photoprism/originals
export PHOTOPRISM_STORAGE_PATH=/opt/photoprism/storage
export PHOTOPRISM_IMPORT_PATH=/opt/photoprism/import
export PHOTOPRISM_HTTP_HOST=0.0.0.0
export PHOTOPRISM_HTTP_PORT=2342
export PHOTOPRISM_ADMIN_USER=admin
export PHOTOPRISM_ADMIN_PASSWORD="${PHOTOPRISM_ADMIN_PASSWORD:-secubox123}"
export PHOTOPRISM_DISABLE_FACES=false
export PHOTOPRISM_DISABLE_CLASSIFICATION=false
export PHOTOPRISM_DISABLE_PLACES=false
# Run PhotoPrism
cd /opt/photoprism
exec ./photoprism start
# Start PhotoPrism (foreground to keep container running)
exec ./bin/photoprism start
SCRIPT
chmod +x "${LXC_ROOTFS}/opt/start-photoprism.sh"
chmod +x "${LXC_ROOTFS}/opt/init.sh"
}
# Create PhotoPrism configuration
create_photoprism_config() {
local db_pass="$1"
# Create PhotoPrism directories (config is done via env vars in init script)
create_photoprism_dirs() {
mkdir -p "${LXC_ROOTFS}/opt/photoprism"
cat > "${LXC_ROOTFS}/opt/photoprism/options.yml" << EOF
# PhotoPrism Configuration
AdminUser: "${ADMIN_USER}"
AdminPassword: "${ADMIN_PASS}"
# Storage
OriginalsPath: "/opt/photoprism/originals"
StoragePath: "/opt/photoprism/storage"
ImportPath: "/opt/photoprism/import"
# Server
HttpHost: "0.0.0.0"
HttpPort: ${HTTP_PORT}
# Database
DatabaseDriver: "mysql"
DatabaseDsn: "${DB_USER}:${db_pass}@tcp(127.0.0.1:3306)/${DB_NAME}?charset=utf8mb4,utf8&parseTime=true"
# Features
DisableFaces: $([ "$FACE_RECOGNITION" = "1" ] && echo "false" || echo "true")
DisableClassification: $([ "$OBJECT_DETECTION" = "1" ] && echo "false" || echo "true")
DisablePlaces: $([ "$PLACES" = "1" ] && echo "false" || echo "true")
DisableRaw: $([ "$RAW_THUMBS" = "1" ] && echo "false" || echo "true")
# Quality
JpegQuality: 85
ThumbSize: 2048
ThumbSizeUncached: 7680
EOF
mkdir -p "${LXC_ROOTFS}/opt/photoprism/storage"
mkdir -p "${LXC_ROOTFS}/opt/photoprism/originals"
mkdir -p "${LXC_ROOTFS}/opt/photoprism/import"
}
# Install packages inside container
install_packages() {
log "Installing packages in container..."
# Fix /dev nodes for chroot
[ -e "${LXC_ROOTFS}/dev/null" ] || mknod -m 666 "${LXC_ROOTFS}/dev/null" c 1 3
[ -e "${LXC_ROOTFS}/dev/zero" ] || mknod -m 666 "${LXC_ROOTFS}/dev/zero" c 1 5
[ -e "${LXC_ROOTFS}/dev/random" ] || mknod -m 666 "${LXC_ROOTFS}/dev/random" c 1 8
[ -e "${LXC_ROOTFS}/dev/urandom" ] || mknod -m 666 "${LXC_ROOTFS}/dev/urandom" c 1 9
chmod 666 "${LXC_ROOTFS}/dev/null" 2>/dev/null || true
# Configure apt
cat > "${LXC_ROOTFS}/etc/apt/sources.list" << EOF
deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
@ -212,22 +216,27 @@ deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free
deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
EOF
# Create install script
# Create install script - install gpgv first for apt verification
cat > "${LXC_ROOTFS}/tmp/install.sh" << 'INSTALL'
#!/bin/bash
set -e
export DEBIAN_FRONTEND=noninteractive
# Install gpgv first (required for apt signature verification)
# Use --allow-unauthenticated only for this bootstrap step
apt-get update --allow-insecure-repositories || true
apt-get install -y --allow-unauthenticated gpgv gnupg
# Now apt can verify signatures
apt-get update
apt-get install -y --no-install-recommends \
mariadb-server \
libvips42 \
ffmpeg \
exiftool \
libheif-examples \
ca-certificates \
curl \
wget \
gnupg
wget
# Clean up
apt-get clean
@ -235,8 +244,14 @@ rm -rf /var/lib/apt/lists/*
INSTALL
chmod +x "${LXC_ROOTFS}/tmp/install.sh"
# Mount /proc for chroot
mount -t proc proc "${LXC_ROOTFS}/proc" 2>/dev/null || true
# Run install via chroot
chroot "$LXC_ROOTFS" /tmp/install.sh
# Unmount /proc
umount "${LXC_ROOTFS}/proc" 2>/dev/null || true
rm -f "${LXC_ROOTFS}/tmp/install.sh"
}
@ -244,7 +259,7 @@ INSTALL
install_photoprism_binary() {
log "Downloading PhotoPrism ${PHOTOPRISM_VERSION} for ${ARCH}..."
local url="https://github.com/photoprism/photoprism/releases/download/${PHOTOPRISM_VERSION}/photoprism_${PHOTOPRISM_VERSION}_linux_${ARCH}.tar.gz"
local url="https://github.com/photoprism/photoprism/releases/download/${PHOTOPRISM_VERSION}/photoprism_${PHOTOPRISM_VERSION}-linux-${ARCH}.tar.gz"
mkdir -p "${LXC_ROOTFS}/opt/photoprism"
@ -256,33 +271,12 @@ install_photoprism_binary() {
tar -xzf /tmp/photoprism.tar.gz -C "${LXC_ROOTFS}/opt/photoprism"
rm -f /tmp/photoprism.tar.gz
chmod +x "${LXC_ROOTFS}/opt/photoprism/photoprism"
# Binary is in bin/ subdirectory
chmod +x "${LXC_ROOTFS}/opt/photoprism/bin/photoprism"
log "PhotoPrism binary installed"
}
# Setup MariaDB
setup_database() {
local db_pass="$1"
cat > "${LXC_ROOTFS}/tmp/setup-db.sh" << DBSCRIPT
#!/bin/bash
service mariadb start
sleep 2
mysql -e "CREATE DATABASE IF NOT EXISTS ${DB_NAME};"
mysql -e "CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${db_pass}';"
mysql -e "GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';"
mysql -e "FLUSH PRIVILEGES;"
service mariadb stop
DBSCRIPT
chmod +x "${LXC_ROOTFS}/tmp/setup-db.sh"
chroot "$LXC_ROOTFS" /tmp/setup-db.sh
rm -f "${LXC_ROOTFS}/tmp/setup-db.sh"
}
# Full installation
# Full installation (uses SQLite - no external database needed)
cmd_install() {
defaults
@ -299,34 +293,25 @@ cmd_install() {
mkdir -p "${DATA_PATH}/import"
chmod -R 755 "$DATA_PATH"
# Generate passwords if not set
# Generate admin password if not set
if [ -z "$ADMIN_PASS" ]; then
ADMIN_PASS=$(generate_password)
uci_set admin.password "$ADMIN_PASS"
log "Generated admin password: $ADMIN_PASS"
fi
local db_pass="$DB_PASS"
if [ -z "$db_pass" ]; then
db_pass=$(generate_password)
uci_set database.password "$db_pass"
fi
# Download rootfs
download_rootfs "$ARCH"
# Install packages
# Install packages (libvips, ffmpeg, etc.)
install_packages
# Download PhotoPrism
# Download PhotoPrism binary
install_photoprism_binary
# Setup database
setup_database "$db_pass"
# Create configs
# Create configs and startup script
create_lxc_config
create_photoprism_config "$db_pass"
create_photoprism_dirs
create_startup_script
# Enable service
@ -497,7 +482,7 @@ cmd_index() {
fi
log "Starting photo indexing..."
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/photoprism index
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/bin/photoprism index
log "Indexing complete"
}
@ -514,7 +499,7 @@ cmd_import() {
[ "$(uci_get import.delete_after_import 0)" = "1" ] && delete_opt="--move"
log "Importing photos from ${DATA_PATH}/import..."
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/photoprism import $delete_opt
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/bin/photoprism import $delete_opt
log "Import complete"
}
@ -528,14 +513,14 @@ cmd_passwd() {
return 1
fi
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/photoprism passwd "$ADMIN_USER" "$new_pass"
lxc-attach -n "$LXC_NAME" -- /opt/photoprism/bin/photoprism passwd "$ADMIN_USER" "$new_pass"
uci_set admin.password "$new_pass"
log "Password reset for $ADMIN_USER"
log "New password: $new_pass"
}
# Backup
# Backup (SQLite database is in storage directory)
cmd_backup() {
defaults
local backup_dir="${DATA_PATH}/backups"
@ -544,17 +529,8 @@ cmd_backup() {
mkdir -p "$backup_dir"
if lxc_running; then
log "Dumping database..."
lxc-attach -n "$LXC_NAME" -- mysqldump -u root "$DB_NAME" > "${backup_dir}/database-${timestamp}.sql"
fi
log "Creating backup archive..."
tar -czf "$backup_file" \
-C "$DATA_PATH" storage \
-C "$backup_dir" "database-${timestamp}.sql" 2>/dev/null || true
rm -f "${backup_dir}/database-${timestamp}.sql"
log "Creating backup archive (includes SQLite database)..."
tar -czf "$backup_file" -C "$DATA_PATH" storage
log "Backup created: $backup_file"
}