Files
immish/docs/backup.md

13 KiB

Backup & Upload

This document describes the photo/video backup functionality, including foreground and background uploads.

Backup Overview

The backup system automatically uploads photos and videos from the device to the server:

┌─────────────────────────────────────────────────────────────┐
│                     Backup Flow                              │
├─────────────────────────────────────────────────────────────┤
│  Device Photos    →    Backup Service    →    Server        │
│                                                             │
│  1. Select albums to backup                                 │
│  2. Find new/changed assets                                 │
│  3. Check for duplicates (hash)                             │
│  4. Upload assets                                           │
│  5. Update local database                                   │
└─────────────────────────────────────────────────────────────┘

Backup Configuration

Backup Controller Screen

┌─────────────────────────────────────────────────────────────┐
│  ←  Backup                                                  │
├─────────────────────────────────────────────────────────────┤
│  Backup Status                                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  ✓ Backup Complete                                   │   │
│  │  1,234 of 1,234 backed up                           │   │
│  │  Last backup: 2 hours ago                            │   │
│  └─────────────────────────────────────────────────────┘   │
├─────────────────────────────────────────────────────────────┤
│  Backup Albums                                              │
│  [Select albums to backup]                                  │
├─────────────────────────────────────────────────────────────┤
│  Excluded Albums                                            │
│  [Select albums to exclude]                                 │
├─────────────────────────────────────────────────────────────┤
│  Settings                                                   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Background Backup              [Toggle: ON]         │   │
│  │  Use Wi-Fi only                 [Toggle: ON]         │   │
│  │  Require charging               [Toggle: OFF]        │   │
│  │  Ignore iCloud assets           [Toggle: OFF]        │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘

Album Selection

Backup Albums

  • Select which device albums to back up
  • "Recents" includes all photos
  • Individual albums for selective backup

Excluded Albums

  • Exclude specific albums
  • Useful for Screenshots, WhatsApp Images, etc.
  • Takes precedence over selected albums

Album Selection Logic

Backup Candidates = Selected Albums - Excluded Albums

If "Recents" selected (Android):
  - Back up all device photos
  - Individual album folders tracked for sync

If "Recents" selected (iOS):
  - Use "All Photos" album
  - Check against excluded albums per asset

Backup Process

Step 1: Build Upload Candidates

1. Get selected backup albums
2. Get excluded backup albums
3. For each selected album:
   a. Check if album modified since last backup
   b. Get assets newer than last backup time
   c. Add album name to asset metadata
4. Remove assets from excluded albums

Step 2: Remove Already Uploaded

1. Check local duplicates database
2. Call server to check existing assets

POST /assets/exist
Body:
{
  "deviceAssetIds": ["local-id-1", "local-id-2", ...],
  "deviceId": "device-uuid"
}

Response:
{
  "existingIds": ["local-id-1"]
}

Step 3: Upload Assets

For each asset:

1. Get original file from device
2. If live photo, also get video component
3. Calculate upload metadata
4. Upload via multipart form

POST /assets
Content-Type: multipart/form-data

Fields:
  - deviceAssetId: local ID
  - deviceId: device UUID
  - fileCreatedAt: creation timestamp
  - fileModifiedAt: modification timestamp
  - isFavorite: boolean
  - duration: video duration

Files:
  - assetData: the file
  - livePhotoData: motion video (if applicable)

Step 4: Handle Response

200 OK: Asset already exists (duplicate)
201 Created: Asset uploaded successfully

Response:
{
  "id": "remote-asset-uuid",
  "deviceAssetId": "local-id",
  ...
}

Upload Progress Tracking

Progress Model

CurrentUploadAsset {
  id: String           // Local asset ID
  fileName: String     // File name
  fileType: String     // IMAGE, VIDEO, etc.
  fileSize: Integer    // Bytes
  fileCreatedAt: DateTime
  iCloudAsset: Boolean // Downloading from iCloud
}

UploadProgress {
  bytesUploaded: Integer
  totalBytes: Integer
  percentage: Double
}

Progress UI

┌─────────────────────────────────────────────────────────────┐
│  Uploading...                                               │
│                                                             │
│  IMG_1234.jpg                                               │
│  [████████████░░░░░░░░░░░░░░░░░] 45%                       │
│                                                             │
│  12 of 50 • 2.4 MB / 5.1 MB                                │
└─────────────────────────────────────────────────────────────┘

Background Backup

Platform Differences

Android:

  • Uses WorkManager for scheduling
  • Triggers on content changes
  • Requires battery optimization disabled

iOS:

  • Uses Background App Refresh
  • Limited execution time
  • BGProcessingTask for longer uploads

Background Service Configuration

RequireUnmetered: true/false   // Wi-Fi only
RequireCharging: true/false    // Charging only
TriggerDelay: 5000ms           // Minimum delay
MaxDelay: 50000ms              // Maximum delay

Background Notification

┌─────────────────────────────────────────────────────────────┐
│  Immich                                                     │
│  Uploading 12/50 photos...                                  │
│  [Progress bar]                                             │
└─────────────────────────────────────────────────────────────┘

Background Process Flow

1. System triggers background task
2. Acquire lock (prevent concurrent runs)
3. Load translations
4. Initialize database
5. Set API endpoint
6. Get selected/excluded albums
7. Run backup process
8. Update last backup timestamps
9. Release lock

iCloud Assets (iOS)

Handling iCloud Photos

  1. Check if asset is locally available
  2. If not, option to download from iCloud
  3. Show progress during download
  4. Upload after download complete

Settings

  • ignoreIcloudAssets: Skip assets not on device

Album Sync Feature

Purpose

Automatically organize uploads into server albums matching device album names.

How It Works

  1. Asset uploaded with album names in metadata
  2. After upload, check for matching albums
  3. Create album if doesn't exist
  4. Add asset to album

API

POST /albums/{albumName}/assets
Body:
{
  "assetIds": ["uploaded-asset-id"]
}

Duplicate Detection

Hash-Based Detection

  1. Calculate file hash (checksum)
  2. Store in local duplicates database
  3. Skip uploads for known duplicates

Server-Side Check

POST /assets/exist

Checks if assets already on server by device ID + local ID

Error Handling

Retry Logic

  • Failed uploads retry automatically
  • Exponential backoff
  • Maximum retry attempts

Error Notifications

┌─────────────────────────────────────────────────────────────┐
│  ⚠️ Upload Failed                                           │
│  IMG_5678.jpg could not be uploaded                         │
│  Error: Network connection lost                             │
└─────────────────────────────────────────────────────────────┘

Common Errors

Error Cause Action
Network error No connection Retry when online
Quota exceeded Storage full Stop backup, notify user
File not found Asset deleted Skip asset
Permission denied Gallery access lost Request permission

Failed Uploads Screen

Layout

┌─────────────────────────────────────────────────────────────┐
│  ←  Failed Uploads                                          │
├─────────────────────────────────────────────────────────────┤
│  5 uploads failed                                           │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 📷 IMG_1234.jpg                                      │   │
│  │    Network timeout                                   │   │
│  │    [Retry]                                          │   │
│  └─────────────────────────────────────────────────────┘   │
│  ...                                                        │
├─────────────────────────────────────────────────────────────┤
│  [Retry All]                                                │
└─────────────────────────────────────────────────────────────┘

Backup Statistics

Tracked Metrics

  • Total assets to backup
  • Successfully uploaded
  • Failed uploads
  • Duplicate (already on server)
  • Last backup timestamp

Storage Usage

GET /users/me

Response includes:
{
  "quotaUsageInBytes": 1234567890,
  "quotaSizeInBytes": 10737418240
}

Cellular Data Settings

Options

  • useCellularForUploadPhotos: Allow photo upload on cellular
  • useCellularForUploadVideos: Allow video upload on cellular

Previous: Gallery Viewer | Next: Download