Building your own CDN under 5 minutes
Haroon Khan
Posted on January 20, 2023
Preface
At Ehsaan Technologies, we recently started building a streaming platform and we knew from day one that we are going to need a CDN for that.
I have been using AWS CDK for quite some time now and love the way it makes it easy to deploy infrastructure.
AWS CDK
AWS CDK is infrastructure-as-code (IaC) tool that allows developers to provision and manage AWS resources using familiar programming languages, such as JavaScript, TypeScript, C#, and Python. This makes it easy to automate the deployment of cloud infrastructure and reduce the need for manual configuration. Additionally, the use of programming languages allows for the creation of reusable, modular code that can be easily tested and maintained. This can increase the efficiency and speed of development, as well as reduce the risk of errors.
I promise this article is going to be very small. Just copy-pasta and voila! Your CDN is ready. I am not goint to get into details of scaffolding AWS-CDK project and installing dependecies.
My preferred language is TypeScript.
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import * as cloudfront from "aws-cdk-lib/aws-cloudfront";
import * as origins from "aws-cdk-lib/aws-cloudfront-origins";
import { Construct } from "constructs";
export class StreamKaroApiStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const audioBucket = new s3.Bucket(this, "streamKaro-api-audio-bucket", {
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
bucketName: "streamKaro-api-audio-bucket",
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
const originAccessIdentity = new cloudfront.OriginAccessIdentity(
this,
"streamKaro-api-audio-bucket-oai",
{
comment: "oai for streamKaro-audio-bucket-api",
}
);
const cloudFrontDistribution = new cloudfront.Distribution(
this,
"cloudfront-distribution-streamKaro-api-audio-bucket",
{
comment: "cloudfront distribution for streamKaro-api-audio-bucket",
defaultBehavior: {
origin: new origins.S3Origin(audioBucket, {
originAccessIdentity,
}),
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
viewerProtocolPolicy:
cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
}
);
}
}
Let's break this down:
Creating S3 Bucket:
Here we are creating a S3 bucket. Specifying the name of the bucket, setting up public access etc.
const audioBucket = new s3.Bucket(this, "streamKaro-api-audio-bucket", {
objectOwnership: s3.ObjectOwnership.BUCKET_OWNER_ENFORCED,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS,
bucketName: "streamKaro-api-audio-bucket",
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
Setting up Origin Access Identity (OAI)
Origin Access Identity (OAI) is a AWS CloudFront distribution feature which allows your users to access S3 bucket resources without giving them direct access to S3 bucket.
Here is an example:
Image in your S3 bucket is not accessible via:
https://streamkaro-audio.s3.us-east-1.amazonaws.com/pics/tax.png
But it is accessible via CloudFront distribution:
https://casdk21ASDSCsss.cloudfront.net/pics/tax.png
const originAccessIdentity = new cloudfront.OriginAccessIdentity(
this,
"streamKaro-api-audio-bucket-oai",
{
comment: "oai for streamKaro-audio-bucket-api",
}
);
Setting up CloudFront Distribution:
Notice the defaultBehavior
, where we specifiy orgin
and originAccessIdentity
. We specify our S3 bucket (streamKaro-api-audio-bucket) as our origin
, and pass the originAccessIdentity
(OAI) as an option to origin
which we just created.
You will also notice that we only allow HEAD
, GET
& OPTIONS
HTTP methods. We also specify that viewer should be redirected to https
, in case where user tries to access CDN via http
.
const cloudFrontDistribution = new cloudfront.Distribution(
this,
"cloudfront-distribution-streamKaro-api-audio-bucket",
{
comment: "cloudfront distribution for streamKaro-api-audio-bucket",
defaultBehavior: {
origin: new origins.S3Origin(audioBucket, {
originAccessIdentity,
}),
allowedMethods: cloudfront.AllowedMethods.ALLOW_GET_HEAD_OPTIONS,
viewerProtocolPolicy:
cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
}
);
That's all folks. Thanks for reading.
Cover Photo by Juanita Swart on Unsplash
Posted on January 20, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.