How to get fog-aws / Gitlab Backups to work with Cloudflare R2

Guidance for Configuring Gitlab Backups with Cloudflare R2.

I run a self-hosted version of Gitlab FOSS and given the data it holds, I obviously want to ensure a robust backup of the platform is taken on a regular basis. Gitlab has a number of in-built backup features that work right out of the box, including the S3 uploads (powered by fog-AWS). Great, nice and simple to setup - provided you don't want to use Cloudflare's R2 AWS compatible service that is!

I leverage Cloudflare R2 to backup almost every other application I host, so my preference was to try and get Gitlab to backup to this too, rather than have to setup and configure AWS or GCP object storage for a sole application. I thus spent hours trying to get Gitlab's backups to work with Cloudflare R2. This took much trial and error to a) disable the host-based path and b) disable v4 streaming as this is not implemented by Cloudflare.

It turns out this is a relatively simple fix, you just need to set 'path_style' to true and 'enable_signature_v4_streaming' to false. Configuring path_style hosts was in fact well documented, including in Gitlab's own documentation, however disabling streaming was less so.

While it may in fact be simple, even with extensive browsing, I couldn't easily find how to disable streaming on fog-aws until I stumbled across this PR for fog. It appears that by default 'enable_signature_v4_streaming' is set to true so it was as simple as swapping this to false and hey presto - everything started working.

For those who aren't sure how to configure this via Gitlab's config for omnibus installations, I've included the full extract of the backup connection below. This should get you going in no time.

gitlab_rails['backup_upload_connection'] = {
  'provider' => 'AWS',
  'region' => 'auto',
  'aws_access_key_id' => '%change_me_access_key%',
  'aws_secret_access_key' => '%change_me_secret-key%',
  'endpoint'              => 'https://%change_me_r2_account%.eu.r2.cloudflarestorage.com',
  'path_style'              => true,
  'enable_signature_v4_streaming'              => false
}
gitlab_rails['backup_upload_remote_directory'] = '%change_me_bucket-name%'