iCloud Photos Sync
Back up your complete iCloud Photos Library to your own disk or NAS, and keep it in sync.
Runs unattended in Docker. A small web UI handles the Apple sign-in, including MFA codes and Advanced Data Protection.
Quick start · Get Started guide · CLI reference
Quick start
You need Docker with docker compose and an Apple ID with two-factor authentication.
1. Create a folder for the library and a docker-compose.yml next to it.
mkdir library
services:
photos-sync:
image: steilerdev/icloud-photos-sync:latest
container_name: photos-sync
restart: unless-stopped
user: "1000:1000" # your user's `id -u`:`id -g`, needs write access to ./library
environment:
APPLE_ID_USER: "<iCloud username>"
APPLE_ID_PWD: "<iCloud password>"
TZ: "Europe/Berlin"
SCHEDULE: "0 2 * * *" # sync every night at 2:00
ENABLE_CRASH_REPORTING: true # optional, helps fixing bugs
ports:
- 80:80 # web UI
volumes:
- ./library:/opt/icloud-photos-library
2. Start it.
docker compose up -d
3. Sign in through the web UI. Open http://<your-host> and select Renew Authentication. Apple sends a code to your trusted devices; enter it in the web UI. Then select Sync Now to start the first sync, or wait for the schedule.
That's it. From now on the library syncs on the schedule. Apple asks for a new MFA code about every 30 days: select Enable Notifications in the web UI to get a push notification when that happens.
Good to know:
- Advanced Data Protection: turn on Access iCloud Data on the Web and approve the request that shows up on your device during the first sync. See Advanced Data Protection.
- No plain-text password: use
APPLE_ID_PWD_FILEwith Docker secrets, or leave the password out and enter it on startup. See Installation. - Large libraries: the first sync of a large library takes hours and may need a higher open-file limit. See Ad-Hoc Sync.
Where are my photos? Every photo and video is in library/_All-Photos (and library/_Shared-Photos for the iCloud Shared Library), named by its iCloud checksum. Your iCloud folders and albums appear as folders next to it, linking to those files. A readable, date-based layout with the original file names is planned for v6 (#354).
Without Docker: npm install -g icloud-photos-sync (Node.js 26 or newer), then run icloud-photos-sync --help. See the Get Started guide for all options.
Features
- Complete library: all originals plus their edits, the iCloud Shared Photo Library and, optionally, the Hidden album
- Your folders and albums mirrored locally, without storing any photo twice
- Advanced Data Protection supported
- MFA made easy: codes through trusted devices, SMS or voice, entered in the web UI. The trust token is cached, so syncs run unattended for about 30 days.
- Efficient incremental sync: only new and changed assets are downloaded; large libraries are supported
- Web UI: sync status, ad-hoc syncs, live logs and push notifications. It can be installed as an app (PWA).
- Safe deletes: assets deleted in iCloud can go to a trash folder instead of being removed
- Archiving: keep an album locally forever and, optionally, delete its non-favorite photos from iCloud to free up storage
- Monitoring: Influx and Prometheus metrics, health check pings
- Secure operation: credentials from files (Docker secrets), shell-free image based on Docker Hardened Images, optional Node.js permission model
icloud-photos-sync is an independent project, and is not affiliated, endorsed, recommended by or otherwise affiliated with Apple Inc.
Why
The only official way to keep a local copy of the full library is a Mac that keeps Photos.app running with Download Originals enabled, and those files can't easily be used outside Photos.app. This project syncs the library to a plain folder on any Linux host or NAS. Read more about the motivation and the maintainer's own workflow.
Documentation
- Get Started guide: installation, authentication, syncing, archiving
- CLI reference: every option and its environment variable
- Web UI, Advanced Data Protection, Health Checks, Sync Metrics, Runtime Hardening, Viewing with Photoview
- Troubleshooting and common warnings
Limitations
This application uses an undocumented iCloud API, which comes with a few limitations:
- Live Photos: only the still image is synced, not the video part (#121).
- iCloud Shared Photo Library: the API doesn't tell where shared assets sit in your folders and albums. Shared assets therefore only appear in
_Shared-Photosand can't be archived. - File types: supported file types are hard-coded, because no complete list is available. If you see an
Unknown filetype descriptorwarning, please report it. - Security keys can't be used as the second factor.
Please also check the open and known issues and existing feature requests.
OS Support
The Docker image is available for linux/amd64 and linux/arm64. The npm package runs wherever Node.js 26 runs, except Windows.
Contributing & Feedback
Please check the contributing guidelines to learn how to engage with this project.
Acknowledgments
Special thanks to: - @konraddysput for help on the Backtrace integration. - @timvahlbrock for their interest in this project and contributions in getting it updated. - All current and past sponsors of this project.