How to deploy Docusaurus page using AWS S3 and CloudFront
Learning new technologies goes always better if you have something to test it on. When I wanted to start using AWS I decided to move there my blog (you are currently reading). And these are the steps it takes.
Requirements:
- Docusaurus project
- AWS account
Create S3 bucket
AWS S3 (Simple Storage Service) is an object storage service and we will use it to store static files generated by Docusaurus. Go to AWS console and search S3
:
S3 Bucket, simply explained, is a "disk" where you store your files and it provides mechanisms necessary to control access to them. Click on create bucket button:
Fill the bucket name and pick region that is closest to you:
Leave Object Ownership on predefined option (as recommended):
You don't want anyone to access files on your bucket directly, so you can block all public access:
When your bucket is ready, you can upload there the whole build folder from your Docusaurus project. It should look like this:
Create CloudFront distribution
CloudFront is a web service (CDN) that speeds up distribution of your static and dynamic web content, such as .html
, .css
, .js
, and image files, to your users.
Search cf
in AWS Console:
Then click on create distribution. In origin domain
choose your S3 bucket from the list and set path to /
.
In the Origin access section select Origin access control settings
, create control setting (where you can again use the recommended options) and copy policy, so that you can update S3 bucket afterwards.
You don't want your users to use unsecure http version, therefore change Viewer protocol policy
to Redirect HTTP to HTTPS
.
Last step is to set default root object to index.html
. Without this, CloudFront would return error page.
Now you can create distribution and wait until it is deployed.
Update S3 bucket policy
If you try to visit your CloudFront distribution now, it returns error, because it cannot load anything from the S3 bucket. Public access is forbidden and there is no other policy set to allow the distribution to load objects (files) from it.
You need to go back to S3 service, choose your bucket, go to Permissions
tab and edit Bucket policy
with JSON you copied before. It should look this:
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<your bucket name>/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::<your account ID>:distribution/<distribution ID>"
}
}
}
]
}
CloudFront Functions
The website is now working until you go to some blog post and try to refresh the page. CloudFront always tries to load file from S3 bucket, but you are trying to load something that does not exist (URL is /blog/some-article
). You need to check the URL and return index.html
file if needed (Docusaurus generates index.html file inside each folder, so /blog/some-article/index.html
would work).
Go to CloudFront Functions, create new function RewriteDefaultIndex
, associate it with your distribution and publish it.
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri.endsWith('/')) {
request.uri += 'index.html';
} else if (!uri.includes('.')) {
request.uri += '/index.html';
}
return request;
}
Summary
Your new Docusaurs page should now work perfectly. You can try Free CDN Performance Tool by uptrends, where you can see that users from different places are loading your page from different servers.
Do you like this post? Is it helpful? I am always learning and trying new technologies, processes and approaches. When I struggle with something and finally manage to solve it, I share my experience. If you want to support me, please use button below. If you have any questions or comments, please reach me via email juffalow@juffalow.com.
I am also available as a mentor if you need help with your architecture, engineering team or if you are looking for an experienced person to validate your thoughts.