Skip to content

Cloud backup destinations

Pro Plus. Settings → Pro Plus → Cloud destinations — define where backups should go after the local dump succeeds. Used by scheduled backups and one-off backups from the dialog.

FieldNotes
LabelFree-form (e.g. quay-backups-r2)
ProviderS3 / R2 / GCS
BucketThe bucket / container name
RegionAWS region for S3 ; auto for R2 ; GCS region
EndpointOptional — only needed for R2 (https://<account>.r2.cloudflarestorage.com) or S3-compatible providers (Backblaze B2, MinIO, Wasabi)
Access key + secretThe IAM user’s credentials
Path prefixOptional — quay-backups/<connection>/ style
EncryptionNone / .qenc (recommended for cross-org buckets)

Credentials live in connections.json next to your other secrets, mode 0600. Same locked-decision treatment as DB passwords: plaintext on disk, per-export encryption available via .qenc.

The local backup file (.sql or .qenc), with content-type set appropriately so a browser HEAD reports the right MIME. The remote key is <prefix>/<basename> — same filename as the local dump.

Failures during upload don’t fail the schedule itself — local backup is the source of truth; the cloud upload is a replication step. Failed uploads get logged with the schedule’s last_status (“ok: 84 tables, 12,402 rows (upload failed: 503 Service Unavailable)”). Re-running the schedule replays the upload of the existing local file.

Three options, in increasing security:

  • None — plaintext .sql arrives in the bucket. Fine if the bucket itself is private + behind IAM.
  • .qenc envelope — Quay encrypts before upload; the bucket sees only ciphertext. Even bucket admins can’t read without the passphrase. Recommended for shared / cross-org buckets.
  • Bucket-side encryption (KMS / SSE) — the bucket encrypts at rest with the cloud’s KMS. Combine with .qenc for defence in depth.

Quay doesn’t manage KMS keys; that’s the cloud provider’s domain. Quay’s .qenc is independent of bucket-side encryption — they compose without conflicting.

Minimum permissions per provider:

s3:PutObject on arn:aws:s3:::<bucket>/<prefix>/*
s3:GetObject on arn:aws:s3:::<bucket>/<prefix>/* (for restore)
s3:ListBucket on arn:aws:s3:::<bucket> (for list view)

Cloudflare R2 uses S3-compatible IAM, but tokens are scoped at the bucket level. Create a new R2 token in the Cloudflare dashboard with Object Read & Write for your bucket.

The service account JSON needs storage.objectAdmin on the bucket (or finer-grained storage.objects.create + storage.objects.get

  • storage.objects.list).

Two paths:

  1. In-app: connection → Restore → “From cloud destination” → pick the destination → browse the remote file list → click a file. Quay downloads + opens the restore preview like any local file.
  2. Direct download: most CLI tools (aws s3 cp, rclone, etc.) work against the same bucket — Quay’s uploads aren’t proprietary. Download with whatever, then drag into Quay.
  • Object size — capped by the cloud provider (S3 5 TB single PUT, R2 5 TB multipart, GCS 5 TB). Quay’s uploader handles multipart automatically when needed.
  • No cross-region replication — pick the bucket’s region carefully. Quay doesn’t replicate across regions for you (use the cloud provider’s lifecycle / replication features).
  • No versioning UI — the bucket can have versioning on; Quay doesn’t surface “list previous versions of this object” yet. v0.4.

The default upload pattern (one full backup per scheduled run) isn’t deduplicated — every nightly backup is a full upload. For big DBs this gets expensive; consider:

  • Compression.sql dumps are highly compressible; the v0.4 release adds .sql.gz as an output option (3-5× smaller)
  • Retention policies — set bucket lifecycle rules to expire backups older than N days; Quay never deletes from the bucket
  • Diff-based backups — not yet supported; v0.5 candidate