r2.tf
1 resource "cloudflare_r2_bucket" "cache" { 2 account_id = local.account_id 3 name = "cache" 4 location = "APAC" 5 } 6 7 resource "cloudflare_r2_bucket" "backup" { 8 account_id = local.account_id 9 name = "backup" 10 location = "APAC" 11 } 12 13 # Lifecycle for backup bucket - delete old versions after 90 days 14 resource "cloudflare_r2_bucket_lifecycle" "backup" { 15 account_id = local.account_id 16 bucket_name = cloudflare_r2_bucket.backup.name 17 rules = [ 18 { 19 id = "abort-incomplete-multipart-uploads" 20 enabled = true 21 conditions = { 22 prefix = "" 23 } 24 abort_multipart_uploads_transition = { 25 condition = { 26 max_age = 86400 # 1 day 27 type = "Age" 28 } 29 } 30 } 31 ] 32 } 33 34 # Abort incomplete multipart uploads after 1 day (minimum) 35 resource "cloudflare_r2_bucket_lifecycle" "cache" { 36 account_id = local.account_id 37 bucket_name = cloudflare_r2_bucket.cache.name 38 rules = [{ 39 id = "abort-incomplete-multipart-uploads" 40 enabled = true 41 conditions = { 42 prefix = "" 43 } 44 abort_multipart_uploads_transition = { 45 condition = { 46 max_age = 21600 # 1 day in seconds 47 type = "Age" 48 } 49 } 50 }] 51 } 52 53 # Public access via custom domain 54 # Note: R2 API token (S3 credentials) must be created manually in Dashboard 55 resource "cloudflare_r2_custom_domain" "cache" { 56 account_id = local.account_id 57 bucket_name = cloudflare_r2_bucket.cache.name 58 domain = "cache.mulatta.io" 59 zone_id = local.zone_id 60 enabled = true 61 } 62 63 # Rewrite / to /index.html for R2 custom domain 64 resource "cloudflare_ruleset" "cache_index_rewrite" { 65 zone_id = local.zone_id 66 name = "Cache index.html rewrite" 67 kind = "zone" 68 phase = "http_request_transform" 69 70 rules = [{ 71 action = "rewrite" 72 action_parameters = { 73 uri = { 74 path = { 75 value = "/index.html" 76 } 77 } 78 } 79 expression = "(http.host eq \"cache.mulatta.io\" and http.request.uri.path eq \"/\")" 80 description = "Serve index.html at root for cache.mulatta.io" 81 enabled = true 82 }] 83 }