Tools
Tools: Create AWS CloudFront on Pay-as-You-Go (not the Free Plan)
2026-02-22
0 views
admin
When the console only offers Free or Pro ## What you need ## Step 1: Get the existing distribution config ## Step 2: Set a unique CallerReference ## Step 3: Adjust aliases and origins (optional) ## Step 4: Create the new distribution ## Quick reference: full script ## Pay-as-you-go vs flat-rate (recap) ## Useful links The AWS Free plan is not working for me and
Pay-as-you-go is hidden for new CloudFront Distributions on AWS Console . When you host Hugo-based sites on AWS, you typically put the bucket behind CloudFront and attach a Lambda@Edge function so that requests to directory paths (e.g. /blog/) are rewritten to /blog/index.html for S3 website-style origins. You can then use hugo deploy or deploy with the AWS CLI to sync the built site. The catch: you need a CloudFront distribution that uses that Lambda and, if you want to avoid flat-rate plan commitments, pay-as-you-go pricing. The console no longer lets you choose that-only Free or Pro plans. This post shows how to create a pay-as-you-go distribution by reusing an existing distribution’s config via the AWS CLI and the scripts in this article’s scripts folder. Amazon introduced CloudFront flat-rate pricing plans (Free, Pro, Business, Premium) that bundle the CDN with WAF, DDoS protection, Route 53, and other services for a fixed monthly price with no overages. In the CloudFront console, when you create a new distribution, you now see only Free or Pro (and higher) plan options. The Pro plan starts at $15/month; there is no visible “pay-as-you-go” option there. Pay-as-you-go is still the default when you create a distribution through the CloudFront API or AWS CLI (create-distribution). So if you already have a distribution created earlier (or via CLI) and want another one with the same behaviour—e.g. S3 website origin plus Lambda@Edge for index.html—you can export that distribution’s config, adjust it, and create a new distribution. The new one will be pay-as-you-go unless you attach it to a flat-rate plan later. Example scripts used below live in this post’s scripts folder: current-distribution-config.json, new-distribution-config.json, updated-distribution-config.json, and final-distribution-config.json. Get the full distribution config (including ETag) and save it: get-distribution-config returns a wrapper object with ETag and DistributionConfig. For creating a new distribution you only pass the inner DistributionConfig, so we extract it: At this point new-distribution-config.json looks like the following (abbreviated).
It includes CallerReference, Aliases, Origins, DefaultRootObject, and DefaultCacheBehavior with Lambda@Edge.
For the example site domain I out micro.com: Every distribution must have a unique CallerReference. Reusing the same value as another distribution causes the API to reject the request. Use a new string or a timestamp: If the new site uses a different domain or S3 bucket, update Aliases and Origins in updated-distribution-config.json to match (e.g. new bucket website endpoint and alias list). If you want a distribution without a custom domain for now, clear aliases: If you need to point to a different S3 website endpoint, edit the Origins section in the same file (e.g. change Id and DomainName to the new bucket’s website hostname, and set DefaultCacheBehavior.TargetOriginId to that same Id). Create the distribution from the final config: The response includes the new distribution’s Id, ARN, DomainName, and Status. The new distribution uses pay-as-you-go pricing by default. You can then point your DNS (or Route 53) to the new CloudFront domain and, if you use it for Hugo, deploy with Hugo deploy or AWS CLI as usual. Pasted together (using an existing distribution ID and clearing aliases), the flow is: If your traffic fits within the pay-as-you-go free tier and you don’t need the bundled flat-rate features, creating distributions via the CLI as above keeps you on pay-as-you-go while the console only shows Free/Pro. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse COMMAND_BLOCK:
# Replace ABCDEFG with your existing distribution ID
aws cloudfront get-distribution-config --id ABCDEFG > current-distribution-config.json Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
# Replace ABCDEFG with your existing distribution ID
aws cloudfront get-distribution-config --id ABCDEFG > current-distribution-config.json COMMAND_BLOCK:
# Replace ABCDEFG with your existing distribution ID
aws cloudfront get-distribution-config --id ABCDEFG > current-distribution-config.json COMMAND_BLOCK:
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json COMMAND_BLOCK:
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json CODE_BLOCK:
{ "CallerReference": "8b2b19eb-6d41-4fc0-8d04-a1313e23e2d7", "Aliases": { "Quantity": 1, "Items": ["micro.com"] }, "DefaultRootObject": "index.html", "Origins": { "Quantity": 1, "Items": [ { "Id": "micro.com.s3.us-west-2.amazonaws.com", "DomainName": "micro.com.s3-website-us-west-2.amazonaws.com", "OriginPath": "", "CustomOriginConfig": { "HTTPPort": 80, "HTTPSPort": 443, "OriginProtocolPolicy": "http-only" } } ] }, "DefaultCacheBehavior": { "TargetOriginId": "micro.com.s3.us-west-2.amazonaws.com", "ViewerProtocolPolicy": "redirect-to-https", "LambdaFunctionAssociations": { "Quantity": 1, "Items": [ { "LambdaFunctionARN": "arn:aws:lambda:us-east-1:...your-lambda-arn", "EventType": "origin-request", "IncludeBody": false } ] } }
} Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
{ "CallerReference": "8b2b19eb-6d41-4fc0-8d04-a1313e23e2d7", "Aliases": { "Quantity": 1, "Items": ["micro.com"] }, "DefaultRootObject": "index.html", "Origins": { "Quantity": 1, "Items": [ { "Id": "micro.com.s3.us-west-2.amazonaws.com", "DomainName": "micro.com.s3-website-us-west-2.amazonaws.com", "OriginPath": "", "CustomOriginConfig": { "HTTPPort": 80, "HTTPSPort": 443, "OriginProtocolPolicy": "http-only" } } ] }, "DefaultCacheBehavior": { "TargetOriginId": "micro.com.s3.us-west-2.amazonaws.com", "ViewerProtocolPolicy": "redirect-to-https", "LambdaFunctionAssociations": { "Quantity": 1, "Items": [ { "LambdaFunctionARN": "arn:aws:lambda:us-east-1:...your-lambda-arn", "EventType": "origin-request", "IncludeBody": false } ] } }
} CODE_BLOCK:
{ "CallerReference": "8b2b19eb-6d41-4fc0-8d04-a1313e23e2d7", "Aliases": { "Quantity": 1, "Items": ["micro.com"] }, "DefaultRootObject": "index.html", "Origins": { "Quantity": 1, "Items": [ { "Id": "micro.com.s3.us-west-2.amazonaws.com", "DomainName": "micro.com.s3-website-us-west-2.amazonaws.com", "OriginPath": "", "CustomOriginConfig": { "HTTPPort": 80, "HTTPSPort": 443, "OriginProtocolPolicy": "http-only" } } ] }, "DefaultCacheBehavior": { "TargetOriginId": "micro.com.s3.us-west-2.amazonaws.com", "ViewerProtocolPolicy": "redirect-to-https", "LambdaFunctionAssociations": { "Quantity": 1, "Items": [ { "LambdaFunctionARN": "arn:aws:lambda:us-east-1:...your-lambda-arn", "EventType": "origin-request", "IncludeBody": false } ] } }
} COMMAND_BLOCK:
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json COMMAND_BLOCK:
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json COMMAND_BLOCK:
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json COMMAND_BLOCK:
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json CODE_BLOCK:
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json CODE_BLOCK:
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json COMMAND_BLOCK:
# 1) Export and extract DistributionConfig
aws cloudfront get-distribution-config --id EABCDEFGZ > current-distribution-config.json
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json # 2) Unique CallerReference
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json # 3) Optional: no custom domain
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json # 4) Create (pay-as-you-go) distribution
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
# 1) Export and extract DistributionConfig
aws cloudfront get-distribution-config --id EABCDEFGZ > current-distribution-config.json
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json # 2) Unique CallerReference
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json # 3) Optional: no custom domain
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json # 4) Create (pay-as-you-go) distribution
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json COMMAND_BLOCK:
# 1) Export and extract DistributionConfig
aws cloudfront get-distribution-config --id EABCDEFGZ > current-distribution-config.json
jq '.DistributionConfig' < current-distribution-config.json > new-distribution-config.json # 2) Unique CallerReference
NEW_CALLER_REF="new-distr-$(date +%s)"
jq --arg ref "$NEW_CALLER_REF" '.CallerReference = $ref' new-distribution-config.json > updated-distribution-config.json # 3) Optional: no custom domain
jq '.Aliases = {"Quantity": 0, "Items": []}' updated-distribution-config.json > final-distribution-config.json # 4) Create (pay-as-you-go) distribution
aws cloudfront create-distribution --distribution-config file://final-distribution-config.json - An existing CloudFront distribution whose config you can copy (e.g. one used for another Hugo site, or one created before the console change).
- AWS CLI installed and configured with credentials that can run cloudfront:GetDistributionConfig and cloudfront:CreateDistribution.
- jq (or similar) to edit the JSON config. - Pay-as-you-go: You pay for data transfer out and requests; CloudFront’s perpetual free tier includes 1 TB data transfer and 10M HTTP/HTTPS requests per month. No monthly plan fee.
- Flat-rate plans: Documented here. Free plan has lower allowances (e.g. 1M requests, 100 GB); Pro starts at $15/month with more capacity and bundled WAF, Route 53, etc. No overages. - Deploy Hugo-generated website to AWS S3
- Deploy Hugo Site to AWS S3 with AWS CLI
- Amazon CloudFront pay-as-you-go pricing
- CloudFront flat-rate pricing plans (Developer Guide)
- Introducing flat-rate pricing plans with no overages (AWS Blog)
- create-distribution (AWS CLI)
- get-distribution-config (AWS CLI)
how-totutorialguidedev.toaimldns