Berth

Backups and moving to a new Mac

Database backups happen every night on their own (Postgres, SQLite). For everything else there's one archive:

berth backup                         # → ~/berth-backup-<time>.tar.gz
berth backup /Volumes/USB/berth.tar.gz

It holds everything needed to rebuild: app settings and config, release history, fresh database backups and your storage folders. It leaves out anything that can be fetched or rebuilt again (git mirrors, images, logs). It has your secrets in it, so keep it somewhere safe.

To restore it, on the same Mac or a new one:

berth init --domain example.com      # on a Mac with no apps yet
berth restore berth-backup.tar.gz

Everything comes back: each app's settings, config, domains, access rules, workers and AI access; sign-in groups and sessions; Postgres, Redis and SQLite from their backups; storage folders; and the GitHub, Cloudflare and Google logins. Every app is redeployed from its repo at the commit that was live. A few things come back lazily: apps without a repo come back with their settings (push to them to deploy), dev versions on their next dev:push, previews with their pull requests, and local AI models with berth ai:setup. LAN addresses change to the new Mac's name.

Off-Mac backups

That archive lives on the Mac, which doesn't help much if the Mac dies or walks off. So send one somewhere else every night:

berth offsite:setup --r2 <cloudflare account id> --bucket my-berth-backups

After the 03:00 dumps, Berth makes the same archive as berth backup, encrypts it on the Mac, uploads it, checks it arrived intact, and keeps the newest 14 (--keep changes that). Any S3-compatible storage works. For Cloudflare R2, create a bucket and an R2 API token with Object Read & Write on it. For anything else (Backblaze B2, AWS S3, MinIO), pass --endpoint. Setup asks for the secret key without echoing it, and tries writing, reading, listing and deleting a test file before it saves anything.

Setup then prints a recovery code (berthrestore_…). It's the bucket's address and credentials plus the key that encrypts the backups, all in one string. Save it somewhere that isn't the Mac. A password manager is perfect. The storage provider only ever sees ciphertext, and without the code nobody can read the backups, including you. berth offsite:key prints it again; it changes if you rerun setup with new credentials.

berth offsite:status                 # where they go, the last upload, what's in the bucket
berth offsite:run                    # upload one now
berth offsite:get                    # download and decrypt the latest, ready for berth restore
berth offsite:off                    # stop (the bucket keeps its backups)

berth status warns if no upload has worked for two days, and a failed upload sends a notification.

Moving to a new Mac

With off-Mac backups, moving is one command on the new Mac, once Homebrew and Berth are installed:

berth init --restore                 # asks for the recovery code

It fetches the newest backup and puts the old Mac's settings and logins in place. That means no --domain, and no Cloudflare or GitHub logins in the browser, since it reuses the same tunnel and token. Then it finishes setting up and restores every database and app as above.

Turn Berth off on the old Mac first (berth uninstall). Otherwise both Macs share the tunnel and split your traffic between them, which is confusing.

Uninstalling

berth uninstall              # stop everything and remove the background services; keeps ~/.berth
berth uninstall --purge      # also delete every app, webhook, database volume, image and ~/.berth

Edit this page on GitHub (it's a section of the README)