Cloudflare R2 — Plan
Complexity: Low-Medium Integration: Cloudflare R2 (S3-compatible) for ActiveStorage file uploads in production
External Setup
- Log into Cloudflare Dashboard: https://dash.cloudflare.com
- R2 Object Storage → Activate (free tier: 10GB storage, 10M reads/mo)
- Create bucket: name
your-app-production - Note Account ID (32-char hex, visible in dashboard URL)
- Create R2 API Token: R2 → Manage R2 API Tokens → Create → "Object Read & Write" → note Access Key ID + Secret Access Key
- Set up public custom domain:
- R2 → bucket → Settings → Public Access → Custom Domain
- Add
cdn.yourdomain.com - Domain must be on Cloudflare DNS — add CNAME record
- Enable public access
- (Optional) Set CORS policy: R2 → Bucket → Settings → CORS → allow your app's origin
- (Optional) Set Cache Rule: Caching → Cache Rules → aggressive caching for
cdn.yourdomain.com/*
Code Changes
- Add to
Gemfile:gem "aws-sdk-s3", require: false bundle install- Add credentials via
bin/rails credentials:edit:cloudflare: r2_account_id: "your-cloudflare-account-id" r2_access_key_id: "your-r2-access-key-id" r2_secret_access_key: "your-r2-secret-access-key" r2_bucket: "your-bucket-name" - Add to
config/storage.yml:cloudflare: service: S3 access_key_id: <%= Rails.application.credentials.dig(:cloudflare, :r2_access_key_id) %> secret_access_key: <%= Rails.application.credentials.dig(:cloudflare, :r2_secret_access_key) %> region: auto bucket: <%= Rails.application.credentials.dig(:cloudflare, :r2_bucket) %> endpoint: https://<%= Rails.application.credentials.dig(:cloudflare, :r2_account_id) %>.r2.cloudflarestorage.com force_path_style: true public: true - Update
config/environments/production.rb:config.active_storage.service = :cloudflare - Update CSP in
config/initializers/content_security_policy.rb: addcdn.yourdomain.comtoimg_src - Dev stays on
:local— no changes needed
Verification
- Upload avatar/project logo in production → appears in R2 bucket (Cloudflare dashboard)
- Images load from
cdn.yourdomain.comin browser - Image variants (thumbnails) generate correctly