Cloud Backup

Cloud Backup is Solid Accounting's optional, end-to-end encrypted backup for your .solid file. Backups are deduplicated, compressed, and encrypted on your machine before they leave it — the server (ours or yours) only ever sees opaque encrypted blocks.

This page is the deep reference for how it works. If you just want to set it up, the wizard inside the app walks you through it in five screens.

What it does, in one paragraph

A background worker wakes every 15 minutes, decides whether a new backup is due based on a Grandfather/Father/Son retention schedule, and if so: snapshots your .solid file, splits it into content-defined chunks, deduplicates against blocks already in the destination, compresses what's new, encrypts each block under a key only you control, and uploads the new blocks plus a manifest. Every week it samples random backups and verifies them by rehashing a chunk and validating the authentication tag. You can restore any backup in the catalog with one click using your login password — or, if you've lost that, with a 24-word recovery phrase.

How it works

Chunking — content-defined, not size-bounded

The .solid file is split into chunks whose boundaries depend on content, not byte offset, using FastCDC (a content-defined chunking algorithm). Default sizing: 1 MiB minimum, 4 MiB average, 8 MiB maximum.

The win: when you record one new transaction in the middle of a 100 MB file, only the few chunks that actually changed get re-uploaded. Surrounding chunks keep their hashes and the storage backend recognizes them as already present.

Compression — zstd level 3

Each chunk is compressed with zstd at level 3 before encryption. Level 3 is the sweet spot for accounting data: ~5:1 ratio typical and fast enough that it doesn't dominate the backup pipeline. Chunks under 64 KiB skip compression (the overhead isn't worth it for small tail blocks).

A single leading byte on each block records whether the payload is compressed (0x01) or plain (0x00).

Encryption — envelope, AES-256-GCM

Cloud Backup uses envelope encryption:

KeyLifetimePurpose
BEK (Block Encryption Key, 256-bit)One per file, generated at setup, never changesEncrypts every block
KEK (Key Encryption Key, 256-bit)Derived from your login password + per-license saltWraps the BEK in the manifest

The BEK is generated once with OsRng and never leaves the wrapped form on disk. The KEK is derived from your login password using Argon2id (256 MB memory, 3 iterations, 1 parallelism — strong enough to make brute-force impractical even on a stolen manifest). Each chunk is encrypted with AES-256-GCM using the BEK and a fresh 96-bit random nonce per chunk; the GCM authentication tag (16 bytes) is appended.

Because the BEK only exists in memory while the app is running and is wrapped in the manifest at rest, the server never has the key material to decrypt your data. That holds for managed B2, your own S3, or a folder destination.

Recovery phrase — 24 words, BIP39

The BEK is also encoded as a 24-word BIP39 mnemonic (256 bits of entropy). You see this once during the setup wizard and can re-display it any time from settings (with your login password). If you lose your login password, this phrase is what restores the BEK on a new install — without it, encrypted backups are unrecoverable. Store it like you'd store the seed phrase for a hardware wallet: offline, somewhere you trust.

Manifest — the index for one backup

Each backup writes a manifest that lists every chunk in that snapshot (by content hash), records the wrapped BEK + Argon2id parameters, and stores file metadata. Manifests are stored alongside blocks in the destination — small, JSON-serialized, and themselves encrypted at rest. The manifest is what Restore reads first to figure out which blocks to fetch.

What gets backed up

Just your .solid file. That single file contains every transaction, list, report definition, attached document reference, multi-user state, and audit history. Backing it up is sufficient to fully restore your books on any machine running the same major version of Solid Accounting.

Where it goes — three destination types

DestinationWhen to chooseCost
Managed (B2 via Solid)You want the simplest setup. We provision a scoped B2 access key bound to your license.Included with an active Updates plan. 10 GB included.
Bring your own S3You already have an S3-compatible bucket (AWS S3, Backblaze B2, MinIO, Wasabi, R2) and want backups in your own account.Whatever your provider charges.
Bring your own folderA local folder, NAS, mounted external drive, or cloud-sync folder.Free.

The destination type doesn't change the encryption model — your data is encrypted on your machine before it's written, regardless of where it lands.

A note about cloud-sync folders

If you point Cloud Backup at a folder inside Dropbox, iCloud Drive, OneDrive, Google Drive, or Box, the app warns you. Two reasons:

  1. The cloud-sync client may upload partial blocks while a backup is running, leading to corrupt-looking states until the run completes.
  2. You're effectively re-encrypting and re-uploading the same data through two different services — which is fine, just inefficient.

The warning is informational, not blocking. Some users want belt-and-suspenders backup; the wizard lets you proceed.

Schedule — Grandfather/Father/Son

Defaults:

TierDefault keep
Daily7
Weekly4
Monthly12
Yearly5

The background worker wakes every 15 minutes, decides whether a new backup tier is due (a daily after the most recent daily is more than ~24h old, a weekly after the most recent weekly is more than ~7d old, etc.), and runs one backup if so. Old backups outside the retention window are pruned automatically after each run.

You can change the retention numbers from settings, or trigger a manual backup from the Back up now button.

Restoring

The restore flow is a four-step dialog:

  1. Browse manifests — pick the backup you want to restore from. Each manifest shows the date, file size, and a one-line summary.
  2. Preview contents — optionally inspect the entries inside the chosen manifest (path + size per entry) without running the restore. This shows you what's actually in that backup.
  3. Choose target folder — where should the restored .solid file land? Defaults to your Documents folder.
  4. Confirm with password — enter your login password (or recovery phrase, if you've lost the password) to unwrap the BEK. The dialog runs the restore and reports success.

Restore reads the manifest first, fetches only the blocks listed in the manifest (not the entire destination), decrypts and decompresses them in order, and writes the reconstructed file to your chosen target. Network usage scales with the size of the restored file, not the total amount of data in the destination.

Integrity verification

Two layers:

Continuous (cheap, runs weekly). The auto-verify task picks 10 random manifests, fetches one random block from each, rehashes it, and confirms the hash matches what the manifest says. If hashes match, the manifest is presumed clean. If a hash mismatches, an integrity-failure event surfaces in the status bar and the audit log records it.

Deep (slower, on-demand). From settings → Verify integrity, you can run a deep verification that also decrypts each sampled block and validates the AES-GCM authentication tag. This catches corruption that a hash check alone would miss (e.g., a tampered ciphertext where someone tried to swap a block). The deep mode requires your login password (to unwrap the BEK).

The audit log records every verification run with its result. If a backup ever shows integrity errors, the destination is the place to investigate — the encrypted blob has been altered or partially uploaded.

Audit log

Every privileged Cloud Backup action writes to a local audit database ({app_local_data}/backup_audit.db, separate from your .solid file). What gets recorded:

  • Configure / enable / disable
  • Backup runs (success and failure)
  • Restores
  • Manifest deletes
  • Integrity-verification runs
  • Login-password rotations
  • Recovery-phrase displays
  • Garbage collection runs

Each entry has a timestamp, action type, status (success / failure), and a short detail string. Viewable from settings → Activity log.

Login-password rotation

When you change your Solid Accounting login password, Cloud Backup needs to re-wrap the BEK under a new KEK (derived from the new password). This is an O(1) operation — only the manifest's wrapping changes; the encrypted blocks are untouched.

The app prompts you automatically after a successful login-password change: "Rotate backup encryption?" with two buttons. If you skip, your old password is still required to unwrap the BEK on subsequent restores until you do rotate. If you rotate, the old password is permanently retired from the backup envelope.

If you've lost your login password, restoration falls back to the 24-word recovery phrase. Enter the phrase to recover the BEK, set a new login password, and the app re-wraps everything under the new KEK.

Status indicator + reminders

The app status bar shows one of five Cloud Backup states:

  • Not set up (muted, CloudOff icon) — clicking opens the wizard
  • Idle, due soon (warn) — a backup is scheduled within ~24h
  • Active, recent (ok) — last backup successful, within retention window
  • Running (pulse animation) — a backup is in progress now
  • Failed (err, AlertTriangle icon) — last backup or verify-run failed

A reminder banner appears in priority order:

  1. Integrity issue — verify-run found problems (top priority, ~immediate)
  2. Repeated failures — three consecutive backup failures (1-day snooze)
  3. Stale backup — enabled but no successful backup in 7+ days (3-day snooze)
  4. Not set up — no Cloud Backup configured after 30+ days of usage (14-day or 365-day snooze)

Lapse policy

If your Updates plan lapses while Cloud Backup is enabled with the managed destination:

  • The background worker stops creating new backups immediately.
  • Existing backups remain restorable for 1 year from your last paid date.
  • After 1 year, the managed-B2 data is no longer accessible. Plan ahead — pull anything you need before then, or renew.

If your Cloud Backup is configured to your own S3 or your own folder, lapse changes nothing. Backups keep running on whatever schedule you've set; storage and access are entirely on your account.

The local app and .solid file keep working forever regardless of plan state.

Threat model — the honest version

What Cloud Backup defends against:

  • Server compromise of the destination. Data stays encrypted; the BEK never leaves your machine.
  • Eavesdropping in transit. TLS to the destination + envelope encryption.
  • Lost or stolen laptop. The encrypted backup elsewhere is your recovery path.
  • Single-bit corruption. Per-block hashes catch it; per-block AES-GCM tags catch tampering.
  • Subtle drive failure. Weekly auto-verify surfaces problems before you discover them at the worst time.

What it doesn't defend against:

  • Lost login password AND lost recovery phrase. Both are required for at least one of the two unlock paths. If you lose both, encrypted blocks are unrecoverable. There is no backdoor.
  • Compromise of the running app on your machine. A keylogger that captures your login password during a normal session can decrypt backups. Standard endpoint hygiene applies.
  • Sustained outage of a third-party service. If managed B2 is unreachable, restores from managed destinations are paused until it returns. Local app and .solid keep working.

Reference — Tauri commands

For developers integrating with Cloud Backup, the full command surface (21 commands as of this writing):

backup_v2_initialize · backup_v2_configure · backup_v2_enable · backup_v2_disable · backup_v2_status · backup_v2_now · backup_v2_list · backup_v2_get_manifest · backup_v2_restore · backup_v2_delete_manifest · backup_v2_inspect_folder · backup_v2_test_destination · backup_v2_fetch_managed_credentials · backup_v2_show_recovery_phrase · backup_v2_rotate_login_password · backup_v2_audit_log · backup_v2_verify · backup_v2_gc · backup_v2_worker_start · backup_v2_worker_stop · backup_v2_worker_status

These are not part of the public API contract — they're internal app commands and may evolve between major versions.