Synology NAS Tips

This guide shares my learnings with a Synology DS920+ using Container Manager Projects. Official PhotoStructure Synology docker instructions exist, this just adds some extra flavor to that.

Table of Contents

Revision history

  • 2026-04-11 add section Updating Projects YAML with Synology GUI
  • 2026-04-10 convert posts to Discourse Wiki format and update for 2026.4.x

Create user just for PhotoStructure

Also see Dr. Frankenstein: Step 2: Setting up a restricted Docker user and obtaining IDs

You can skip this, but a custom user makes it easier to customize permissions now and later. For example when adding a new Synology Shared Folder for some extended family for PhotoStructure, I was able to do that without worrying about Jellyfin or anything else touching those files. Note Dr Frankenstein has a single user for all docker containers, which might reduce permissions issues if you have multiple containers reading/writing the same files. I haven’t personally run into any issues yet :right_facing_fist::wood:

  1. Control Panel → User & Group → Create.
  2. Control Panel → User & Group → Edit lets you make changes later.
  3. Follow User Creation Wizard to create username and password. I chose dockerphotostructure.
  4. Assign permissions:
    • Shared Folders: Deny all, except you will need to grant Read/Write to docker shared folder and your photos/videos folder(s). If desired, you can set Read-Only for photos/videos later with the Docker Compose Wizard. Read/Write is required for the docker folder(s) for PhotoStructure’s library, tmp, etc. My shares are docker and main.
    • Applications: Deny all.
  5. Finish.

Get PUID / GUID from GUI

Also see Synology: Find UID (userID) and GID (groupID) in 5 Seconds – Marius Hosting, EXCEPT his tutorial requires you to set up email which is actually not necessary.

You don’t need SSH to get the user PUID / GUID, we can get this from the control panel using Synology’s Task Scheduler!

  1. Control Panel → Task Scheduler → Create → Triggered Task → User-defined script.
  2. General tab:
    • I named it taskGetPuidGuid and run as myself (my user is in the admin group).
    • Uncheck Enabled so it never runs automatically.
  3. Task Settings tab:
    • Uncheck Send run details by email
    • User-defined script: id dockerphotostructure
  4. Click OK.
  5. Select the task → click Run.
  6. Select the task again → click Action → View Result.
  7. It will be something like uid=1033(dockerphotostructure) gid=100(users) groups=100(users):
    • PUID = number after uid= (e.g. 1033)
    • GUID = number after gid= (usually 100 on Synology)

The following more advanced script lists all non-system usernames with PUID and GUID:

for user in $(awk -F':' '$3>999 && $3<9999 {print $1}' /etc/passwd); do id $user; done

Folder paths for Docker Compose Wizard

PhotoStructure provides Docker Compose Wizard which includes a Synology preset and shareable links with your customizations saved in the URL. My config as of 2026-04-11 looks like https://photostructure.com/server/docker-compose-wizard/?plat=synology&lib=%2Fvolume2%2Fdocker%2Fphotostructure%2Flibrary&puid=1026&nf=1&scan=%2Fvolume1%2Fmain%2FMedia

Following the official PhotoStructure instructions worked well. The main part I found tricky was making a docker shared folder with photostructure/library subfolder, and figuring out the exact right path to enter into the Docker Compose Wizard. The easiest way I found to do this was:

  1. Pretend to start making a PhotoStructure docker container using the Create Container wizard, using any old image. If you do not have any images yet, download latest or something else from https://hub.docker.com/r/photostructure/server.
  2. The wizard includes a GUI for mapping folders, so use GUI to select folders then fill in a fake mapped path so you can click “Next”.
  3. Uncheck “Run this container after the wizard is finished”
  4. Finish the wizard.
  5. Click into the container. In the “General” tab, the full filepath needed for Docker Compose is written out before the : colon.

Once you’ve figured out the folder path, delete the container since that’s all we needed from it.

Updating YAML with Synology Projects GUI

As of 2026-04-11, DO NOT edit, save, then Build and start the project (rebuild the image). If you skip cleaning, you may lose the ability to stop and edit your project again until after rebooting your entire Synology NAS (more details). Rebooting is much more annoying than first cleaning:

  1. ** Project → select Project → Action → Stop**
  2. Action → Clean.
    This deletes the container that was previously built, although none of the PhotoStructure library data is deleted. If you go to the Container tab; you should see that the container previously built is now gone.
  3. Edit YAML Configurations tab, and make desired changes.
  4. Save.
  5. Build and start the project (rebuild the image). Or if you can’t remember whether you first cleaned, click Only save the changes and then do Action → Clean followed by Action → Build.

Updating latest

One step with latest branch:

  1. Container Manager → Image → Update available

This automatically downloads the updated image then restarts the container.

Note it does not work for stable, main, beta, or any other named tag I’ve tried. Synology Version: 20.10.23-1405 (2023-05-22) says, “Supports automatic update detection for images with the ‘latest’ tag.” I have not been able to find anything in Synology docs or my own testing saying anything is supported besides “latest”.

Updating non-latest

Synology Container Manager Projects using beta, stable, or other tags can be updated by with these steps:

  1. Project → select Project → Action → Stop
  2. Project → select Project → Action → Clean. Note that Synology documentation says “Clean” is docker-compose down to “Stop the containers and removes containers, networks, volumes, and images created by the docker-compose.yml of this project.”
  3. Image → select tagged PhotoStructure images (beta and <none in my case) → Delete
  4. (I did not delete the mwader/static-ffmpeg:8.0.1 image
  5. Project → select Project → Action → Build
  6. Successful update without using latest tag and without entirely deleting the project!

SSD Volume (M.2 and 2.5")

Starting with DSM 7.2 and some Synology models, SSDs (2.5" and M.2) can be created as a volume for a Synology Shared Folder. This is ideal for use for docker containers in general, PhotoStructure’s /ps/library, and especially /ps/tmp. See the folders explained in more detail at PhotoStructure for Docker.

Older Synology products like the DS920+ and DSM 6.x only supported using M.2 SSDs as a Synology-managed read/write cache. But now my DS920+ with DSM 7.3 does support using 2.5" SSDs, so my system has three HDD (Volume 1) and one 2.5" SSD (Volume 2).

These scripts (and associated Synology subreddit threads) appear to make it easy to unofficially implement where Synology has not officially enabled it. GitHub - 007revad/Synology_HDD_db: Add your HDD, SSD and NVMe drives to your Synology’s compatible drive database and a lot more

Faster import/rebuild (and less responsive NAS)

Synology wasn’t using enough CPU resources for my liking. See discussion at Import and resync faster on Docker NAS? for parameters you can play with, and of course more info at PhotoStructure’s advanced settings | PhotoStructure. However I haven’t done specific performance testing yet, so do not have a specific recommended setup for Synology DS920+ and others with the same CPU.

Whoa! DSM 7.2 supports Docker Compose from the UI!! And they’ve updated docker-compose to 2.5.1 (currently it’s 1.28.5, which is really old).

Via Synology DSM 7.2

:construction::construction::construction:
This procedure is a work-in-progress using the latest pre-alpha, details may change with stable release; and anyway, details are hopefully eventually officially updated in PhotoStructure for Docker | PhotoStructure
:construction::construction::construction:

  1. Create a new user for photostructure and find the new user’s PUID and GUID (see previous comments).
  2. Click Main MenuContainer Manager
  3. Click the Image tab
  4. Click ActionImportAdd From URL
  5. Enter https://hub.docker.com/r/photostructure/server and import
  6. Select tag latest
  7. Wait for the image to download (it’s about 500 MB, it may take a minute). You’ll see a system notification when it’s done.
  8. Click Run
  9. You can select resource limitation, but give PhotoStructure at least 2GB. Do not select high CPU priority.
  10. You may want to select Enable auto-start
  11. Click Next.
  12. Configure port settings as you’d like. You can just map port 1787 directly.
  13. Configure volume settings by reading about required and optional volumes and adding entries for
  • /ps/library (must be read/write)
  • /pictures and/or any other existing directories you want to import into your library
  1. Depending on your Synology setup, you may wish to configure additional volumes for
  • /ps/tmp
  • /ps/logs
  • /ps/config
  1. Configure Environment by adding PUID and GUID
  2. Do not select Execute container using high privilege
  3. Configure network settings by selecting bridge.
  4. Click Next, select Run this container after the wizard is finished, then click Done
    and wait for it to start successfully.
  5. Switch to the Container tab, click your new container, then click Details. Then you can:
  • Manually start the new container at any time by clicking Start in top-right
  • If it doesn’t start successfully, switch to the Log tab
  • Email/Discord/etc us if you need help!

Extra credit: while container is running, from Details you can click ActionOpen terminal. Then you can type --status (and hit return) to have PhotoStructure run health checks. (You can also run --pause, --resume, and --exit).

To update, assuming you are using the latest branch then just click the Update available link in Container Manger in the Image tab. For more details see Synology: How to Update Containers in Container Manager – Marius Hosting

1 Like

Edit:
12. Configure Environment user/group by adding PUID and GUID
12.1 Configure Environment time by adding TZ, see List of tz database time zones - Wikipedia, for example set it to America/Los_Angeles.

Via Synology DSM 7.3, using PhotoStructure Docker Compose Wizard

:construction::construction::construction:
This procedure is a work-in-progress using the latest beta, details may change with stable release; and anyway, details are hopefully eventually officially updated in PhotoStructure for Docker | PhotoStructure
:construction::construction::construction:

Figuring this out was greatly aided by Project | Container Manager - Synology Knowledge Center and also https://drfrankenstein.co.uk/jellyfin-in-container-manager-on-a-synology-nas-hardware-transcoding/

  1. Create a new user for photostructure and find the new user’s PUID and GUID as described in this previous comment.

  2. Click Main MenuContainer Manager

  3. Click the Project tab

  4. Click Create

  5. Use PhotoStructure’s Docker Compose Wizard to create your own compose.yaml and Dockerfile. For the paths, reference this config that worked on my Synology to understand what a valid path ought to look like on Synology. https://photostructure.com/server/docker-compose-wizard/?plat=synology&lib=%2Fvolume2%2Fdocker%2Fphstr-test-compose%2Flibrary&puid=1033&port=1788&tz=America%2FChicago&log=debug&nf=1&idf=0&exp=1&scan=ro%3A%2Fvolume1%2FmyShareName%2FMedia%2FPictures%2FCamera+Roll_20201219%2Fmove4%2Freview%2Fpictures&env=PS_ALLOW_FUZZY_DATE_IMAGE_HASH_MATCHES%3Dtrue

  6. Note the compose.yaml from Docker Compose Wizard currently gives image photostructure/server:beta, where the tag is beta. Only the latest tag supports one-click updates using the Image tab in Container Manager, so while beta is necessary for now, latest is the eventual desire.

  7. Note if the Dockerfile downloads as Dockerfile.txt, you will have to rename it to just Dockerfile.

  8. The rest seemed pretty self-explanatory to me, and/or I’ve gone over it in previous comments.

1 Like

Can @tkohhh or someone else who’s a higher trust level than me turn my first post into a wiki?

I see Matt shared this thread in https://photostructure.com/server/photostructure-for-docker/#synology-docker-instructions, but without the first post being an community-editable wiki, , I think the information in this thread is too scattered to easily comprehend.

For a walkthrough with screenshots, see MK Library’s PhotoStructure for Synology guide. Community tips are in the Synology NAS Tips forum thread.

1 Like

I just made all posts wiki. If you want to start anew I could just point to a different page!

Thanks again for sharing what works!

2 Likes

Today I learned about Wiki’s in Discourse! Thanks for pointing this out. I followed your lead and converted my Recommended Unraid Setup to a wiki as well.

Info moved to first post in this thread:

For reference, two upgrade methods I tried which did not work:

Try deleting images without cleaning project:

  1. Project → select Project → Action → Stop
  2. Image → select tagged PhotoStructure images (beta and <none in my case) → Delete
  3. Error: the beta image is in use by a project, even though that project is stopped.

Try cleaning project without deleting images:

  1. Project → select Project → Action → Stop
  2. Project → select Project → Action → Clean. Note that Synology documentation says “Clean” is docker-compose down to “Stop the containers and removes containers, networks, volumes, and images created by the docker-compose.yml of this project.”
  3. Do NOT delete any images
  4. Project → select Project → Action → Build
  5. Issue: Does not download a new version of the image. (I also tested this with Jellyfin which is using latest tag and says Update available in the Images tab – trying to update like this did not work)

Weirdness with and a randomly-generated container name prefix


Edit 1

The following steps cause the container with randomly-generated prefix to appear and disappear.

  1. Stop the project
  2. Edit YAML Configurations
  3. Save
  4. Choose Build and start the project (rebuild the image).

Now the container is rebuilt with a weird prefix, and you get errors when you try interacting with it. To fix it, reboot your Synology. The prefix disappears and you can now interact with it like usual.

I also tried Only save the changes, manually running Clean, and then manually restarting the image, and that seems to have worked as well. No weird container name prefix.

I still do not know where the <none> image comes from.


First off, I do not think this needs to block stable release. Especially since it seemed to resolve itself by rebooting the Synology, except for the <none> image. And especially because I edited YAML from the Synology GUI, I could totally see Synology having some bugs around that.

And if this is a necessary limitation for getting HEIF / HEIC support on Synology without licensing concerns, I can certainly accept that with a documented note in the official PhotoStructure Synology instructions.

Weirdness
To me it seems the official compose YAML (with external Dockerfile?) can cause the project to somehow spawn containers and then disassociate the project from those containers.

  1. https://photostructure.com/server/photostructure-for-docker/#synology-docker-instructions suggests Docker Compose / Synology Projects is the preferred install method, and that is what I am using.
  2. During initial setup of previous version 2026.4.4 in Project tab, it triggered a download of three images in the Image tab. One mwader/static-ffmpeg:8.0.1, one PhotoStructure with beta tag, and one PhotoStructure with <none> tag.
  3. The <none> image is 728MB with sha256:16544981886ee149037257a77f01c5d2c690a0a548a2565938716a5a8203ce04, so maybe it’s simply an issue with beta / stable tags that will go away once we can use latest tag?. I don’t mind this, it’s just weird that it would download something with a <none> tag.
  4. After a day or two I used the Synology GUI in the Project tab to modify the YAML config to stop the project, change PS_MAX_CONCURRENT_IMPORTS=3 to 2 instead, and restart. That spawned a new container with a randomly-generated extra prefix. (The project has the same name, but the container associated with it now has a randomly-generated prefix).
  5. Then when clicking into the project then into the container, there are strange error messages about Container undefined does not exist and Container {"message":"No such container: db077dd5a98f_phstr-full-2026.4.4"} does not exist.
  6. Then when trying to stop the project, it opens up a Terminal window, but nothing stops.
  7. Then when trying to stop the container, it gives an error that there’s no container.
  8. I tried refreshing the Synology webpage web interface and that seemed to help a little previously, but not now.
  9. I tried rebooting the Synology, and then was able to stop the project normally!
  10. After rebooting the Synology, the weird container name prefix disappeared, although the 728MB photostructure <none> image remained.

After updating the project per previous post with Clean, deleting images beta and <none>, but not deleting mwader/static-ffmpeg:8.0.1 image, the <None> image did not return. Maybe because I did not delete the mwader/static-ffmpeg:8.0.1 image? I do not care to test more at this time. Not a big deal, just weird.

000_PhotoStructureDockerImageNone

Thanks! I’ve finished updating my first post to have the latest and greatest info to date, and deleted duplicate info from my other posts.

Install Phone App (PWA) with Synology + Tailscale

This has been a few more hoops to jump through than I really wanted to. But it does feel cool now that it’s working for me!

Four overall steps are necessary:

  1. Configure Tailscale on your NAS and devices
  2. Enable Tailscale MagicDNS and confirm you can access your PhotoStructure library via HTTP at http://your-machine.yak-bebop.ts.net:1787.
  3. Enable HTTPS on your Tailnet
  4. Use Tailscale Serve as a reverse proxy to provide the PhotoStructure service via HTTPS.

I did use SSH to figure out the right commands, but then I referenced steps in Get PUID / GUID from GUI (see 1st post in this thread) for putting the final commands into Synology GUI with its Task Manager and User-defined scripts.

1st script: tailscale enable outbound connections (run as root on boot)

/var/packages/Tailscale/target/bin/tailscale configure-host; synosystemctl restart pkgctl-Tailscale.service

2nd script: tailscale HTTPS certs (run as root, run monthly)

tailscale configure synology-cert

3rd script: tailscale serve x (run as root, only need to run once)
(I run two PhotoStructure containers, one normal and one for testing stuff. Note that mapping 1787 to 1787 works with https://your-machine.yak-bebop.ts.net:1787, but stops working with http://your-machine-ip:1787. To ensure I can still access PhotoStructure without MagicDNS, I chose to serve non-default port 17870 so http://your-machine-ip:17870 remains accessible).

tailscale serve --bg --https=1787 http://localhost:17870
tailscale serve --bg --https=1789 http://localhost:17890

4th script: tailscale serve x off (run as root, just in case)

tailscale serve --bg --https=1787 http://localhost:1787 off
tailscale serve --bg --https=1789 http://localhost:1789 off

5th script: tailscale serve status (run as admin, run as needed)

tailscale serve status

Also see

Note that Tailscale Funnel for sharing services to general internet in general can only listen on ports 443, 8443, and 10000. But Tailscale Serve for sharing services within your tailnet has no such limitation, so port 1787 works fine!