← All Guides
intermediate

Self-Hosting Immich + Syncthing: Auto-Backup Your Phone Photos

Combine Immich and Syncthing for bulletproof phone photo backup. Get a plain-file copy of your camera roll on your server AND a searchable Immich timeline, with no cloud and no subscription.

Budget Homelab ·
dockersyncthingimmichhow-to

This post contains affiliate links. If you buy through them, I earn a small commission at no extra cost to you.

If you already run Immich, your phone photos are backing up through the Immich mobile app, and that works fine. So why add Syncthing to the mix?

One word: independence. The Immich app backup is great, but it is app-managed. Your photos live inside Immich’s storage structure and are tied to Immich’s database. If Immich’s database gets corrupted, if a bad update breaks the upload pipeline, or if you ever want to walk away from Immich entirely, you are at the mercy of one application. Syncthing fixes that by dropping a plain, untouched copy of your camera roll straight onto your server’s filesystem, in a normal folder, with no app in between. Then you point Immich at that same folder so you still get the searchable timeline, face recognition, and map view.

The result is belt and suspenders: one continuously synced file copy you fully control, plus the full Immich experience layered on top of the exact same files. No cloud, no subscription, no second upload.

This is an intermediate guide. It assumes you already have both apps running. If you do not, set up Immich first, then read the Syncthing setup guide, and come back. For Docker fundamentals, start with Docker Compose basics. For the full picture of what to self-host, see the getting started guide.

The architecture

Here is the data flow, start to finish:

[ Phone camera roll ]
        |  Syncthing (Send Only)
        v
[ Server: ~/docker/syncthing/data/phone-photos ]   <-- plain files, your copy
        |  mounted read-only into Immich
        v
[ Immich External Library ]  -->  timeline, faces, search

The key idea is that Syncthing owns the folder and Immich only reads it. Syncthing pushes new camera photos to the server within seconds of you taking them. Immich treats that folder as an “External Library,” which means it indexes the files where they sit instead of copying them into its own upload store. You end up with exactly one copy of each photo on disk, visible both as a normal file and inside Immich.

This is different from the default Immich app backup, where the app uploads each photo into Immich’s managed upload folder and Immich is the only thing that understands the layout. With the external library approach, your file browser, your backup tool, and Immich all see the same plain JPEGs.

A note on platform: Android vs iPhone

Be honest with yourself about your phone before you start.

Android: This works well. The native Syncthing app (or the maintained Syncthing-Fork) can sync your DCIM/Camera folder continuously in the background. This is the setup this guide is built around.

iPhone: This does not work well, and I am not going to pretend otherwise. iOS sandboxing blocks true background folder sync. There is no native Syncthing app, and the third-party Mobius Sync app cannot reliably sync the system camera roll on its own. On iPhone, use the Immich app for camera backup and use Syncthing only between your server and a laptop or desktop. The combo guide below is for Android. iPhone users can still apply the External Library half of it to a desktop photo folder. One extra iPhone gotcha: if iCloud “Optimize Storage” is active, the Immich mobile app can silently back up low-resolution thumbnails instead of originals. See how iCloud Optimize Storage wrecks your Immich backup for the audit and fix.

Prerequisites

A quick word on storage before you commit: your phone library plus the Immich database plus any existing collection can add up fast. If your server boot drive is small, this is a good moment to add a dedicated SSD for photo storage. A 1TB or 2TB SATA SSD is cheap insurance and keeps your photos off the system drive.

Step 1: Create the synced photos folder on the server

Syncthing needs a dedicated folder to receive your camera roll. Make it inside Syncthing’s data directory so it is clearly owned by Syncthing:

mkdir -p ~/docker/syncthing/data/phone-photos

If your Syncthing Compose file mounts ~/docker/syncthing/data into the container (the standard linuxserver.io image mounts /data1, /data2, or a custom path), this folder will show up inside the Syncthing web UI. Confirm the mount in your docker-compose.yml:

services:
  syncthing:
    image: lscr.io/linuxserver/syncthing:latest
    container_name: syncthing
    volumes:
      - ~/docker/syncthing/config:/config
      - ~/docker/syncthing/data:/data
    # ... ports and environment as in the Syncthing guide

The container now sees your new folder at /data/phone-photos.

Step 2: Install Syncthing on the phone

On your Android phone, install Syncthing from the Play Store or F-Droid. (Syncthing-Fork is a popular maintained alternative with better battery controls; either works.)

Open the app, let it generate its Device ID, and grant it storage permission so it can read your camera folder. On modern Android you may need to grant “All files access” in system settings for the camera folder to be readable.

Step 3: Pair the phone with the server

You need each device to trust the other.

  1. On the server Syncthing web UI (usually http://your-server-ip:8384), click Actions -> Show ID and copy the long Device ID.
  2. On the phone, go to the Devices tab, tap the +, and paste the server’s Device ID. Give it a name like “Homelab Server” and save.
  3. Back on the server UI, a prompt will appear asking to add the new device (your phone). Accept it.

Within a minute the two devices should show as “Connected.” If they sit on “Disconnected,” make sure both are on the same network for the first handshake, then they can reconnect remotely later through the relay.

Step 4: Share the camera folder one-way

This is the most important configuration choice in the whole guide: the phone sends, the server receives, and never the other way around.

  1. On the phone, go to the Folders tab and tap + to add a folder.
  2. Set the Folder Path to your camera directory, typically /storage/emulated/0/DCIM/Camera.
  3. Give it a Folder Label like “Camera” and a Folder ID like camera-phone.
  4. Open the folder’s advanced settings and set Folder Type to Send Only.
  5. In the Sharing tab of that folder, check the box for your server device.

Then on the server:

  1. The server UI will show a prompt: a new folder camera-phone is being shared with you. Click to add it.
  2. Set its path to /data/phone-photos (the container path that maps to ~/docker/syncthing/data/phone-photos).
  3. Set the server folder’s Folder Type to Receive Only.

Send Only on the phone and Receive Only on the server means a deleted or edited photo on the server can never propagate back and damage your phone’s camera roll. The phone is the source of truth; the server is a passive copy. This one-directional setup is what makes the whole thing safe to leave running.

Save, and Syncthing will begin copying your camera roll to the server. The first sync of a large library can take a while, so leave both devices on WiFi and the phone charging for the initial pass.

Step 5: Point Immich at the synced folder

Now layer Immich on top. Immich needs read access to the same folder, mounted into its container. Edit your Immich docker-compose.yml and add the synced folder as a read-only volume on the immich-server service:

  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/usr/src/app/upload
      - ~/docker/syncthing/data/phone-photos:/mnt/phone-photos:ro
      - /etc/localtime:/etc/localtime:ro
    # ... rest of the service unchanged

The :ro flag makes the mount read-only. Immich indexes the files but cannot alter or delete them. Recreate the container so the new volume takes effect:

cd ~/docker/immich
docker compose up -d

Step 6: Create the External Library in Immich

  1. In the Immich web UI, go to Administration -> External Libraries.
  2. Click Create External Library and assign it to your user.
  3. Set the Import Path to /mnt/phone-photos (the path inside the container, not the host path).
  4. Save, then click the three-dot menu on the library and choose Scan.

Immich walks the folder, reads each photo’s embedded EXIF data (date taken, GPS, camera model), and builds them into your timeline using the original capture dates. Because Syncthing copies the raw camera files untouched, all that metadata is intact, which means your photos land on the right day on the map in the right place, with no import-date mangling.

Step 7: Set a scan schedule

A one-time scan only catches what exists right now. To keep the library current as Syncthing delivers new photos, set Immich to rescan on a schedule.

  1. Go to Administration -> Settings -> External Library.
  2. Enable Periodic Scanning and set a cron expression. Every few hours is plenty:
0 */3 * * *

That runs a scan at the top of the hour every three hours. Syncthing already moved the files in real time, so the scan is just Immich catching up to index them. There is no rush, and frequent scans on a big library waste CPU on a low-power box.

Step 8: Verify the full pipeline

Take a test photo on your phone, then watch it travel:

  1. Within seconds, the Syncthing folder on the server should gain the file. Check from a shell:

    ls -lt ~/docker/syncthing/data/phone-photos | head
  2. After the next scheduled scan (or a manual one), the photo appears in your Immich timeline.

If the file shows up in the folder but never in Immich, the External Library scan is the thing to check. If it never reaches the folder at all, the problem is in Syncthing, not Immich, so debug the sync first.

Don’t double up: app backup OR external library, not both

A trap worth calling out. If you leave the Immich mobile app backup enabled AND run the Syncthing external library for the same phone, you get two copies of every photo: one uploaded into Immich’s managed store by the app, and one indexed from the Syncthing folder. They will both appear in your timeline as near-duplicates.

Pick one path per device:

ApproachBest forTrade-off
Immich app backup onlySimplicity, iPhonePhotos locked inside Immich’s storage structure
Syncthing + External LibraryAndroid, file independenceMore moving parts to set up

For this guide’s whole reason to exist (a plain-file copy you control), turn off the Immich app’s automatic backup for that phone once Syncthing is delivering reliably. You still get the full Immich timeline from the external library.

Backup strategy: this is not your only backup

Important caveat: Syncthing is sync, not backup. If you delete a photo on your phone, the Send Only folder will not push that deletion to the server, which is good, but Syncthing’s job is replication, not version history. It is not a substitute for a real backup of the server folder.

Treat ~/docker/syncthing/data/phone-photos as production data and back it up like everything else: a scheduled Restic job to Backblaze B2, a second Syncthing copy to another always-on device, or a periodic copy to external storage. A USB SSD or a small NAS gives you a cheap offline copy. The combo in this guide gets your photos onto the server safely. Getting them safely off the server is a separate, equally important step.

Why this setup is worth the extra effort

It comes down to one question: if Immich vanished tomorrow, where are your photos? With app-only backup, the answer is “inside an Immich folder structure I would have to reverse-engineer.” With this setup, the answer is “in a normal folder, named the way my camera named them, that any tool on earth can open.” That portability is the entire point of self-hosting in the first place.

You spend thirty minutes once, and from then on every photo you take lands as a plain file on hardware you own, and shows up in a beautiful searchable timeline, with zero cloud and zero monthly fee.

For the next service to add to your stack, see the best self-hosted apps roundup. For remote access to your Immich timeline without opening ports, set up the Tailscale guide.