ios-backup

ios-backup

Docker app from louij2's Repository

Overview

Scheduled iPhone/iPad backups straight to your array, over Wi-Fi - no Mac, no Windows VM. Makes standard Finder/iTunes (MobileBackup2) backups, so iMazing, Finder or iTunes can open them later, encrypted backups included. Built on pymobiledevice3. Pair each device once over USB (docker exec ios-backup ios-backup pair), then it reaches the phone over a RemotePairing Wi-Fi tunnel on your schedule. Encrypted backups need approving with the passcode on the phone when they start. Status page + Prometheus /metrics on port 9871, optional Discord alerts.

ios-backup

Scheduled iPhone/iPad backups to your server, over Wi-Fi. No Mac, no Windows VM.

It writes standard Finder/iTunes (MobileBackup2) backups, so iMazing, Finder or iTunes can open them later, encrypted backups included. Under the hood it's pymobiledevice3.

  • Pair once over USB. After that, on your schedule it finds the device on your LAN and runs an incremental backup through an encrypted RemotePairing tunnel, the Wi-Fi route Apple uses for iOS 17 and later. The older Wi-Fi sync route no longer works on current iOS.
  • If the device is plugged into the server it uses USB instead, which is quicker for the first full backup.
  • A device that's asleep or away is retried every RETRY_MINUTES for RETRY_WINDOW_HOURS.
  • Status page and Prometheus /metrics on port 9871. Optional Discord alert when a backup fails.

Run

docker run -d --name ios-backup --network host --privileged --restart unless-stopped \
  -v /dev/bus/usb:/dev/bus/usb -v /run/udev:/run/udev:ro \
  -v /srv/ios-backups:/backups \
  -v /srv/ios-backup/config:/config \
  -v /srv/ios-backup/lockdown:/var/lib/lockdown \
  -e TZ=Europe/London -e BACKUP_TIMES=03:00 \
  louij2/ios-backup:latest

--network host is required for Bonjour discovery. --privileged is needed for the Wi-Fi tunnel (a TUN interface) and for USB; /dev/bus/usb is only needed for pairing and USB backups. Unraid users can install it from louij2/unraid-templates.

Pair a device (once)

  1. Plug the iPhone into the server and unlock it.
  2. docker exec -it ios-backup ios-backup pair, then tap Trust and enter the passcode. This also creates the remote pairing that Wi-Fi backups need.
  3. Optional but recommended: turn on encrypted backups. They also include saved passwords, Health and Wi-Fi networks: docker exec -it ios-backup ios-backup pmd3 backup2 encryption on 'YOUR-BACKUP-PASSWORD' Enter the passcode on the phone when it asks. Keep that password: you'll need it to open or restore the backup.
  4. First backup now: docker exec -it ios-backup ios-backup backup. A full backup over USB takes about 1 to 2 hours per 70 GB.

Then unplug it. From now on it backs up over Wi-Fi on your schedule.

Backups need approving on the phone. With encrypted backups on, iOS 26 shows a passcode prompt when a backup starts on a locked phone, and the backup waits until it's answered. So pick a time you usually have the phone (BACKUP_DAYS=sun, BACKUP_TIMES=20:00) rather than the middle of the night. A Discord alert (DISCORD_WEBHOOK_URL) and the ios_backup_waiting_for_passcode metric tell you when it's waiting. Whether unencrypted backups skip the prompt is untested.

Private Wi-Fi Address: set it to Fixed (or Off) for your home network on the phone, under Settings → Wi-Fi → (i). A rotating address breaks Wi-Fi sync for every tool, Finder included.

Open the backups with iMazing (Mac)

  1. In Finder, connect to the share (Go → Connect to Server, e.g. smb://tower/backups).
  2. In iMazing, open Preferences → Backups and add the backups folder (the one that holds the <UDID> folders) as a backup location.
  3. The device's backup shows up in iMazing's backup list. Browse messages, photos and so on, or restore from it. Enter the backup password if it's encrypted.

You can also browse without iMazing: ios-backup pmd3 backup2 unback /backups/<UDID> --password ... (on a copy).

Configuration

Variable Default
BACKUP_TIMES 03:00 Comma-separated HH:MM, container time zone (TZ)
BACKUP_DAYS – (daily) Comma-separated days, e.g. sun or mon,thu
RETRY_MINUTES 20 Retry interval while a device is unreachable
RETRY_WINDOW_HOURS 5 Stop retrying after this long
BACKUP_TIMEOUT_HOURS 8 Kill a stuck backup
DISCORD_WEBHOOK_URL – Alert on failures and when a backup needs approving
NOTIFY_SUCCESS false Also post successes
UDIDS – Only back up these devices; the default is every paired device
PORT 9871 Status page + /metrics
RUN_ON_START false Run a round when the container starts
USBMUXD true false = Wi-Fi only
PUID / PGID 99 / 100 Owner of finished backups (Unraid's nobody:users)
VERBOSE false Debug logging from pymobiledevice3 into each run's log

Commands, all run with docker exec ios-backup ios-backup ...: pair, backup [UDID], status, and pmd3 ... (passthrough to pymobiledevice3).

Metrics: ios_backup_last_success_timestamp_seconds, ios_backup_last_ok, ios_backup_size_bytes, ios_backup_last_duration_seconds, ios_backup_running, ios_backup_progress_percent, ios_backup_usb_connected, ios_backup_wifi_reachable, ios_backup_waiting_for_passcode, ios_backup_safe_to_unplug (0 only while a USB backup is running), all labelled udid/name.

Security

/var/lib/lockdown holds the pair records, and they give full access to the paired devices. Keep that folder private, and use encrypted backups.

Licence

MIT

Requirements

Host networking (Bonjour discovery) and privileged mode (Wi-Fi tunnel TUN interface, USB access). A USB port on the server is needed once per device for pairing.

Download Statistics

102
Total Downloads

Related apps

Explore more like this

Explore all

Details

Repository
louij2/ios-backup:latest
Last Updated2026-11-05
First Seen2026-11-05

Runtime arguments

Web UI
http://[IP]:[PORT:9871]/
Network
host
Shell
bash
Privileged
true
Extra Params
--restart=unless-stopped

Template configuration

BackupsPathrw

Each device gets a UDID folder in standard Finder/iTunes format

Target
/backups
Default
/mnt/user/backups/ios
Value
/mnt/user/backups/ios
ConfigPathrw

State, logs

Target
/config
Default
/mnt/user/appdata/ios-backup
Value
/mnt/user/appdata/ios-backup
Pair recordsPathrw

Device pair records - these grant full access to the paired devices; keep this folder private

Target
/var/lib/lockdown
Default
/mnt/user/appdata/ios-backup/lockdown
Value
/mnt/user/appdata/ios-backup/lockdown
USB devicesPathrw

For USB pairing and USB backups

Target
/dev/bus/usb
Default
/dev/bus/usb
Value
/dev/bus/usb
udevPathro

USB hotplug for usbmuxd

Target
/run/udev
Default
/run/udev
Value
/run/udev
Backup timesVariable

Comma-separated HH:MM (container TZ). Unreachable devices are retried every RETRY_MINUTES for RETRY_WINDOW_HOURS.

Target
BACKUP_TIMES
Default
03:00
Value
03:00
Backup daysVariable

Comma-separated days, e.g. sun or mon,thu. Blank = daily. Encrypted backups need approving on the phone, so pick a time you have it.

Target
BACKUP_DAYS
TZVariable

Timezone for the schedule

Default
Europe/London
Value
Europe/London
Web UI portVariable

Status page and /metrics

Target
PORT
Default
9871
Value
9871
Discord webhookVariable

Optional: alert on failed backups and when a backup needs approving on the phone

Target
DISCORD_WEBHOOK_URL
Notify on successVariable

true = also post successful backups

Target
NOTIFY_SUCCESS
Default
false
Value
false
Retry minutesVariable
Target
RETRY_MINUTES
Default
20
Value
20
Retry window hoursVariable
Target
RETRY_WINDOW_HOURS
Default
5
Value
5
Only these UDIDsVariable

Optional comma list; default = every paired device

Target
UDIDS