diff --git a/README.md b/README.md index c0b0a37..167dc93 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,14 @@ Install desktop apps like Moonlight or VLC, and set each Android app's resolutio **⚡ One-click tools**
SSH, SFTP, Steam Link, remote desktop, volume, sleep, restart and shut down. + + + + + +**💾 Backup and recovery**
+Copy game saves, settings and Android app data to your computer, and restore them after a factory reset. Sign-in files and keys are never copied. A Return to Game Mode button helps when the headset is stuck in Desktop Mode. Not tested on a headset yet. [How it works](docs/backup-and-recovery.md). + diff --git a/docs/backup-and-recovery.md b/docs/backup-and-recovery.md new file mode 100644 index 0000000..dc7ad26 --- /dev/null +++ b/docs/backup-and-recovery.md @@ -0,0 +1,167 @@ +# Backup and recovery + +**Tools → Backup & recovery** copies what a factory reset would lose from the +Steam Frame to your computer, puts it back afterwards, and gets the headset out +of Desktop Mode. It runs from Frame Control on a computer, not from the iPhone +app or the Frame itself. + +**Partly tested on a headset.** On a Frame running SteamOS 0.5.6 (build +20261015.6141207), a full backup saved 26 parts (40.7 MB): 14 games' Proton +saves, Linux game saves, Steam and desktop settings and 9 Android apps' data, +with no sign-in files or keys in the archives. Restoring one game's saves on top +of identical files wrote nothing and left nothing behind. The session check +reported Game Mode, so **Return to Game Mode** changed nothing. Not tested on a +headset: a restore after a real factory reset, a restore that replaces files, +Android data restore, and the switch out of a real Desktop Mode session. Unit +tests and the fake Frame cover those (see [Verification](#verification)). + +## Back up + +Choose **Game saves**, **Steam and desktop settings** and **Android app data** +(all three by default), then **Back up now**. **See what's included** lists each +part and its size first. Backing up only reads the headset. + +Each backup is a folder named after the time it started: + +``` +~/Documents/Frame Control Backups/2026-10-23-142530/ + manifest.json + saves/saves-1234.tar.gz one per game + saves/saves-linux.tar.gz + settings/settings-steam.tar.gz + settings/settings-system.tar.gz + android/org.example.game.tar.gz one per Android app +``` + +`manifest.json` records the headset's name, SteamOS version and BUILD_ID, every +file with its size and SHA-256, and each archive's SHA-256. It also lists what +was skipped and why. A backup is written under a hidden `.…partial` name and +renamed when complete, so a cut-off backup never shows up as one. + +### What's saved + +| Part | From the headset (`~` is `/home/steamos`) | Restored? | +|---|---|---| +| Windows game saves | `~/.local/share/Steam/steamapps/compatdata//pfx/drive_c/users/steamuser/` → `AppData/Roaming`, `AppData/Local`, `AppData/LocalLow`, `Documents`, `Saved Games`. Wine's own folders in them (`Temp`, `Microsoft`, `D3DSCache`, `CrashDumps`) are left out. Sideloaded Windows games (non-Steam shortcuts) have prefixes here too | Yes | +| Linux game saves | `~/.config/unity3d`, `~/.local/share/godot/app_userdata`: where Unity and Godot games save by default | Yes | +| Steam controller layouts | `userdata//241100/remote/controller_config`, `steamapps/common/Steam Controller Configs//config` | Yes | +| Steam library settings | `userdata//config/localconfig.vdf`, `shortcuts.vdf`, `grid/` (custom artwork) | Kept for reference | +| Desktop settings | `~/.config/kdeglobals`, `kwinrc`, `kxkbrc` (keyboard layout), `konsolerc`, `dolphinrc` | Yes | +| SteamVR settings | `~/.config/openvr/config/steamvr.vrsettings` | Kept for reference | +| Android app data | Each Frame Control Android app's private data, through the existing `backup-data` helper ([sidequest.md](sidequest.md#private-app-data-backups)) | Yes | + +"Kept for reference" files are in the backup but not put back automatically: +Steam and SteamVR rewrite them while they run, and an old `shortcuts.vdf` would +point at apps that aren't installed after a reset. Open the backup folder to +copy one by hand if you need it. + +### What's never copied + +- **Steam sign-in:** `steam.token`, `config/config.vdf`, `loginusers.vdf`, + `registry.vdf` and `ssfn*` files. +- **Keys and passwords:** `~/.ssh`, `~/.gnupg`, keyrings and KWallet, any + `*.token`, `*.key` or `*.pem` file, Tailscale state and proxy settings + (`secrets.env`). These are refused by name wherever they turn up, including + inside a game's folder, and a restore refuses them too. +- Games, Proton and the Steam runtimes: reinstall them from Steam. +- Steam Cloud's own folders (`userdata//`), shader caches and + screenshots (**Tools → Capture & Live** saves those to Pictures). +- Android apps themselves, their OBB files and shared storage (`/sdcard`). +- Symbolic links (never followed), and single files over 2 GiB. + +Backups aren't encrypted. Game folders can still hold a launcher's login, and +Android app data can hold an app's, so keep backups private. + +Android apps that are open are skipped (the helper needs the app closed); close +them and back up again. + +## Restore after a factory reset + +1. Set up the headset again: Developer Mode, **Set Up Connection**, sign in to + Steam with the same account. +2. Reinstall your games, and **start each once** so Proton creates its folders. +3. Reinstall your Android apps from Frame Control. +4. **Tools → Backup & recovery → Restore…** on a backup. Frame Control checks + each part against the headset and says what it would do: how many files it + replaces and how many are new. +5. Tick the parts to restore and **Restore selected**. It asks before replacing + anything. + +Parts that can't go back yet are skipped, not failed, with the reason: + +| Reason | What to do | +|---|---| +| Install the game first | Install it from Steam, then restore | +| Start the game once | Proton hasn't made its folders yet; start the game, quit, restore | +| Sign in to Steam first | Controller layouts go under your account's folder | +| Install the app first / close the app first | Android app data needs the app installed and closed | +| The backup file doesn't match its checksum | The archive changed since it was made | + +A restore writes only the files in the parts you chose, and only inside that +part's folders: it never deletes a file, and a save archive can't write outside +its game. Before replacing a file it copies the current one to +`~/.local/share/frame-control/restore-previous/