It's mainly just rsync. When the phone was plugged in, the photos were accessible at a path like "/run/user/1000/gvfs/gphoto2:host=Apple_Inc._iPhone_abc123/".
Now I use Time Machine, but I still need to check whether it includes iCloud photos.
While I haven't tested for that myself, the script should keep pretty much everything including image metadata. I just made a small change so that it also keeps extended attributes in case any image-related metadata is there.
The script currently requires changing one or two folder paths at the top (more details in the script).
It's mainly just rsync. When the phone was plugged in, the photos were accessible at a path like "/run/user/1000/gvfs/gphoto2:host=Apple_Inc._iPhone_abc123/".
Now I use Time Machine, but I still need to check whether it includes iCloud photos.