Install PhotoStructure on TrueNAS Scale

I would very much appreciate detailed instructions on how to install Photo Structure on TrueNAS Scale simple enough for newbies to follow. While I am a programmer, I don’t know Docker/Docker Compose/Whatever system TrueNAS scale uses. I have spent a day reading Photo Structure instructions for Docker and Docker Compose - they are a great overview - but I am reasonably confident that they assume someone knows these tools very well. I do not. They are a great overview for someone that knows what they are doing - but not for a Docker/TrueNAS newbie.

I think I should be looking for a YAML file - but could not find that in the instructions.

Thanks in advance for any help you might offer.


Hey there! TrueNAS SCALE is Debian-based, which should run docker-compose natively, but I don’t have a box locally that I can verify this with (yet). Here’s the docker-compose YAML.

I’m setting up a new NAS (I’m still picking out components so I can run with ECC) specifically to run SCALE on it, so I should have better instructions (perhaps a video walkthrough and screenshots!) after the next stable release is out.

Not quite… TrueNAS Scale does not run your standard docker setup, it’s kubernetes and does not come with Docker Compose - one of the key reason why I chose NOT to use TrueNAS Scale myself. Last year the community introduced a docker-compose system in a docker-in-docker setup. See here: TrueCharts Integrates Docker Compose with TrueNAS SCALE | TrueNAS Community - yikes!

Ideally, someone would create a “chart” for Photostructure so you can just pick it from their list of available app, and all the kubernetes nastiness is taken care of.

Meanwhile, if you really want to use Truenas Scale, you best bet is to follow this tutorial to setup a docker container from scratch using their UI - Using Launch Docker Image |

Hi Team, thanks very much for your help. Have tried several things - unsuccessfully so far.

  1. I tried using the Launch Docker Image tool (the provided method for adding an app) but could not successfully link the mount points on TrueNas Scale to the target points in the container e.g., /mnt/Photos/photostructure/config to /ps/config … get an error like:
    chart_release_create.hostPathVolumes.2.hostPath: Invalid mount ‘/mnt/Photos/photostructure/config’ path. Following service(s) use this path: SMB Share [EINVAL]
    which suggests either that SMB and this docker container cannot share the same mount point or that I am trying to create a mount point that already exists.

I am not good enough yet with this docker mechanism to figure this problem out and the documentation that avdp suggests appears to be a great reference if you are a guru and have done this before - but not good enough for me without many days of experimentation.

Avdp is correct with his description of the TrueCharts mechanism. That is what I tried above. There appears to be a placeholder for PhotoStructure there as well in the TrueCharts Incubator dashboard | TrueCharts - but there is nothing other than a placeholder there that I can see.

I may try the Docker and YAML approach next - but suspect I will also not be able to link to other mounts outside the container.

MRM, I find TrueNas Scale to be excellent as a file storage system. Apart from the docker issues the other main drawbacks are:
a) Can’t properly add an additional disk to an existing pool (hence can’t really expand a Raid5 pool by adding extra disks after the pool is initially created). There is a mechanism to add a disk to a pool - but it is not really integrated into the zfs Raid system - hence redundancy is lost on the newly added disk. Hence when you build a raid array - make it as big as you ever intend to use it (and make another one if you need to expand).
b) Can’t defrag (zfs does not support defragging yet).

Note that I am using PhotoStructure because it has superior file sorting and de-duplication capabilities compared other tools, it also has a more flexible query language. However - for now I have to also use PhotoPrism because it provides reverse geocoding and supposedly AI tools for image recognition (current version is not accurate and apparently is untrainable by a user). I would love to use PhotoStructure for all my needs … just a few more features needed first. I did try and write an app myself to do this - but got 50% of the R&D done before having to get back to life and work.

The issue may be related to my (not) favorite topic of how to protect your system security where it is only deemed safe if security is so good that no-one can access the files – including you, the owner. Of course, this makes the system safe but utterly unusable = Security Achieved.

I have read a number of posts that suggest linlking from within a TrueNAS Scale container to a filesystem on the local TrueNAS server that has an SMB link connected anywhere in its (parental) path prevents the container from being able to access it. Various things have been tried to overcome this issue including:

A) Disabling Host Path Safety Check – but this could be problematic for all sorts of scary anticipated reasons.
B) Creating a symlink to the path you want and linking to that (did not work for me)
C) Use an SMB mount to the SMB share in the same way SMB mountpoint using the same SMB link mechanism as external connections to TrueNAS use (have not figured how to do this yet – and this does not sound like a very high speed or smart way to do this).
D) Use storage dedicated to the container (not desirable in my case as it just requires a stack more disks and expense)

Frustratingly, I do not know how to solve this and may have to abandon the project as it is too hard for my skill set and is taking too long. Any suggestions very much appreciated.

If I use Truenas Scale mounts which do not have SMB shares assigned to them, then I can create a Photostructure app which states that it is I can’t get open a shell or a web connection/portal. No idea how to debug this unless it is to try different configurations. Status is Deploying Up to Date.

Configuration is

Photo Structure Files
/ps/library /mnt/Photos/originals Where sorted photos go
/ps/tmp /mnt/Photos/photostructure/tmp Cache and working files
/ps/config /mnt/Photos/photostructure/config Settings
/ps/logs /mnt/Photos/photostructure/logs Logs

Setup Steps for TrueNas Scale

  1. Application Name photostructure
  2. Version 2304.0.7 (Default and Can’t Change)
  3. Container Images
    a. Docker Image
    i. Image Repository photostructure/server
    ii. Image Tag stable
  4. Image Pull Policy Only pull image if not present on host
  5. Container Entrypoint
    a. Container CMD None (Default)
    b. Container Args None (Default)
    c. Container Environmental Variables None (Default)
  6. Networking
    a. Add external interfaces None (default)
    b. DNS Policy None (default)
    Use Default DNS Policy where Pod will inherit the name resolution configuration from the node.
    c. Nameservers None (Default)
    d. Searches None (Default)
    e. DNS Options None (Default)
  7. Provide access to node network namespace for the workload (Not Checked)
  8. Port Forwarding
    a. Container Port 1787
    b. Node Port 9787
    c. Protocol TCP Protocol
  9. Storage

Mount Path Dataset Name What for
/mnt/Photos/library /ps/library Where sorted photos go
/mnt/Photos/photostructure/tmp /ps/tmp Cache and working files
/mnt/Photos/photostructure/config /ps/config Settings
/mnt/Photos/photostructure/logs /ps/logs Logs
/mnt/Photos/Source /ps/source Photo source

  1. Memory Backed Volumes
    a. None - default
  2. Volumes
    a. None - Default all settings
  3. Workload Details
    a. Enable TTY Not Checked
    b. Enable STDIN Not Checked
    c. Security Context
    i. Priviledged Node Not Checked
  4. Capabilities
    a. None – Default
  5. Configure Container User and GroupID – Not Checked
    a. Run Container as User 568
    b. Run Container as Group 568
  6. Scaling / Upgrade Policy
    a. Resource Reservation
    b. Update Strategy
    i. “Kill existing pods before creating new ones” (Default)
  7. Resource Reservation
    a. GPU Configuration
    i. GPU Resource (
  1. Allocate 1 GPU
  1. Resource Limits
    a. Enable pod resource limits
  2. Portal Configuration
    a. Enable WebUI Portal (Only supported in TRUENAS Scale Bluefin)
  3. WebUIPortal
    a. Portal Name
    i. Web Portal
  4. Protocol for Portal
    a. HTTP Protocol
  5. Use Node IP for Portal IP/Domain
    a. Port 16000

Maybe this will help, maybe it won’t… Again I personally took a hard pass on TrueNAS Scale.

try setting the entrypoint to: /sbin/tini,--,/ps/app/
also an env variable for PATH set to: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Also, I would recommend you use the image tag of alpha rather than stable since you’re using docker.

Truenas Scale user here!
I have been using native docker using the below guide:

I have already configured few containers already. I will try soon photostructure

Welcome, @Mahmood_AlShafai !

I’d suggest caution from running non-trivial scripts from random internet posts, unless you’re willing to spend time reviewing the script in depth. It’s too easy to add either an exploitable surface (intentionally or otherwise), or straight up malware in any script (especially when the script runs other external scripts).

Need Help …
I have Photostructure going on TrueNAS Scale. Will write a brief note on how I got it working soon. It started processing and within a day or two got to 37997 photos - then hung.
Have stopped Photostructure and turned logging to “debug” level. Then restarted Photostructure and started rescan through Web GUI. It added around 60 photos in the last 10 hours. Photostructure does not seem to be processing like I would expect it to. Not sure how to interpret the logs (there are many). Seems to be some errors in the log.

One recent log is:
{“ts”:1687935007168,“l”:“error”,“ctx”:“EventStore”,“msg”:“maybeSendEvent(): ACCEPT”,“meta”:{“event”:{“timestamp”:1687935007.092,“exception”:{“values”:[{“stacktrace”:{“frames”:[{“colno”:7,“filename”:“node:internal/timers”,“function”:“processTimers”,“lineno”:500,“in_app”:false,“module”:“timers”},{“colno”:17,“filename”:“node:internal/timers”,“function”:“listOnTimeout”,“lineno”:557,“in_app”:false,“module”:“timers”},{“colno”:101250,“filename”:“/ps/app/bin/main.js”,“function”:“Timeout.”,“lineno”:9,“in_app”:true,“module”:“main”,“pre_context”:[“”,“/*”," * Copyright © 2021, PhotoStructure Inc.“,” * By using this software, you accept all of the terms in“,” * IF YOU DO NOT ACCEPT THESE TERMS, DO NOT USE THIS SOFTWARE"," /“,”“],“context_line”:”'{snip} ut "" after "+("ms";this.reject(e),null==t||t()}}),e)),this}get stateStr(){return this.pending?"pending":t {snip}“,“post_context”:[”//#"]},{“colno”:102000,“filename”:“/ps/app/bin/main.js”,“function”:“p.reject”,“lineno”:9,“in_app”:true,“module”:“main”,“pre_context”:[“”,"/“,” * Copyright © 2021, PhotoStructure Inc.“,” * By using this software, you accept all of the terms in“,” * IF YOU DO NOT ACCEPT THESE TERMS, DO NOT USE THIS SOFTWARE"," /“,”“],“context_line”:”'{snip} isIgnorableError(e)?"info":"warn",".reject()",e);const t=s.asError(e);return this.settle((()=>{this._error=t,this.state=u.PromiseStates.reje {snip}“,“post_context”:[”//#"]},{“colno”:591746,“filename”:“/ps/app/bin/main.js”,“function”:“Object.t.asError”,“lineno”:9,“in_app”:true,“module”:“main”,“pre_context”:[“”,"/“,” * Copyright © 2021, PhotoStructure Inc.“,” * By using this software, you accept all of the terms in“,” * IF YOU DO NOT ACCEPT THESE TERMS, DO NOT USE THIS SOFTWARE"," */“,”“],“context_line”:”'{snip} ce(i+1).trim());return,i).trim(),e}return new Error(t)}},t.isError=function(e){return e instanceof Error}},85643:(e,t)=>{"u {snip}“,“post_context”:[”//#"]}]},“type”:“Error”,“value”:“Timeout ChildService(sync) healthCheck at Wed Jun 28 2023 00:49:42 GMT-0600 (Mountain Daylight Time) after 25001ms: healthCheck for ChildService(sync): failed”,“mechanism”:{“handled”:true,“type”:“generic”}}]},“event_id”:“af039fbd97294caf81f63bf2e045545e”,“platform”:“node”,“environment”:“production”,“release”:“1.1.0+20210815185424”,“sdk”:{“integrations”:[“InboundFilters”,“FunctionToString”,“Console”,“Http”,“OnUncaughtException”,“OnUnhandledRejection”,“LinkedErrors”]},“message”:“Timeout ChildService(sync) healthCheck at Wed Jun 28 2023 00:49:42 GMT-0600 (Mountain Daylight Time) after 25001ms: healthCheck for ChildService(sync): failed: Error: Timeout ChildService(sync) healthCheck at Wed Jun 28 2023 00:49:42 GMT-0600 (Mountain Da…”,“extra”:{“pid”:27,“serviceName”:“main”,“serviceEnding”:false,“runtimeMs”:1009977,“version”:“1.1.0”,“os”:“Alpine Linux v3.13 on x64”,“isDocker”:true,“nodeVersion”:“16.2.0”,“locale”:“en”,“cpus”:“8 × Intel(R) Core™ i7-4790K CPU @ 4.00GHz”,“memoryUsageMb”:25,“memoryUsageRssMb”:54,“systemMemory”:“6.7 GB / 33.6 GB”,“ffmpeg”:“version 4.3.1”,“vlc”:“(not found)”,“argv”:“["/usr/local/bin/node","/ps/app/bin/main.js"]”}},“pleaseSend”:false,“recentEventCount”:1,“maxErrorsPerDay”:3}}

One solution to get Photostructure working on TrueNAS Scale.
This is a brief version of the method which highlights some of teh gotchas and tricks:

  1. TrueNAS Scale supports apps in Kubernetes containers. The “official” TrueNAS Scale supported apps do not include a template for PhotoStructure.
  2. A 3rd party group “TrueCharts” does support a PhotoStructure Template for TrueNas Scale.
    a) Install TrueNAS. Log into TrueNAS Scale - go to Apps (Left Side bar icon)
    b) Go to Manage Catalogs
    c) Add Catalog
    i) Catalog Name: Community-Incubator
    ii) Repository: GitHub - truecharts/catalog: This is JUST the catalog, please refer to truecharts/apps for the actuall app code!
    iii) Branch: main
    iv) Preferred Trains: incubator, stable
    d) Now go to Available Applications and somewhere down the list you will see a PhotoStructure Template (You can save time by searching for PhotoStructure)
    e) This template will either be in the stable or incubator Train. In either case it seems to work.
    f) Select Install
    g) The default install should work but creates default folders within the Kubernetes container
    each with limit of 256G and you will not have access to your source photos.
  3. While TrueNAS scale does support SMB shares, NFS Shares and a few others, The Kubernetes implementation only supports Direct linkage to other filesystems (outside the Kubernetes container) and nfs shares. If there is an nfs share in the path to the point that your would like PhotoStructure to access - then you cannot create a direct linkage to it. You can only do an nfs mount. If there is an SMB share defined in the path of where you would like PhotoStructure to access - then you can’t access that location - unless you uncheck “Enable Host Path Safety Checks” in apps->settings->advanced Setting on TrueNAS Scale. This is not advised.

Hence, if you are like me and have a file share where new photos get dumped and another file share where you would like PhotoShop to put its processed images … then it looks like you only have nfs mounts as an option. So set up NFS mounts on the locations you wish to access in TrueNAS share settings. Then configure the PhotoStructure Template to access those locations …

Hence in settings I have the following configurations that are different from the default:
Integrated Persistent Storage:
Type of Storage: NFS Share
NFS Server:
Path on NFS Server: /mnt/Photos/photo-library

tempscratchdisk Storage
Type of Storage: NFS Share
NFS Server:
Path on NFS Server: /mnt/Photos/photostructure/tmp

logs storage
Type of Storage: NFS Share
NFS Server:
Path on NFS Server: /mnt/Photos/photostructure/logs

config storage
Type of Storage: NFS Share
NFS Server:
Path on NFS Server: /mnt/Photos/photostructure/config

This causes nfs share mounts to be placed over folders that PhotoStructure uses i.e.,

And under “Additional App Storage” define where my source photos reside …
Type of Storage: NFS Share
NFS Server:
Path on NFS Server: /mnt/PhotoArchive
Mount Point: /var/PhotoArchive
and install the app template with this configuration.

I have two nfs mounts defined in TrueNAS Scale under Shares - that support this config.
with the following file tree structure under /mnt/Photos

If all goes well, the PhotoStructure App will be listed under installed apps. and will be listed as active. If it is stuck at Deploying (make sure you refresh your browser screen), then you may get a clue as to what went wrong by clicking on the app panel and looking under Events.

You may be able to reconfigure the template in situ without having to stop delete and then reinstall it by selecting the three dots to the right of the Photostructure app panel (under installed apps), selecting edit, make changes to the template configuration and then saving it (means execute as well).

You can get into the Kubernetes container by selecting the three dots at the res of the PhotoStructure App container (under Installed Apps) and then selecting “shell” then “choose”

Hope this helps someone.