Architecture Overview¶
Apple Juicer is composed of five cooperating subsystems:
- FastAPI backend – hosts REST endpoints for discovery, unlocking, manifest browsing, and artifact exports.
- Redis + RQ worker – runs asynchronous ingestion jobs that parse SQLite artifacts and populate Postgres.
- PostgreSQL – persists backups, sessions, manifest indexes, and normalized artifact tables.
- React + Vite frontend – provides the investigator UI and speaks to the backend via authenticated JSON APIs.
- Backup filesystem layer – mounts Finder/iTunes backups, unlocks encrypted bundles, and exposes Manifest data.
Runtime Topology¶
Browser ──▶ Frontend (Nginx → React)
│ ↳ fetch() w/ X-API-Token & X-Backup-Session
▼
FastAPI backend ──▶ Postgres (async SQLAlchemy)
│
├─▶ Redis (RQ) ──▶ Worker pods (rq worker default)
│
└─▶ BackupFS (iphone_backup_decrypt + local paths)
- The backend is stateless; it uses Redis for session caches and Postgres for durability.
- Workers share the same container image as the backend to reuse parsers and settings.
- Backups remain on disk and are mounted read-only into backend/worker containers.
Major Data Flows¶
- Discovery –
BackupRegistryscansbackup_paths.base_path, records metadata in Postgres, and exposes summaries via/backups. - Unlocking –
UnlockManagerdecrypts encrypted backups usingiphone_backup_decrypt, caches a live session, and issues anX-Backup-Sessiontoken. - Manifest browsing – the frontend pages through
/backups/{id}/filesand/domains, streaming metadata without copying payloads. - Artifact indexing – the frontend dispatches a job that enqueues
index_backup_job→ worker parses domain-specific SQLite DBs and writes normalized rows plus a search index. - Downloads – the backend extracts requested files into a temporary sandbox and streams them to the browser, deleting the sandbox via a Starlette
BackgroundTask.
Each step is fully asynchronous, making it straightforward to scale backend replicas, workers, or Postgres independently as data volumes grow.