Hugo on AWS
Hugo on AWS with a WYSIWYG Editor
Rather than rewrite someone else’s good material, I used this guide to help me set up Hugo
I ignored the parts about setting up a public bucket and static website hosting and ignored the part about pointing my domain at the bucket. Instead…
CloudFront in front of S3
I whacked CloudFront infront of my bucket
Created a CloudFront S3 Identify and secured the bucket
Created an SSL certificate in ACM
Created a lambda@edge to redirect to
index.html
where necessary'use strict'; exports.handler = (event, context, callback) => { // Extract the request from the CloudFront event that is sent to Lambda@Edge var request = event.Records[0].cf.request; // Extract the URI from the olduri var olduri = request.uri; var a = olduri.split("."); if( (a.length === 1) && (a[0].charAt(a[0].length - 1) != "/" )) { newuri = olduri + "/index.html"; console.log("Old URI: " + olduri); console.log("New URI: " + newuri); request.uri = newuri; return callback(null, request); } // Match any '/' that occurs at the end of a URI. Replace it with a default index var newuri = olduri.replace(/\/$/, '\/index.html'); // Log the URI as received by CloudFront and the new URI to be used to fetch from origin console.log("Old URI: " + olduri); console.log("New URI: " + newuri); // Replace the received URI with the URI that includes the index page request.uri = newuri; // Return to CloudFront return callback(null, request); };
Created another lambda@edge to add on some security headers in all my responses - because, why not
A couple of changes were needed from the below to allow for github commenting, but just put everything here to keep it clean. Its sufficient to get full marks at securityheaders.com
'use strict'; exports.handler = (event, context, callback) => { //Get contents of response const response = event.Records[0].cf.response; const headers = response.headers; //Set new headers headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age=31556952; includeSubdomains; preload'}]; headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'self'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}]; headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}]; headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}]; headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}]; headers['referrer-policy'] = [{key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin'}]; headers['feature-policy'] = [{key: 'Feature-Policy', value: "autoplay 'none'; camera 'none'; document-domain 'none'; encrypted-media 'none'; fullscreen 'none'; geolocation 'none'; microphone 'none'; midi 'none'; payment 'none'; vr 'none'"}]; //Return modified response callback(null, response); };
WYSIWYG Editor
That’s all well and good, but I also wanted to be able to update my blog on the fly from my phone or wherever easily and pain free. Below got that all done for me
- A github repository - https://github.com/nick-stocks/website
- A WYSIWYG post editor, which pushes my markdown posts to my github repository. - https://www.forestry.io. Free for single user use and, bonus, it also generates a preview of the site
- A github workflow to automatically generate the Hugo static website on every push, then run AWS S3 Sync to push it up to my bucket - https://github.com/nick-stocks/website/blob/master/.github/workflows/main.yml
Mission accomplished. No idea what I’ll do with this site now… 🤷♂️