FreeBSD support

I’m filing this under Support rather than in Feature Requests because this is more of a question than a request.

I run FreeBSD on my desktop and would like to run Photostructure on it. Has anyone here attempted to do so?

I checked to see if the dependencies are in the main ports tree and they are so I was going to create a jail to experiment in and try to install Photostructure via the Node installation guide. I’ll report back once I’ve done so but was hoping others might have attempted this already and could shed some light on your failures/successes.

Welcome to PhotoStructure, @distefam !

Porting PhotoStructure to new OSes can be nontrivial.

  1. We need to get all the third-party libraries and tooling to work nicely on FreeBSD. I expect third-party javascript-only libraries should work, but native libraries (especially SQLite and libVIPS) may need build tweaks to successfully compile on FreeBSD.

  2. Volume scanning will fail, as PhotoStructure’s “posix-but-not-mac” scanning requires a working lsblk. The only port I found was implemented in shell, and doesn’t support the lsblk -P -b --output mountpoint,label,uuid command, so I’d need to cook up a specific-to-bsd command line to get volume labels and UUIDs.

    If volume scanning failed, a hack workaround would be to forgo library portability, and just use file:// URIs in your library database for all asset files found outside of your library directory. This might not be too hard… I’ll poke at it a bit.

Wow, thank you for the thorough reply @mrm! And, thank you especially for what looks to be an amazing software package. I’m very much looking forward to running it. We have our first child on the way and I’ve been digging into photo management solutions in anticipation.

It looks like there are some ways to run docker on FreeBSD - would that be feasible for you?

And congrats on the new baby! Make backups of your pics a very high priority.

And if they give you little thermal prints (how quaint) of any ultrasounds, scan them for safe keeping, they degrade very fast (learned that the hard way).

Thank you for the suggestion and the congratulations.

Docker isn’t really supported on FreeBSD and while I don’t doubt others have managed to get it working I’d prefer a more native solution if at all possible.

Some other things that might work:

  • Use a Linux Jail. I’ve used native FreeBSD jails before but never Linux ones and I’m not sure how well they’re supported.
  • Run photostructure as a server within a bhyve VM and use the virtualized networking to access the interface from my host machine.



  1. Take more videos.
  2. Sleep when they do. Really. Naps are key.
  3. At 3am, when the blob in front of you is a screaming meemee and I couldn’t figure it out, I’d always have forgotten one of the Big Three. Fed? Clean? Burped? (Now you won’t!)
  4. See 1.

(When our kids were little, video technology was basically moving postage stamps, and storage was expensive, so I didn’t take that many, but (assuming you have good photo management software), you’ll never have regret that you pushed the shutter button too much).

1 Like

I managed to get Photostructure running on FreeBSD according to one of the potential methods I listed above: running within a Bhyve VM. I’m going to document below how I did it so that others can replicate the install and so that I can remember it myself. Also, it would be useful to hear from others if I overlooked some things and/or if there is an easier way to handle something.

How to Install Photostructure on FreeBSD


  1. Install Alpine Linux in a dedicated Bhyve VM
  2. Install Docker and docker-compose inside of Alpine Linux VM
  3. Mount directories from host inside of Alpine linux VM using SSHFS
  4. Configure docker-compose file & install
  5. Set-up automatic loading

1. Install Alpine Linux in a dedicated Bhyve VM

First, install the dependencies for Bhyve as well as vm-bhyve, which helps manage Bhyve Virtual Machines with an easy to understand CLI.

Note: most of what follows comes from this very helpful YouTube video

1a. Install vm-bhyve and set-up volumes

The following is mostly a replication of the vm-bhyve quick-start instructions

# pkg install vm-bhyve

Set up ZFS dataset for bhyve. Be sure to use zfs list to check your root data pool off of which you will create your new dataset, mine is zroot.

# zfs create zroot/vm

Enable Bhyve virtualization via sysrc:

# sysrc vm_enable="YES"
# sysrc vm_dir="zfs:zroot/vm"

Tell vm-bhyve to initialize its directories:

$ vm init

Copy the Alpine Linux vm-bhyve template into your vm-bhyve working directory:

# cp /usr/local/share/examples/vm-bhyve/alpine.conf /zroot/vm/.templates/

Modify the template. You will need to replace all instances of “vanilla” with “lts” for Alpine but other than that the defaults will work. I gave mine 8 cpu cores and 16GB of RAM but do what works for you.

Set-up a “virtual switch” for networking:

# vm switch create public “public” is just a name suggested by the quick-start, it can be anything
# vm switch add igb0 Replace igb0 here with your primary network device returned by ifconfig

Have vm-bhyve download the Alpine Linux installation image. Note, vm-bhyve stores these isos in a hidden directory that is a sibling of the above .templates directory.

$ vm iso {alpine_linux_iso_url}

Create the virtual machine that we will be using:

I’m naming it “docker” but you can name it whatever you like. -t refers to the template name (sans extension) and -s tells it the size. Since we used ZFS above the size isn’t fixed but can expand to the amount listed. I gave mine 100GB capacity.

# vm create -t alpine -s 100G docker
# vm list will show your new virtual machine (note Alpine hasn’t been installed yet)

Install Alpine Linux into the VM:

# vm install docker alpine_iso_file_name.iso.
Note, run vm iso to get the full file name and copy-paste it into the above command.

Attach to your vm console:

# vm console docker

Here, you will finish the Alpine installation from inside of the VM. Do whatever you would ordinarily do for Alpine Linux. Personally, I just used root for everything since this is inside of a VM and docker wants to run as root anyway.

2. Install Docker and docker-compose inside of Alpine Linux VM

Allow Alpine Linux to use all apk repositories by uncommenting all lines in /etc/apk/repositories. Then, run apk update and proceed to install docker and docker-compose:

docker # apk update
docker # apk add docker docker-compose

Set up docker to run at boot and start it now:

docker # rc-update add docker boot
docker # service docker start

3. Mount directories from host inside of Alpine linux VM using SSHFS

I want to use directories on my host for holding photos so that I can easily back them up with my normal system backups. So, I’ll be mounting those host directories into the Alpine Linux VM while leaving the tmp directory directly in the VM for speed.

The first step is to generate an SSH key on the vm and add that to the known_hosts on the host computer. I won’t go into how to do that here as it’s pretty straightforward.

If you configured the networking as above the host and the vm will each have their own unique IP addresses, which you can query using ifconfig or something similar. I have my router set these as static for both the host and the vm so the IPs don’t change and can reliably connect without local DNS.

Once you have the keys set up then you’ll need to install sshfs on your Alpine vm:

docker # apk add sshfs

Then, mount your desired directories:
Host → VM
/home/username/photostructure -> /mnt/photostructure

Before we go ahead and mount the above directory we need to create the mountpoint on the vm:

docker # mkdir -p /mnt/photostructure

Then, go ahead and mount it:

docker # sshfs username@ip.address:photostructure /mnt/photostructure

4. Configure docker-compose file & install

First, let’s create the volumes that will be used by Photostructure. Note, these will only be in the vm and not mounted from the host.

source (inside of vm but not inside of docker images):
docker # mkdir -p "${HOME}/.cache/photostructure"
docker # mkdir -p "${HOME}/.config/PhotoStructure-docker"
docker # mkdir -p "${HOME}/.config/PhotoStructure/logs

Now, create a directory for photostructure to store its Docker information:

docker # mkdir ~/photostructure && cd ~/photostructure

Let’s create a docker-compose.yml file now:

docker # vi docker-compose.yml

The contents of this file should be according to the one in the official Photostructure instructions for docker-compose.

Some relevant portions:

# mounted library from host using sshfs
- type: bind
  source: /mnt/photostructure
  target: /ps/library


  # necessary to keep the local library inside the vm for speed

Those are the only differences between what you need and what’s in the official documentation. Oh, and do not include the user: port line as we want to use root.

5. Set-up automatic loading

We set up Docker to run automatically when the VM starts above and the compose file will automatically start PhotoStructure. However, the sshfs directories will not be mounted at this time from the host. I’ve attempted to do this by modifying /etc/fstab but can’t seem to get it to work with sshfs properly so that the directories are mounted before PhotoStructure starts.

Finally: Run

On your VM from within the directory that holds your docker-compose.yml file:

docker # docker-compose up --detach

Now, on your host (or any device on your local network) open a browser and navigate to:


If all worked you should see PhotoStructure up and running!

Thank you so much! Our little girl was born last Tuesday and your advice about videos is already paying off. Grandparents can’t stop watching a video we took of her with hiccups!

1 Like

I saw in the Beta 10 announcement post that there is a new variable called remoteFilesystemTypes, which seems to imply that there is some way to mount via sshfs directly with settings in PhotoStructure but I couldn’t find out how to do so. If this is possible it would greatly simplify Step 3 above as we wouldn’t have to manually mount host directories with sshfs but instead let PhotoStructure do it. This would also obviate the problem with needing to mount the directories before PhotoStructure starts. @mrm is this possible? If so, how can I get PS to mount sshfs directories?

This setting only lets PhotoStructure figure out if a given volume is local or remote, if it can’t tell via other clues.

Remote filesystems are handled a bit differently than local: if the library is stored remotely, the database will be interacted with via a local filesystem replica, for example.

I don’t have any code to do this yet: I was expecting people to bind mount the sshfs volume into their docker image (rather than having Alpine do the sshfs/fuse dance).

If it’d be convenient to have PhotoStructure look for a script or something to run within the container at startup, holler and I can add that. Maybe something like PS_RUN_AT_STARTUP=/opt/ and then add this to

if [ -x "$PS_RUN_AT_STARTUP" ] ; then

(if you know of a standard env token I can adopt instead of PS_RUN_AT_STARTUP, I’m happy to use that instead)

I just got VirtFS mounting working, which is a major improvement over sshfs, both in terms of simplicity and speed.

Rather than sharing SSH keys between your FreeBSD host machine and your Docker guest (not to mention worrying about permissions) you can specify a folder to be shared from the host config file and mount it from the guest.

From the FreeBSD host, configure the sharing:
# vm configure {vm_name}

# Config file

Next, from inside the Docker guest test the share by mounting manually:
# mount -t 9p -o trans=virtio share_name /mnt/share_name

If you’re happy with this, add an entry to /etc/fstab on the Docker guest:

# /etc/fstab

share_name    /mnt/share_name    9p    trans=virtio,rw    0  0