I spend nearly every weekend with my SLR camera, but the last thing I want to do when I get home is pull out my computer to upload, organize, and backup the photos. I just feels like work. I know newer cameras have WiFi and all that, but my trusty D3300 isn’t going to be replaced anytime soon. That’s where I got the idea for PiPhoto.


PiPhoto makes your raspberry pi automatically upload your photos when you insert your SD card.

Here is a video showing PiPhoto uploading photos to OSX:

In this post, I’ll discuss the core components and challenges I faced. I’ve open-sourced the project on Github.

Mounting the SD Card on Insert

The first challenge I faced was how to automatically mount the sd card when it is inserted inserted into the Raspberry Pi. UDev is the commonly accepted way to do this. With some help from the Arch Wiki, I settled upon this rule:


ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", RUN{program}+="/usr/bin/systemd-mount --no-block --automount=no $devnode /media"

This tells the system to mount any filesystem block device to /media when it is inserted into the USB port. Just pop that file into /etc/udev/rules.d/ and you’re good to go.

Triggering A Command on Mount

Once the sd card is mounted, I wanted to trigger a command to be run that would upload the photos to my computer, cloud, whatever. Though systemd is controversial, I found it was pretty easy to write a quick service that did just that:


Description=PiPhoto Trigger on Usb Mount



This systemd service triggers the piphoto command to execute when the /media directory is mounted.

Un-Mounting When The Job is Finished

Once the media are uploaded, I wanted the pi to unmount the sd card. This actually turned out to be a bit tricky: If the piphoto command called unmount, then systemd would kill the piphoto.service, and it would report an error. Alternatively, if you have the systemd service call umount after exit using ExecStartPost, then it catches the cyclic logic and throws an error.

My solution was to have the systemd process unmount the drive, but do so in a different process. A quick and easy way to achieve this was to use at:

ExecStartPost=/bin/bash -c 'echo "systemd-umount /media" | at now'

This is a bit of a hack, so I’m open to better solutions :D.

Adding LED Feedback

Okay, so now I have the pi:

  • mounting the sd card when inserted
  • executing the piphoto command
  • umounting the sd card when complete

Next, I wanted to add some user feedback so I know if the job failed. To do this, I leveraged the pi’s on-board LEDs.

As noted in the Pi Docs, you can change how the LED behaves by sending a string to /sys/class/leds/led{number}/trigger. There are a number of different options such as timer to flash the led and default-on to keep it steady.

First, I made the green light flash while the photos were uploading:

echo timer | tee /sys/class/leds/led0/trigger

and solid green when the syncing was complete:

echo 'default-on' | tee  /sys/class/leds/led0/trigger > /dev/null

Finally, I wanted the red led to flash if the sync command failed. Putting this all together into the pihole script:

# start flashing the green led
echo timer | tee /sys/class/leds/led0/trigger

# upload the files
rsync -rav -e ssh /media ...

# Indicate success or failure
if [ $sync_status -eq 0 ] ; then
    # sync successful
    echo 'default-on' | tee  /sys/class/leds/led0/trigger > /dev/null
    # sync failure
    echo 'none' | tee /sys/class/leds/led0/trigger > /dev/null
    echo timer | tee /sys/class/leds/led1/trigger > /dev/null

Using in Practice

Above I’ve detailed the basics of how PiPhoto works. In the open-source release, you can easily change the sync command to fit your needs. I’ve included guides for:

In addition, I added error handling and a Udev rule to reset the leds when you remove your SD card.

I’ve already found PiPhoto to be a great convenience in my life. I hope you do too! If you find problems or have ideas, please hit up the issue tracker on github.