Skip to main content
Type: rvn-cloudfront · Latest version: 0.3.1

Dependencies and consumers

Every dependency input can be specified manually to reference existing external infrastructure rather than a Ravion module.

Readme

CloudFront distribution that serves web applications and private S3 buckets from ECS services, load balancers, S3 origins, and other custom origins.

Overview

The CloudFront module puts the AWS CloudFront edge network in front of a dynamic web application or private S3 bucket. Point it at an existing ECS web service, an ECS cluster load balancer, an S3 bucket, or any custom domain, and Ravion provisions the distribution, origin configuration, cache behaviors, optional access logging bucket, and metrics. The default configuration is safe for dynamic apps: responses are cached at the edge only when your app returns Cache-Control headers, and the full viewer request, including the Host header, cookies, and query strings, is forwarded to the origin. You get TLS termination close to users, HTTP/2 and HTTP/3, connection reuse to the origin, optional WAF, and per-path caching for static assets. Terraform source: flightcontrolhq/modules/cdn/cloudfront

Use cases

How the ECS connection works

An ECS cluster load balancer routes requests to services using listener rules that match the request’s host and path. CloudFront preserves that behavior: the default origin request policy (AWS managed AllViewer) forwards the viewer’s Host header to the load balancer, so the same listener rules keep routing each request to the right service. That means the origin is really the load balancer, not an individual service: Both ECS options resolve to the same ALB when the service runs on that cluster, so pick whichever is easier to select. One distribution can front all services behind the load balancer.

Domain aliases and host routing

If your services route by Domain host rules, the forwarded Host header must match those rules:
  • Add each domain to Domain aliases (for example app.example.com and api.example.com).
  • Point the domains’ DNS at the CloudFront distribution domain.
  • Keep the same domains in the ECS services’ Domain host rules.
Without aliases, CloudFront forwards its default cloudfront.net domain as the Host header. That only works when services route by path rules (or a /* rule), not by host. Cache behaviors are path-based only. If different domains need different edge settings, such as caching, WAF, or geo restrictions, create one CloudFront module instance per domain group. All of them can share the same load balancer origin.

TLS between CloudFront and the origin

Origin protocol policy defaults to HTTPS only. For that to work, the load balancer must have an HTTPS listener with a certificate that is valid for the forwarded Host domain, which is the same certificate the ALB already needs to serve those domains directly. Use HTTP only when the load balancer has no HTTPS listener; traffic from CloudFront to the origin is then unencrypted.

Private S3 origins

S3 origins use CloudFront Origin Access Control so the bucket can stay private. Use the None origin request policy unless you intentionally need CORS headers, because forwarding the viewer Host header to S3 can break OAC-signed origin requests. The bucket policy must allow CloudFront to read objects, scoped to this distribution ARN. For rvn-s3 buckets, apply the CloudFront stack first, then edit the S3 bucket and add the CloudFront OAC read policy template with the CloudFront distribution ARN.

Signed URLs

Enable Require signed URLs to set trusted key groups on the default cache behavior. Each custom cache behavior can also require signed URLs for only that path and must provide its own trusted key group IDs. Ravion does not create key groups in this module; provide existing CloudFront key group IDs and keep the private signing key in your application.

Edge redirects

Redirect rules run at viewer request time before CloudFront checks its cache or contacts an origin. Rules are evaluated in order and the first match wins. Sources and destinations accept absolute HTTPS URLs or host-agnostic paths. Use :name to capture one path segment and a final :name* to capture the remaining path, then place those named values anywhere in the destination. Query preservation is optional and disabled by default. The managed redirect function is attached to the default cache behavior and every custom cache behavior so redirects cover every request path. CloudFront allows only one viewer-request edge association per behavior, so redirect rules cannot be combined with a viewer-request CloudFront Function or Lambda@Edge association supplied through Advanced Terraform variables. The module prevents a rule from redirecting back into its own source pattern. It cannot detect cycles spanning multiple independently matching rules, so review rule ordering and destinations when defining bidirectional or multi-domain redirects.

Avoid overlapping same-host rules

Before returning a redirect, the edge function checks whether the destination would match the same source pattern on the same host. If it would, the function skips that rule and evaluates the next rule. If no later rule matches, CloudFront sends the original request to the configured origin. This prevents an infinite loop, but it can make an overlapping rule appear inactive. For example, a source of https://example.cloudfront.net/:path* and destination of https://example.cloudfront.net/docs/:path* does not redirect. The destination /docs/guide still matches the broad source and would otherwise become /docs/docs/guide on the next request. Use different hosts for a domain migration, such as https://docs.example.com/:path* to https://www.example.com/docs/:path*. For same-host testing, use non-overlapping namespaces such as https://example.cloudfront.net/old/:path* to https://example.cloudfront.net/docs/:path*. To redirect only the root, use the exact source https://example.cloudfront.net without a path parameter. Redirect patterns do not currently support exclusions such as “all paths except /docs”.

Certificates

Domain aliases require a certificate issued in us-east-1, because CloudFront is a global service. Select an ACM Certificate module instance in the ACM certificate field; its certificate ARN is mapped automatically. Request the certificate with the primary domain and any additional aliases as subject alternative names. This certificate is for viewers connecting to CloudFront. The load balancer keeps its own regional certificate for the origin leg.

Caching

The default cache behavior applies to all requests that do not match a custom cache behavior path: With the default cache policy, nothing is cached until the app opts in by returning Cache-Control headers such as public, max-age=300. Responses without caching headers always go to the origin. Choose CachingDisabled to turn off edge caching entirely, or CachingOptimized to cache aggressively regardless of origin headers. Pick Custom policy ID to use a cache or origin request policy you created in your own account. Response headers policy is optional and adds headers such as the SecurityHeadersPolicy set or CORS headers to every response. To cache static content, add Custom cache behaviors. A typical setup adds /assets/* or /static/* with the CachingOptimized policy and GET, HEAD methods. Each behavior can also target an additional origin for path-based traffic splitting. Per-behavior policies use the managed policy lists; for a custom per-path policy, override ordered_cache_behaviors in Advanced Terraform variables. CloudFront accepts only three allowed-method combinations per behavior: GET,HEAD; GET,HEAD,OPTIONS; or all seven methods.

Distribution settings

Monitoring

The dashboard always shows the default CloudFront distribution metrics: requests, total error rate, 4xx error rate, 5xx error rate, bytes downloaded, and bytes uploaded. CloudFront publishes these default metrics to CloudWatch at no additional CloudWatch metric cost. You can also enable all additional metrics charts for cache hit rate, origin latency, and per-status error rates. AWS enables all 8 additional metrics together and CloudWatch charges a flat per-metric monthly rate, about 2.40permonthperdistributionatthestandard2.40 per month per distribution at the standard 0.30 per metric rate. This cost does not change with request volume.

Access logging

CloudFront access logging is on by default, delivered to CloudWatch Logs and viewable in Ravion. Choose where logs are delivered: Logging retention days defaults to 90 and controls the CloudWatch log group retention or the S3 bucket lifecycle expiry, depending on the destination. CloudWatch retention must be one of the standard CloudWatch Logs retention values (1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, and larger).

Configuration

Design decisions

  • The primary origin is always the load balancer or domain you select, with the fixed origin ID primary. ECS references exist to discover the load balancer DNS name, not to create per-service origins, because listener rules already fan traffic out behind one origin.
  • Caching is disabled by default. A wrong edge cache on dynamic responses is worse than no cache, so caching is an explicit per-path opt-in.
  • The AllViewer origin request policy is the default so Host-based listener rules, cookies, and query strings keep working unchanged behind CloudFront.
  • Redirects use one managed CloudFront Function shared by the module’s distributions and attached to every cache behavior.
  • One module instance manages one distribution. Create additional instances when domains need different edge configuration; they can share the same origin.
  • The certificate is referenced from an ACM Certificate module instance so the us-east-1 requirement is explicit and reusable.

Learn more

Inputs reference

All inputs for rvn-cloudfront version 0.3.1. Use the name shown for each field as the input key in module config.

AWS account & region

aws_account_id
string
required
AWS account.
  • Immutable after creation
aws_region
string
required
Region. CloudFront is global. Access logs go to CloudWatch Logs in us-east-1 by default; this region is used for the optional S3 logging bucket.
  • Default: us-east-1
  • Immutable after creation

Distribution

name
string
required
Name slug. Name prefix for the distribution comment, origin access control, and logging bucket.
  • Default: <<project.given_id>>-<<environment.given_id>>-<<module.given_id>>
  • Immutable after creation
  • Pattern: ^[a-zA-Z][a-zA-Z0-9-]{0,62}$ — 1-63 letters, numbers, or hyphens. Start with a letter.
distribution_aliases
string_array
Domain aliases. Custom domain names like app.example.com. Leave empty to use the default cloudfront.net domain. Aliases must match the domain host rules on the origin load balancer when it routes by host.
  • Default: []
certificate
$ref:rvn-acm-certificate
ACM certificate. Certificate for the domain aliases. Required when aliases are set. CloudFront requires the certificate to be issued in us-east-1.

Origin

origin_source
string
required
Origin source. Choose an existing ECS module, private S3 bucket, or custom origin domain name.
  • Default: ecs_web_service
  • Allowed values: ecs_web_service (ECS web service), ecs_cluster (ECS cluster), s3_bucket (S3 bucket), custom (Custom domain)
ecs_web_service
$ref:rvn-ecs-web
ECS web service. ECS web service whose load balancer becomes the origin. The service must be on rvn-ecs-web 0.8.0 or later so its stack exposes the load balancer DNS name.
  • Shown when: {"origin_source":"ecs_web_service"}
ecs_cluster
$ref:rvn-ecs-cluster
ECS cluster. ECS cluster whose public ALB becomes the origin. Listener rules on the ALB keep routing requests to the right services.
  • Shown when: {"origin_source":"ecs_cluster"}
origin_domain_name
string
required
Origin domain name. Domain name CloudFront connects to for the primary origin.
  • Shown when: {"origin_source":"custom"}
s3_bucket
$ref:rvn-s3
S3 bucket. Private S3 bucket to serve through CloudFront Origin Access Control. After this CloudFront stack applies, add its distribution ARN to the S3 bucket’s CloudFront OAC read policy template.
  • Shown when: {"origin_source":"s3_bucket"}
origin_protocol_policy
string
required
Origin protocol policy. How CloudFront connects to the origin. HTTPS only requires the origin load balancer to serve a certificate valid for the forwarded host.
  • Default: https-only
  • Allowed values: https-only (HTTPS only), http-only (HTTP only), match-viewer (Match viewer)
  • Shown when: {"origin_source":["ecs_web_service","ecs_cluster","custom"]}
additional_origins
object_array
Additional origins. Optional extra origins that custom cache behaviors can route paths to. Each origin needs a unique ID.
  • Default: []

Edge redirects

redirect_rules
object_array
Redirect rules. Optional URL-pattern redirects handled by a CloudFront Function at viewer request time.
  • Default: []

Default cache behavior

viewer_protocol_policy
string
required
Viewer protocol policy. How viewers connect to CloudFront.
  • Default: redirect-to-https
  • Allowed values: redirect-to-https (Redirect to HTTPS), https-only (HTTPS only), allow-all (Allow all)
allowed_methods
string
required
Allowed methods. HTTP methods CloudFront forwards to the origin. Use all methods for apps that accept form posts or API writes.
  • Default: all
  • Allowed values: all (All methods), read_options (Read and OPTIONS), read (Read only)
cache_policy
string
required
Cache policy. Controls edge caching for the default behavior. The default respects your app’s Cache-Control headers, so nothing is cached unless the app asks for it.
  • Default: 4cc15a8a-d715-48a4-82b8-cc0b614638fe
  • Allowed values: 4cc15a8a-d715-48a4-82b8-cc0b614638fe (UseOriginCacheControlHeaders-QueryStrings (recommended)), 83da9c7e-98b4-4e11-a168-04f0df8e2c65 (UseOriginCacheControlHeaders), 4135ea2d-6df8-44a3-9df3-4b5a84be39ad (CachingDisabled), 658327ea-f89d-4fab-a63d-7e88639e58f6 (CachingOptimized), custom (Custom policy ID)
cache_policy_custom_id
string
required
Custom cache policy ID. ID of a cache policy from your AWS account.
  • Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ — Invalid CloudFront policy ID. Use the 36-character policy ID, not the name or ARN.
  • Shown when: {"cache_policy":"custom"}
origin_request_policy
string
required
Origin request policy. Controls what CloudFront forwards to the origin. Use None for private S3 origins so CloudFront can sign OAC requests without forwarding the viewer Host header.
  • Default: 216adef6-5c7f-47e4-b989-5492eafa07d3
  • Allowed values: none (None), 216adef6-5c7f-47e4-b989-5492eafa07d3 (AllViewer (recommended)), b689b0a8-53d0-40ab-baf2-68738e2966ac (AllViewerExceptHostHeader), 33f36d7e-f396-46d9-90e0-52428a34d9dc (AllViewerAndCloudFrontHeaders-2022-06), 59781a5b-3903-41f3-afcb-af62929ccde1 (CORS-CustomOrigin), 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf (CORS-S3Origin), custom (Custom policy ID)
origin_request_policy_custom_id
string
required
Custom origin request policy ID. ID of an origin request policy from your AWS account.
  • Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ — Invalid CloudFront policy ID. Use the 36-character policy ID, not the name or ARN.
  • Shown when: {"origin_request_policy":"custom"}
cache_behaviors
object_array
Custom cache behaviors. Optional path-based behaviors evaluated before the default behavior, such as caching /assets/* or routing /api/* to another origin.
  • Default: []

Signed URLs

signed_urls_enabled
boolean
Require signed URLs. Require signed URLs or signed cookies for the default cache behavior. Unsigned requests receive 403 responses from CloudFront.
  • Default: false
trusted_key_group_ids
string_array
required
Trusted key group IDs. Existing CloudFront key group IDs whose public keys are trusted for signed URLs or signed cookies. Add at least one key group before enabling Require signed URLs on the default behavior or any custom cache behavior.
  • Default: []
  • Pattern: ^[A-Z0-9]+$ — Invalid CloudFront key group ID.
  • Shown when: {"signed_urls_enabled":true}
response_headers_policy
string
Response headers policy. Optional headers CloudFront adds to responses, such as security headers or CORS. Leave empty to add none.
  • Allowed values: 67f7725c-6f97-4210-82d7-5512b31e9d03 (SecurityHeadersPolicy), 60669652-455b-4ae9-85a4-c4c02393f86c (SimpleCORS), 5cc3b908-e619-4b99-88e5-2cf7f45965bd (CORS-With-Preflight), e61eb60c-9c35-4d20-a928-2b84e02af89c (CORS-and-SecurityHeadersPolicy), eaab4381-ed33-4a86-88ca-d9558dc6cd63 (CORS-with-preflight-and-SecurityHeadersPolicy), custom (Custom policy ID)
response_headers_policy_custom_id
string
required
Custom response headers policy ID. ID of a response headers policy from your AWS account.
  • Pattern: ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ — Invalid CloudFront policy ID. Use the 36-character policy ID, not the name or ARN.
  • Shown when: {"response_headers_policy":"custom"}

Distribution settings

price_class
string
Price class. You can reduce edge locations for some cost savings if it becomes an issue.
  • Default: PriceClass_All
  • Allowed values: PriceClass_All (All edge locations), PriceClass_200 (Most edge locations), PriceClass_100 (US, Canada, Europe)
http_version
string
HTTP version.
  • Default: http2and3
  • Allowed values: http2and3 (HTTP/2 and HTTP/3), http2 (HTTP/2), http1.1 (HTTP/1.1)
web_acl_id
string
WAF web ACL ARN. Optional WAFv2 web ACL to associate with the distribution. Must be a global (CloudFront) web ACL.
geo_restriction_type
string
Geo restriction.
  • Default: none
  • Allowed values: none (None), whitelist (Whitelist), blacklist (Blacklist)
geo_restriction_locations
string_array
Geo restriction country codes.
  • Default: []
  • Shown when: {"geo_restriction_type":["whitelist","blacklist"]}

Monitoring

additional_metrics_enabled
boolean
Additional metrics. Enable CacheHitRate, OriginLatency, and 401/403/404/502/503/504 error rate charts. Adds a flat CloudWatch cost of about $2.40/month per distribution.
  • Default: false

Access logging

logging_enabled
boolean
CloudFront access logging. Enable CloudFront access logging. Logs are delivered to CloudWatch Logs by default and can be viewed in Ravion.
  • Default: true
logging_destination
string
Logging destination. Where CloudFront delivers access logs.
  • Default: cloudwatch
  • Allowed values: cloudwatch (CloudWatch Logs), s3 (S3 bucket)
  • Shown when: {"logging_enabled":true}
logging_bucket_retention_days
number
Logging retention days. Days to retain CloudFront access logs in CloudWatch Logs or the automatically created S3 logging bucket.
  • Default: 90
  • Min: 1
  • Shown when: {"logging_enabled":true}

Misc

tags
keyvalue
Tags. A map of tags to assign to all resources. Default tags are Owner, ProjectGivenId, EnvironmentGivenId, ModuleGivenId, ModuleId

Terraform settings

opentofu_version
string
OpenTofu version override. Override the environment’s default version for this module
ravion_state_backend_workspace
string
Ravion Terraform workspace name. Override Terraform state backend workspace name. Defaults to project + environment + module given ids.
  • Immutable after creation
advanced_terraform_variables
object
Advanced Terraform variables. Optional raw Terraform variable overrides for advanced module inputs or one-off overrides. Values here override the generated variables above.
  • Default: {}
execution_environment_id
string
Terraform execution environment. Override the execution environment for Terraform runners. Must use the same AWS account as selected above.