photoprism on droidian
PhotoPrism on Droidian , All on Host
Droidian has limited container support, so we wil install everything natively. This guide builds a low-power PhotoPrism server on a Redmi Note 9S with an external USB drive.
The stack is a dependency chain: Toshiba USB Drive >MariaDB > PhotoPrism. If the drive sleeps, the services wait. If you touch the drive, the whole stack wakes.
Why: It covers three critical things: • Prevents “Internal Suicide”: If the drive doesn’t have power during boot, the chain blocks MariaDB and PhotoPrism from starting. This stops them from creating “fake” empty databases that would fill up your phone’s tiny internal storage and brick the OS. • Automates Recovery: Instead of you manually fixing things, the chain waits for the drive to “wake up.” Once the power stabilizes and the drive appears, the apps see it and start themselves automatically. • Protects Data Integrity: It ensures the “Librarian” (MariaDB) never tries to write to a “Missing Bookshelf” (the drive), which prevents database corruption during power dips. In short: It turns a potential system crash into a temporary pause, keeping your phone fast and your photos safe.
Phase 1: The Foundation (MariaDB and Hardware)
1. Install MariaDB natively
Lighter on RAM than Docker.
1
2
sudo apt update
sudo apt install mariadb-server -y
2. Migrate existing database (optional)
If you are moving from a Raspberry Pi, if you are not using the same drive that holds the files , copy your old database folder to the drive first then fix ownership.
1
2
sudo chown -R mysql:mysql /mnt/drive/photoprism/database
sudo chmod -R 750 /mnt/drive/photoprism/database
3. Fix AppArmor for /mnt access (Droidian/Ubuntu)
Droidian blocks MariaDB from /mnt by default. Create a local override if you hit permission denied.
1
sudo nano /etc/apparmor.d/local/usr.sbin.mariadbd
Add:
1
2
/mnt/drive/photoprism/database/ r,
/mnt/drive/photoprism/database/** rwk,
Reload:
1
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mariadbd
4. Ensure base directory exists
MariaDB expects /var/lib/mysql even if datadir is elsewhere.
1
2
sudo mkdir -p /var/lib/mysql
sudo chown mysql:mysql /var/lib/mysql
5. Restart MariaDB
1
2
sudo systemctl stop mariadb
sudo systemctl start mariadb
6. Mount the external drive
Find your drive UUID.
1
2
lsblk -f
# Example UUID: d0289834-0b0d-47ba-bfc4-ebb6fa6f5827
Create mount point and edit fstab.
1
2
sudo mkdir -p /mnt/drive
sudo nano /etc/fstab
Add this line. The noauto,x-systemd.automount trick prevents boot failures when the USB port is underpowered. The drive mounts only when first accessed.
1
UUID=d0289834-0b0d-47ba-bfc4-ebb6fa6f5827 /mnt/drive ext4 defaults,noauto,x-systemd.automount,x-systemd.idle-timeout=600,nofail 0 2
Apply:
1
sudo systemctl daemon-reload
Phase 2: Connecting Hardware to Software
1. Make MariaDB wait for the drive
Create a systemd drop-in.
1
2
sudo mkdir -p /etc/systemd/system/mariadb.service.d/
sudo nano /etc/systemd/system/mariadb.service.d/override.conf
Content:
1
2
[Unit]
RequiresMountsFor=/mnt/drive
This forces MariaDB to stay off until /mnt/drive is confirmed mounted. It solves the crash when the drive is in standby.
2. Point MariaDB to the external datadir
Edit the server config.
1
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
Use these low-memory settings for a 4GB phone:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[mysqld]
user = mysql
pid-file = /run/mysqld/mysqld.pid
basedir = /usr
datadir = /mnt/drive/photoprism/database
# PhotoPrism required settings
transaction-isolation = READ-COMMITTED
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# Mobile tuning
innodb_buffer_pool_size = 128M
max_connections = 50
Reload MariaDB:
1
sudo systemctl restart mariadb
3. Verify databases
1
sudo mariadb -u root -p -e "SHOW DATABASES;"
If you migrate from an old database use you old credential
Phase 3: Installing PhotoPrism Natively
1. Install dependencies
These let PhotoPrism read HEIC, RAW, and video.
1
2
sudo apt update
sudo apt install -y libheif-examples libvips42 libexif12 libexif-dev ffmpeg
2. Install the ARM64 deb
PhotoPrism provides static builds.
1
2
3
4
curl -sLO https://dl.photoprism.app/pkg/linux/deb/photoprism_latest_arm64.deb
sudo dpkg -i photoprism_latest_arm64.deb
sudo ln -sf /opt/photoprism/bin/photoprism /usr/local/bin/photoprism
photoprism --version
3. Create the systemd service
1
sudo nano /etc/systemd/system/photoprism.service
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[Unit]
Description=PhotoPrism AI-Powered Photos App
After=mariadb.service
RequiresMountsFor=/mnt/drive
[Service]
Type=simple
User=photoprism
Group=photoprism
WorkingDirectory=/opt/photoprism
ExecStart=/usr/local/bin/photoprism start
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Enable it later after config.
4. Configure paths
All data lives on the Toshiba drive.
1
sudo nano /etc/photoprism/defaults.yml
Example config:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ConfigPath: "~/.config/photoprism"
StoragePath: "/mnt/drive/photoprism/storage"
OriginalsPath: "/mnt/drive/photos"
ImportPath: "/mnt/drive/photoimport"
AdminUser: "ippo"
AdminPassword: "CHANGE-ME-STRONG-PASSWORD"
AuthMode: "password"
HttpHost: "0.0.0.0"
HttpPort: 2342
HttpCompression: "gzip"
DatabaseDriver: "mysql"
DatabaseServer: "127.0.0.1:3306"
DatabaseName: "photoprism"
DatabaseUser: "photoprism"
DatabasePassword: "CHANGE-ME"
# Mobile optimization
Workers: 1
IndexWorkers: 1
LowMem: true
DatabaseConns: 5
DatabaseConnsIdle: 2
DisableTLS: false
DefaultTLS: true
JpegQuality: 85
DetectNSFW: false
UploadNSFW: true
Critical fix: HttpHost: "0.0.0.0" not 127.0.0.1. This exposes the UI on your LAN at 192.168.1.198:2342.
Fix ownership:
1
sudo chown -R photoprism:photoprism /mnt/drive/photoprism/storage
5. Test first run
1
photoprism start
Check logs in another terminal:
1
sudo journalctl -u photoprism -f
Then enable:
1
sudo systemctl enable --now photoprism
Phase 4: Resource Optimization
- Workers = 1 Prevents using all 8 cores and overheating the Redmi Note 9S
- innodb_buffer_pool_size = 128M Keeps MariaDB under 200MB RAM
- Swap 2GB Acts as emergency RAM for face recognition
- x-systemd.idle-timeout=600 Lets the drive sleep after 10 minutes idle
The Boot Flow
- Droidian boots, /mnt/drive is not mounted yet
- systemd tries MariaDB, sees RequiresMountsFor, waits
- You access PhotoPrism, automount triggers, drive spins up
- MariaDB starts using /mnt/drive/photoprism/database
- PhotoPrism starts and serves UI on port 2342
Key Commands
Health check the whole chain:
1
systemctl status mnt-drive.mount mariadb photoprism
Check hardware:
1
lsblk -f
Check memory:
1
free -h
Live logs:
1
2
sudo journalctl -u photoprism -f
sudo journalctl -u mariadb -f
Monitor heavy lifting:
1
top -b -n 1 | grep photoprism
Emergency RAM clear:
1
2
sudo sync; echo 3 | sudo tee /proc/sys/vm/drop_caches
clear:**
Verdict , initial impressions
The PhotoPrism user experience I had is better on the droidian micro server than it was on my raspberry pi 400 .
Browsing my assets is snappier from the web ui and from the iOS app prismatic.
Indexing also looks snappier. Even though we set 1 worker against 2 that I had on raspberry pi importing 100 photos took like 10 - 15 mins tensorflow enabled . Keep in mind without the 1 worker parameter droidian crashed.
There is extra hardware required: Plugging in an external hard drive on a phone is not gonna just work . Power from the usb c port is not sufficient to spin the drive . I used an externally powered usb hub to power the drive. Also the dual purpose on a single port problem has to be addressed : You need to power the phone and use otg at the same time as the phone battery will deplete at some point . There are some option for Y splitters on the market . I’m waiting my 10$ splitter from Amazon in the next days .
That’s all , if you have a droidian compatible around don’t hesitate to give it a go .