Automated Backups
Portside backs up any database instance it manages — on a schedule or on demand — to Cloudflare R2, any S3-compatible storage, a local folder, Google Drive, or Dropbox. Restores always create a new instance from a backup, so the source database is never touched.
Destinations
One backup panel supports four destination types:
| Type | What you enter | Good for |
|---|---|---|
| S3-compatible | Endpoint URL, bucket, region, access key, secret key | R2, AWS S3, Backblaze B2, MinIO, Wasabi — anything speaking the S3 API |
| Local folder | A directory path | Zero-setup copies; point it inside a Drive/Dropbox/OneDrive sync folder for cloud copies with no OAuth at all |
| Google Drive | Folder ID + your own OAuth client (client ID, client secret, refresh token) | Backups alongside your Google files |
| Dropbox | App key, app secret, refresh token | Backups alongside your Dropbox files |
Every destination is tested live before it is saved: if the connection check fails, nothing is stored. The same Test button stays available on each saved row.
Why Cloudflare R2 is the default recommendation
R2 includes a 10GB free tier with no egress fees, which comfortably holds gzipped dumps of development databases. In the Portside UI, pick the S3 type, enter your Cloudflare account ID, and hit Use Cloudflare R2 — the endpoint (https://<account-id>.r2.cloudflarestorage.com) fills in automatically with region auto. Create one bucket, generate an API token, paste the keys, and you're done.
Schedules
Each backup job links one instance to one destination with:
- Interval — hourly, daily, or weekly presets.
- Retention — keep the latest N backups; older ones are deleted automatically, oldest first, and only after a successful run.
- Backup now — run any job on demand from its row.
Scheduled runs happen while the Portside app is open (it checks every minute). A job that has never run fires shortly after startup, so the first backup lands without waiting for the interval.
What gets backed up
Dumps run inside the instance's own container — no host tooling needed — and are gzip-compressed before upload:
| Engine | Dump method |
|---|---|
| Postgres | pg_dump per user database (template DBs excluded) |
| MySQL / MariaDB | mysqldump over user databases only — system tables excluded, so a restore can never clobber the target's grant tables |
| Redis / Valkey | Raw RDB via redis-cli --rdb (TLS flags on LAN-shared instances) |
Files are stored as portside/{instance-id}/{engine}-{utc-timestamp}.sql.gz.
Restores and history
The history list for every job shows each run's status, size, and errors. From any good backup you can:
- Download the
.sql.gzfile to any path. - Restore to a new instance — Portside creates a fresh instance (same engine, catalog-default version, next free port) and streams the backup into it. This doubles as a verified-restore drill: you prove the backup works without risking the original.
There is deliberately no in-place overwrite restore. Pair this with the lifecycle contract: wipe the failed experiment, restore the backup as a new instance, keep moving.
flowchart LR
A["Backup job\n(instance → destination)"] --> B["Scheduled tick\nor Backup now"]
B --> C["Dump → gzip → upload\nrun recorded"]
C --> D{"Need it back?"}
D -- "inspect file" --> E["Download .sql.gz"]
D -- "need a live DB" --> F["Restore to NEW instance\nsource untouched"]
Security
- S3 secret keys and Drive/Dropbox refresh tokens live in the OS keychain (Windows Credential Manager, macOS Keychain, Linux Secret Service) — never in Portside's database.
- Connection details (endpoints, buckets, folder IDs) stay in the local SQLite registry alongside instance metadata.
- Error messages are scrubbed of secret material before display.
- Database passwords are passed to dump tools via environment variables inside the container, never on command lines.
Limits in v1
- Backups cover managed instances (created by Portside). Imported external servers are rejected.
- Scheduled runs require the app to be open; there is no headless CLI scheduler yet — scripted flows should use the Headless CLI dumps until one lands.
- Backups are gzipped but not encrypted at rest — for sensitive data, prefer a private bucket or an encrypted local disk.
- Google Drive and Dropbox need a user-created OAuth client (Desktop app type); the UI takes the client ID/secret plus a refresh token.