Share the account's redirect ruleset with the rule already in it
The account already had an http_request_redirect entrypoint, made in the dashboard, sending mykiwi.dev to Bluesky - and there can only be one. It is imported rather than created, with that rule repeated under its own ref so an apply leaves it alone. The token is also granted Bulk URL Redirects.
f521aee parent: a658c96 modified
infra/README.md +3 -2 | @@ -16,8 +16,9 @@ on. | ||
| 16 | 16 | Create a token at https://dash.cloudflare.com/profile/api-tokens (Custom |
| 17 | 17 | Token, scoped to the `mykiwi.blog` zone) with `Zone:DNS:Edit`, |
| 18 | 18 | `Zone:Zone:Read`, `Zone:Dynamic Redirect:Edit`, `Account:Cloudflare Pages:Edit`, |
| 19 | -`Account:Account Filter Lists:Edit`, and `Account:Account Rulesets:Edit` (the | |
| 20 | -last two for the `*.pages.dev` bulk redirects), then: | |
| 19 | +`Account:Account Filter Lists:Edit`, `Account:Account Rulesets:Edit`, and | |
| 20 | +`Account:Bulk URL Redirects:Edit` (the last three for the `*.pages.dev` bulk | |
| 21 | +redirects), then: | |
| 21 | 22 | |
| 22 | 23 | ```sh |
| 23 | 24 | export CLOUDFLARE_API_TOKEN=... |
| @@ -16,8 +16,9 @@ on. | |||
| 16 | Create a token at https://dash.cloudflare.com/profile/api-tokens (Custom | 16 | Create a token at https://dash.cloudflare.com/profile/api-tokens (Custom |
| 17 | Token, scoped to the `mykiwi.blog` zone) with `Zone:DNS:Edit`, | 17 | Token, scoped to the `mykiwi.blog` zone) with `Zone:DNS:Edit`, |
| 18 | `Zone:Zone:Read`, `Zone:Dynamic Redirect:Edit`, `Account:Cloudflare Pages:Edit`, | 18 | `Zone:Zone:Read`, `Zone:Dynamic Redirect:Edit`, `Account:Cloudflare Pages:Edit`, |
| 19 | -`Account:Account Filter Lists:Edit`, and `Account:Account Rulesets:Edit` (the | 19 | +`Account:Account Filter Lists:Edit`, `Account:Account Rulesets:Edit`, and |
| 20 | -last two for the `*.pages.dev` bulk redirects), then: | 20 | +`Account:Bulk URL Redirects:Edit` (the last three for the `*.pages.dev` bulk |
| 21 | +redirects), then: | ||
| 21 | 22 | ||
| 22 | ```sh | 23 | ```sh |
| 23 | export CLOUDFLARE_API_TOKEN=... | 24 | export CLOUDFLARE_API_TOKEN=... |
modified
infra/main.tf +29 -5 | @@ -134,15 +134,39 @@ resource "cloudflare_list" "pages_dev_redirects" { | ||
| 134 | 134 | |
| 135 | 135 | # Bulk Redirects need an account-level entrypoint ruleset in the |
| 136 | 136 | # http_request_redirect phase to actually apply the list. There can only be |
| 137 | -# one per account and phase, so this fails to create if one already exists | |
| 138 | -# (import it instead). | |
| 139 | -resource "cloudflare_ruleset" "pages_dev_redirect" { | |
| 137 | +# one per account and phase, and this account already had one ("default", | |
| 138 | +# made in the dashboard) before this file knew about it, so it was imported | |
| 139 | +# rather than created: | |
| 140 | +# | |
| 141 | +# tofu import cloudflare_ruleset.account_redirects \ | |
| 142 | +# account/<account_id>/<ruleset_id> | |
| 143 | +# | |
| 144 | +# A ruleset resource owns every rule in it, so the rule that was already | |
| 145 | +# there has to be repeated here or the next apply would delete it: it sends | |
| 146 | +# mykiwi.dev to Bluesky, from a "bluesky" list that is not managed here. Its | |
| 147 | +# ref is the one Cloudflare gave it, which is what keeps an apply from | |
| 148 | +# replacing the rule instead of leaving it alone. | |
| 149 | +resource "cloudflare_ruleset" "account_redirects" { | |
| 140 | 150 | account_id = var.cloudflare_account_id |
| 141 | - name = "pages.dev to custom domain redirects" | |
| 142 | - description = "Applies the ${cloudflare_list.pages_dev_redirects.name} list" | |
| 151 | + name = "default" | |
| 152 | + description = "" | |
| 143 | 153 | kind = "root" |
| 144 | 154 | phase = "http_request_redirect" |
| 145 | 155 | |
| 156 | + rules { | |
| 157 | + ref = "de053cde60824fce9cd92ebebd0df0b6" | |
| 158 | + description = "Bluesky" | |
| 159 | + expression = "http.request.full_uri in $bluesky" | |
| 160 | + action = "redirect" | |
| 161 | + | |
| 162 | + action_parameters { | |
| 163 | + from_list { | |
| 164 | + name = "bluesky" | |
| 165 | + key = "http.request.full_uri" | |
| 166 | + } | |
| 167 | + } | |
| 168 | + } | |
| 169 | + | |
| 146 | 170 | rules { |
| 147 | 171 | ref = "pages_dev_redirect" |
| 148 | 172 | description = "Redirect <project>.pages.dev to its custom domain" |
| @@ -134,15 +134,39 @@ resource "cloudflare_list" "pages_dev_redirects" { | |||
| 134 | 134 | ||
| 135 | # Bulk Redirects need an account-level entrypoint ruleset in the | 135 | # Bulk Redirects need an account-level entrypoint ruleset in the |
| 136 | # http_request_redirect phase to actually apply the list. There can only be | 136 | # http_request_redirect phase to actually apply the list. There can only be |
| 137 | -# one per account and phase, so this fails to create if one already exists | 137 | +# one per account and phase, and this account already had one ("default", |
| 138 | -# (import it instead). | 138 | +# made in the dashboard) before this file knew about it, so it was imported |
| 139 | -resource "cloudflare_ruleset" "pages_dev_redirect" { | 139 | +# rather than created: |
| 140 | +# | ||
| 141 | +# tofu import cloudflare_ruleset.account_redirects \ | ||
| 142 | +# account/<account_id>/<ruleset_id> | ||
| 143 | +# | ||
| 144 | +# A ruleset resource owns every rule in it, so the rule that was already | ||
| 145 | +# there has to be repeated here or the next apply would delete it: it sends | ||
| 146 | +# mykiwi.dev to Bluesky, from a "bluesky" list that is not managed here. Its | ||
| 147 | +# ref is the one Cloudflare gave it, which is what keeps an apply from | ||
| 148 | +# replacing the rule instead of leaving it alone. | ||
| 149 | +resource "cloudflare_ruleset" "account_redirects" { | ||
| 140 | account_id = var.cloudflare_account_id | 150 | account_id = var.cloudflare_account_id |
| 141 | - name = "pages.dev to custom domain redirects" | 151 | + name = "default" |
| 142 | - description = "Applies the ${cloudflare_list.pages_dev_redirects.name} list" | 152 | + description = "" |
| 143 | kind = "root" | 153 | kind = "root" |
| 144 | phase = "http_request_redirect" | 154 | phase = "http_request_redirect" |
| 145 | 155 | ||
| 156 | + rules { | ||
| 157 | + ref = "de053cde60824fce9cd92ebebd0df0b6" | ||
| 158 | + description = "Bluesky" | ||
| 159 | + expression = "http.request.full_uri in $bluesky" | ||
| 160 | + action = "redirect" | ||
| 161 | + | ||
| 162 | + action_parameters { | ||
| 163 | + from_list { | ||
| 164 | + name = "bluesky" | ||
| 165 | + key = "http.request.full_uri" | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | + } | ||
| 169 | + | ||
| 146 | rules { | 170 | rules { |
| 147 | ref = "pages_dev_redirect" | 171 | ref = "pages_dev_redirect" |
| 148 | description = "Redirect <project>.pages.dev to its custom domain" | 172 | description = "Redirect <project>.pages.dev to its custom domain" |