An open API service indexing awesome lists of open source software.

https://github.com/gastonmorixe/macback

A powerful, interactive macOS backup and restore CLI
https://github.com/gastonmorixe/macback

apple backup backup-script config mac mac-apps macos time-machine

Last synced: 5 days ago
JSON representation

A powerful, interactive macOS backup and restore CLI

Awesome Lists containing this project

README

          


macback

macback

Interactive macOS backup and restore CLI


License: MIT
CI
ShellCheck
Platform: macOS

---

**macback** backs up and restores your entire macOS environment: files, configs, Homebrew packages, system metadata, and more. It runs in an **interactive terminal UI** with smart defaults that exclude caches, build artifacts, and iCloud clutter automatically. Built entirely in Bash, powered by [rclone](https://rclone.org/).

## ✨ Features

- πŸŽ›οΈ **Interactive TUI**: arrow keys, vim bindings (`j`/`k`), `/` filtering, and `Space` multi-select
- πŸ“¦ **Modular components**: back up files, Homebrew, keychain metadata, launchd metadata, and system snapshots independently
- 🧠 **Smart defaults**: iCloud paths, caches, `node_modules`, build artifacts, and other rebuildables are excluded automatically
- πŸ”„ **rclone-powered**: reliable file transfer with progress reporting and integrity verification
- πŸ›‘οΈ **Destination guard**: supervises `rclone` and pauses the backup if the selected volume disappears, remounts elsewhere, or no longer matches the original mount identity
- πŸ”’ **SHA256 checksums**: `rclone check` verifies that backups are complete and correct
- πŸ“‹ **JSON manifests**: spec versioning for structured metadata and forward compatibility
- ⏸️ **Resume support**: pick up interrupted backups without re-copying transferred files
- 🎯 **Granular restore**: choose which components, paths, and individual app configs to restore
- πŸ₯ **Doctor command**: diagnose and fix backup health, permissions, and integrity issues
- πŸ§ͺ **Comprehensive tests**: unit + integration + PTY coverage powered by BATS
- πŸ” **Runs as root**: full access to system files and Library data, with automatic user detection

## πŸ“¦ What Gets Backed Up

| Component | Contents |
|---|---|
| **Files** | Projects, Documents, Desktop, Downloads, SSH keys, GPG keys, shell configs, dotfiles, Library preferences, Mail, Messages, LaunchAgents |
| **Homebrew** | Brewfile, formula/cask lists, taps, leaves, services. Everything needed to reconstruct your dev environment |
| **Keychain metadata** | Keychain discovery and locations (metadata only, no secrets exported) |
| **Launchd metadata** | User LaunchAgents and custom system LaunchDaemons/LaunchAgents |
| **System snapshot** | macOS version, machine serial, hostname, full application inventory |

## 🚫 What Gets Excluded

macback skips things you can rebuild:

- ☁️ **iCloud**: Mobile Documents, CloudStorage, iCloud app support
- πŸ—‘οΈ **System caches**: `.DS_Store`, Library Caches/Logs/WebKit, Xcode DerivedData
- πŸ“¦ **Package caches**: `node_modules`, `.pnpm-store`, `.yarn/cache`, `.bun/install/cache`
- πŸ”¨ **Build artifacts**: `__pycache__`, `.pytest_cache`, `.gradle`, `target/`, `.terraform`
- πŸ”Œ **Socket files**: `.gnupg/S.*`, `*.sock`, agent sockets

All defaults are customizable through the **interactive rules editor** during backup.

## πŸ“‹ Requirements

- **macOS** (tested on macOS 13+)
- **Bash 4+** (ships with macOS or install via Homebrew)
- **[rclone](https://rclone.org/)**: `brew install rclone`
- **Homebrew** (optional, only needed for the Homebrew component)

## πŸš€ Installation

```bash
git clone https://github.com/gastonmorixe/macback.git
cd macback
make bootstrap # checks for shellcheck and bats-core
```

## πŸ“– Usage

### Interactive mode

```bash
sudo bash ./macback
```

Opens the TUI main menu:

```
macback
macOS backup and restore

Mode Interactive
Primary user youruser
Primary home /Users/youruser

❯ Backup Create a new backup run
Restore Restore from an existing backup
Inspect View backup metadata and verification state
Doctor Check and fix backup health and permissions
Help Usage information
Quit Exit the tool
```

### Direct commands

```bash
sudo bash ./macback backup # guided backup flow
sudo bash ./macback restore # guided restore flow
sudo bash ./macback inspect # inspect an existing backup
sudo bash ./macback doctor # check and fix backup health
sudo bash ./macback help # show usage information
```

## ⌨️ TUI Controls

| Key | Action |
|-----|--------|
| `↑` / `k` | Move up |
| `↓` / `j` | Move down |
| `Enter` | Select / Confirm |
| `Space` | Toggle selection (multi-select) |
| `a` | Select all visible |
| `u` | Unselect all visible |
| `/` | Filter / Search |
| `q` | Cancel / Back |

## πŸ›‘οΈ Destination Safety

For local-disk backups, `rclone` only sees a filesystem path. It does not know that `/Volumes/My Disk` is supposed to remain bound to the same physical external drive for the entire run. Because of that, macback wraps the file-copy/check steps with a parallel destination guard.

- Before `rclone` starts, macback records the selected destination mount root, filesystem device id, and volume UUID when available.
- While `rclone` runs, a watcher checks that identity every 2 seconds.
- If the destination disappears or remounts under a different `/Volumes/...` path, macback stops `rclone` and pauses the backup instead of trusting the stale pathname.
- If the same volume UUID comes back under a new mount path, macback can offer to continue the same run on the remounted volume.
- Stale `/Volumes/...` directories that are not real mounted volumes are rejected before a run is created or resumed.
- File backups use `rclone --inplace` to avoid `.partial -> final` rename failures on external filesystems.
- Backup asks you to choose a speed profile:
- `Normal`: safer defaults, full `rclone check` on new runs
- `Fast`: more parallelism, skips the long post-copy `rclone check`
- `Ultrafast`: highest parallelism, skips full verification and compares by size only
- When you resume an existing backup run, macback always skips the full post-copy `rclone check` so the restart path focuses on copying what is still missing.

This is a strong supervisory guard, not a per-write guarantee. Writes already in flight when the destination changes may still complete or fail before the watcher stops `rclone`.

## πŸ—οΈ Architecture

```
macback # main entrypoint
lib/
common.sh # environment detection, utilities, manifest discovery
ui.sh # terminal UI framework (colors, selectors, widgets)
templates.sh # backup rule template expansion (@HOME@ tokens)
filter.sh # rclone filter generation
destination.sh # destination volume selection, mount identity capture, remount lookup
manifest.sh # manifest creation, validation, integrity checks
components.sh # backup components plus the rclone destination watcher/pause flow
restore.sh # restore workflows, path remapping, permission reconciliation
templates/
include-paths.txt.template # default paths to back up
exclude-patterns.txt.template # default exclusion patterns
```

Backups are stored on the destination volume under `macback///`:

```
meta/
run.json # run metadata (timestamps, source info, versions)
manifest.json # component flags and restore defaults
include-paths.txt # resolved include rules
exclude-patterns.txt # resolved exclude patterns
integrity/ # SHA256 checksums and rclone verification results
components/
files/rootfs/ # filesystem backup (mirrored directory tree)
brew/ # Brewfile, formula/cask lists, taps
system/ # system facts, app inventory
keychain/ # keychain metadata
launchd/ # launchd plist inventory
```

## πŸ§‘β€πŸ’» Development

```bash
make bootstrap # check dev dependencies (shellcheck, bats-core)
make lint # run shellcheck on all scripts
make test # run full BATS test suite (unit + integration)
make check # lint + test
```

## πŸ“„ License

[MIT](LICENSE). [Gaston Morixe](https://gastonmorixe.com/) 2026