@cryptotaxi247 / infra-1 / commits / 12c180ac

terraform/channels: disable caching for redirects and turn 301s into 302s

More context in: - https://github.com/NixOS/nixos-channel-scripts/issues/42 - https://github.com/NixOS/nixos-homepage/issues/1181 - https://github.com/NixOS/nixos-homepage/issues/1015 - and more linked in the above bugs S3 object-level redirects can only generate 301s, which are cached indefinitely by clients. S3 bucket-level redirects are limited to 50 rules, which is too few for our use case. This leaves the option of using Fastly to doctor the responses from S3. Using VCL, we: - Turn 301s (indefinitely cacheable by clients) into 302s (temporary, usually not cached). - Disable all Fastly-level caching for redirects, since some redirects need to be kept in sync (for example: a .iso and its associated .iso.sha256 should always point to the same version). Redirects should be cheap anyway, and the added latency is not a terrible cost compared to the potential issues of people not being able to checksum their downloads. We could in theory re-enable caching if we modified the channel scripts to do a partial Fastly cache invalidation for the impacted redirects. This is left as an exercise to future readers.

Pierre Bourdon committed Dec 6, 2023 at 14:14 UTC 12c180ac1cda557f5dac620848e51255384f79fb
1 file changed +26
terraform/channels.tf
+26
@@ -212,6 +212,32 @@ resource "fastly_service_vcl" "channels" {
212 type = "recv"
213 }
214
215 + snippet {
216 + content = <<-EOT
217 + # S3 object-level redirects can only be 301s. We use them to point
218 + # "latest" versions of various channel/release artifacts to the correct
219 + # location. First, mark these redirects as temporary. Second, disable
220 + # caching, since some of the artifacts need to have matching versions
221 + # (e.g. a .iso and its checksum), which is near-impossible to guarantee
222 + # with caching unless we explicitly perform invalidations.
223 + #
224 + # Note: we need to match on 301s and 302s here, since Fastly has multiple
225 + # layers, and otherwise a redirect might still get cached at the second
226 + # layer after the first layer turned a 301 into a 302.
227 + if (beresp.status == 301 || beresp.status == 302) {
228 + set beresp.status = 302;
229 + set beresp.ttl = 0s;
230 + set beresp.grace = 0s;
231 + set beresp.cacheable = false;
232 + return (pass);
233 + }
234 + EOT
235 + name = "Change 301 from S3 to 302"
236 + # Keep close to last, since it conditionally returns.
237 + priority = 999
238 + type = "fetch"
239 + }
240 +
241 logging_s3 {
242 name = "${local.channels_domain}-to-s3"
243 bucket_name = local.fastlylogs["bucket_name"]