supabase-r2-backup creates a logical backup of selected schemas in a hosted
Supabase Postgres database, packages the dumps with a manifest and checksums,
uploads them to a private Cloudflare R2 bucket, then downloads the objects
again to verify their content.
This is a selected-schema PostgreSQL logical backup. It is not a complete Supabase project backup.
It was created for Supabase Free Plan projects: automatic database backups are not included, and Supabase recommends regular off-site exports.
It is designed for unattended Linux servers. Credentials stay in owner-only files, PostgreSQL runs in a reviewed Docker image, and systemd template units let one host back up more than one Supabase project.
The default configuration includes:
- schema definitions and access privileges from
public; - table data from
public,auth, andstorage; - a manifest recording the exact scope, shared-snapshot consistency, file sizes, hashes, client image identity, and source project ref.
It intentionally does not include:
- database roles or role passwords;
- files stored through the Supabase Storage API;
- client-side encryption or signing of the backup archive;
- Cloudflare R2 lifecycle configuration.
The schema and data lists are configurable. The default split avoids restoring
Supabase-managed auth and storage schema definitions over a fresh project.
See configuration and security before the first run.
- A Linux host with Bash, systemd, Docker, OpenSSL,
flock,tar,sha256sum, and rclone 1.59 or newer. - A hosted Supabase Postgres connection and a database role that can read every configured schema.
- A private Cloudflare R2 bucket and bucket-scoped Object Read & Write credentials.
- A reviewed PostgreSQL client image whose major version is compatible with the Supabase database.
- Python 3 on workstations that run the archive verification helper.
Choose a local instance name that contains only letters, digits, dots, underscores, or hyphens:
git clone https://github.com/scarletkc/supabase-r2-backup.git
cd supabase-r2-backup
sudo bash scripts/install-systemd.sh --instance my-projectThe installer creates:
/etc/supabase-r2-backup/my-project.env.example
/etc/supabase-r2-backup/secrets/my-project/
Follow configuration and security to create the actual environment file, database password file, R2 credential files, and trusted Supabase root certificate.
Validate local configuration without connecting to Supabase or R2:
sudo /usr/local/libexec/supabase-r2-backup/supabase-r2-backup.sh \
--env-file /etc/supabase-r2-backup/my-project.env \
--checkRun and inspect the first real backup:
sudo systemctl start supabase-r2-backup@my-project.service
sudo systemctl status supabase-r2-backup@my-project.service --no-pager
sudo journalctl -u supabase-r2-backup@my-project.service -n 100 --no-pager
sudo cat /var/lib/supabase-r2-backup-my-project/last-successConfirm the exact archive and checksum in R2, then enable the default daily timer:
sudo systemctl enable --now supabase-r2-backup@my-project.timer
systemctl list-timers supabase-r2-backup@my-project.timer --allThe shipped timer runs at 03:30 UTC with a randomized delay of up to 10 minutes. Per-instance schedule overrides are documented in configuration and security.
Stop the timer and any running backup, then remove the instance's local configuration, installed credential directory, standard state and runtime directories, and systemd overrides:
sudo bash scripts/uninstall-systemd.sh --instance my-projectShared program and systemd template files are removed automatically when no other installed instance remains. The command does not delete existing R2 backups or revoke the Supabase database login or Cloudflare R2 token. Revoke those credentials separately when retiring an instance. System journal entries and the shared Docker image cache are left intact. If credential, work, or runtime paths were customized outside the installed paths, review and remove those locations separately.
A successful upload is not proof that an application can be restored. Download an exact archive and checksum, then run:
bash bin/verify-backup.sh /path/to/NAME-YYYYMMDDTHHMMSSZ.tar.gzThe helper verifies safe archive paths, the external and manifest hashes, the recorded PostgreSQL repository digest or image ID, and both dump catalogs. It does not connect to or restore a database. Rehearse restoration into a disposable Supabase project after verification.
See recovery checks. Supabase also maintains the official backup and restore guide.
The test suite uses fake Docker, PostgreSQL, OpenSSL, and R2 commands. It does not connect to external services:
bash scripts/test.shShellCheck runs automatically when it is installed.
MIT