A little Terraform module for Publii hosting

A few months ago (when I started this blog) I was looking around for a serverless CMS solution. I wanted to go serverless for all the main reasons people go serverless (eg. no need to maintain infrastructure, which is normally required for self-hosted CMS solutions, eg. Wordpress / Wagtail). I also had a near zero buget, so also didn't want to pay for databases and servers.

This is where static site generators came to mind. And then I found Publii.

Publii is a nice little CMS and static site generator, which provides an easy to use interface for creating content.

One of the options it provides, is the ability to upload the content straight to an S3 bucket in AWS. There are a lot more, eg GitHub Pages, GitLab, Google Cloud or even FTP/SFTP if you're that way inclined ...

My knowledge is mainly in AWS, so I went with that one (Although probably not the easiest of the choices available). Publii do provide some basic documentation for setting up an AWS account and creating the S3 bucket to host the site, which should get anyone started - although, it does stop short at explaining how to host it under your own domain name, and doesn't quite follow the best security practices.

The building of the terraform module

As with most of the terraform modules I create, they start of with me just writing out some general terraform code for a project, then when I realise I'm copy/pasting code to another project, I decide to create a generic module for it. Then if it seems relatively useful, I go ahead and make it public 😬

You can find or contribute to the module on GitHub - https://github.com/chris-qa-org/terraform-aws-publii-hosting

This module creates the resources to host a site generated by Publii. It can also be used for most static site hosting aswell, however there are some configurations specific to Publii for ease of use.

  • Creates an S3 bucket along with an IAM user which has the minimum required permissions to sync from Publii
  • Creates a CloudFront endpoint (And optionally ACM certificates and Route53 records in an existing Hosted Zone)
  • Creates a Lambda function to run a Cloudfront Invalidation when files.publii.json is created/updated (This file is updated on every sync)
  • Optionally have CloudFront do the right thing when 'Pretty URLs' are enabled (This is achieved via a CloudFront function which adds index.html to the URI if there is no extention)
  • Optionally redirect from the apex domain (eg. example.com) to www (www.example.com). If this is enabled (var.cloudfront_enable_apex_to_www_redirect), the 'Website Url' within 'Server' options should be set to www.yourdomain.com
  • Optionally enable WAF
  • Optionally add custom origins and cache behaviours

Future features

There are a couple of other things that I'd still like to add, such as fixing the /search.html when Pretty URLs are enabled (currently Publii doesn't change the location of it to /search/index.html, so a rewrite will need to be added to the CloudFront function). And also the option to block access to files.publii.json, which essentially exposes the full index to all files on the site (It's not a massive deal, but if it doesn't need to be public, then make it private 👍)