[{"data":1,"prerenderedAt":10},["ShallowReactive",2],{"public:public\u002Fcontent\u002Fdocs\u002Fcloud-sql-gcs":3},{"slug":4,"title":5,"description":6,"draft":7,"updated":8,"html":9},"cloud-sql-gcs","Cloud SQL for PostgreSQL","Schedule Cloud SQL for PostgreSQL exports to Cloud Storage and let Verestore test the newest export with a read-only HMAC key.",false,null,"\u003Ch1>Cloud SQL for PostgreSQL: scheduled export to Cloud Storage\u003C\u002Fh1>\n\u003Cblockquote>\n\u003Cp>Verified against the provider&#39;s documentation, not against a live account.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>Cloud SQL&#39;s own backups stay inside Google&#39;s service and are lost with the project. Keep an export in Cloud Storage: a bucket in another project (or with another provider) survives the loss of the instance&#39;s project, and Verestore proves it restores.\u003C\u002Fp>\n\u003Ch2>1. Let the instance write to the bucket\u003C\u002Fh2>\n\u003Cp>Find the instance&#39;s service account and grant it \u003Ccode>roles\u002Fstorage.objectCreator\u003C\u002Fcode> on the bucket. Google&#39;s documentation names \u003Ccode>roles\u002Fstorage.objectAdmin\u003C\u002Fcode> or a custom role with \u003Ccode>storage.objects.create\u003C\u002Fcode>; Object Creator carries exactly that permission, enough for a single-file export (parallel exports also need list and delete):\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-sh\">SA=$(gcloud sql instances describe INSTANCE --format=&#39;value(serviceAccountEmailAddress)&#39;)\ngcloud storage buckets add-iam-policy-binding gs:\u002F\u002Facme-backups \\\n  --member=&quot;serviceAccount:$SA&quot; --role=roles\u002Fstorage.objectCreator\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>If the export fails with a permission error, check the provider&#39;s current documentation for the role it requires.\u003C\u002Fp>\n\u003Ch2>2. Export one database\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-sh\">gcloud sql export sql INSTANCE \\\n  &quot;gs:\u002F\u002Facme-backups\u002Forders\u002Forders-$(date -u +%Y-%m-%dT%H-%M).sql.gz&quot; \\\n  --database=orders --offload\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>This writes plain SQL; the \u003Ccode>.gz\u003C\u002Fcode> suffix makes Cloud SQL compress it. \u003Ccode>--offload\u003C\u002Fcode> uses a serverless export, which avoids load on the primary (check Google&#39;s pricing for it). Verestore detects the format from the content, not the extension.\u003C\u002Fp>\n\u003Cp>The export contains statements that reference Cloud SQL roles such as \u003Ccode>cloudsqlsuperuser\u003C\u002Fcode>. Verestore creates missing roles as \u003Ccode>NOLOGIN\u003C\u002Fcode> in the scratch server and reports them as warnings.\u003C\u002Fp>\n\u003Ch2>3. Schedule the export\u003C\u002Fh2>\n\u003Cp>Keep it simple: a \u003Cstrong>Cloud Scheduler\u003C\u002Fstrong> job that triggers a \u003Cstrong>Cloud Run job\u003C\u002Fstrong> (or a Cloud Function) which calls the Cloud SQL Admin API export, at a time before your Verestore schedule. The request body for \u003Ccode>POST https:\u002F\u002Fsqladmin.googleapis.com\u002Fv1\u002Fprojects\u002FPROJECT\u002Finstances\u002FINSTANCE\u002Fexport\u003C\u002Fcode> is:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;exportContext&quot;: {\n    &quot;fileType&quot;: &quot;SQL&quot;,\n    &quot;uri&quot;: &quot;gs:\u002F\u002Facme-backups\u002Forders\u002Forders-2026-11-05T02-00.sql.gz&quot;,\n    &quot;databases&quot;: [&quot;orders&quot;],\n    &quot;offload&quot;: true\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Generate the date in the file name in your job, so each export is a new object and Verestore picks the newest. Google publishes a guide to scheduling Cloud SQL exports with Cloud Scheduler: check it for the current setup and the roles the calling service account needs.\u003C\u002Fp>\n\u003Ch2>4. Give Verestore read access\u003C\u002Fh2>\n\u003Cp>The read side is the same as for any Cloud Storage bucket: a dedicated \u003Ccode>verestore-reader\u003C\u002Fcode> service account with \u003Ccode>roles\u002Fstorage.objectViewer\u003C\u002Fcode> on the bucket and an HMAC interoperability key. Follow \u003Ca href=\"\u002Fdocs\u002Fgoogle-cloud-storage\">Google Cloud Storage\u003C\u002Fa>, then add the target:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>S3 endpoint: \u003Ccode>https:\u002F\u002Fstorage.googleapis.com\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>Region: \u003Ccode>auto\u003C\u002Fcode> (or leave it empty: it is filled from the endpoint)\u003C\u002Fli>\n\u003Cli>Bucket: \u003Ccode>acme-backups\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>Prefix: \u003Ccode>orders\u002F\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>Access key ID and secret access key: the HMAC access ID and secret\u003C\u002Fli>\n\u003C\u002Ful>\n",1794290783589]