Headless Wordpress CMS on AWS

Quickly spin up a headless Wordpress CMS on AWS using Docker

Randy Findley
Nov 2, 2018 · 5 min read
Credit — https://www.superdesk.org/news/headless-cms

Headless CMS is very popular at the moment. But what is a headless CMS and why should I start using one?

A headless CMS is a backend that is decoupled from its frontends. The backend is where the content is created and published. Whereas the frontends are where the content is displayed (web, mobile apps, set-top box, Alexa, etc…).

For example, a traditional CMS is a single website. The same website is used to add the content as it is to display the content. The backend and frontend are coupled.

A headless CMS is only used to created and publish content. That content is then available through an API. The website or mobile apps, for displaying the content, are separate.

But why is decoupled better? Here are some of the reasons:

  • Faster and more flexible content delivery than traditional CMS
  • Resiliency in the face of changes on the user interface side (future-proof)
  • Rapid design iterations
  • Enhanced security
  • Fewer publisher and developer dependencies
  • Simpler deployment

*** Thanks for the list Brightspot

Now that we all emphatically agree that headless CMS is the way to go. Let’s take a look at these awesome CloudFormation templates I created to help you spin up and manage your headless (Wordpress) CMS.

To be clear, this is a Wordpress installation running on AWS using Infrastructure as Code and Docker.

Wait… Why use Wordpress and not one of these cool new headless CMS services like Contently or Cosmic JS? Well, these services are really great but they cost a lot of money, and I usually like to run everything myself, if I can help it. And… Wordpress is really good at managing content.

But how can Wordpress be a headless CMS? Easy, it has an API.

The trick is making Wordpress stateless so that it can autoscale, and run on AWS, with zero-downtime deployments.

Ok, headless CMS is cool, Wordpress is pretty cool, let's continue.


Our Wordpress instance is running as an Elastic Container Service using Docker.

First we have the VPC, then an ECS cluster, then an EC2 instance, and finally an ECS service with tasks. Our Wordpress service is exposed to the world via an Elastic Load Balancer. We’re using RDS as our MySQL database.

Our Wordpress service is stateless, which means we can’t rely on the file system to store content, like Wordpress Media or Plugins. Every time an instance of our Wordpress service is spawned it will only have the files that are baked into our Docker image.

Let’s take a look at how we handle Wordpress Media first.

We use a plugin called WP Offload Media. This plugin allows us to store the Media in S3 and use CloudFront as the CDN. Take a look at the diagram below. We also use the same CDN to cache the Wordpress API…

Now how do we handle the Plugins? (We can ignore Templates because this is headless 😃)

Remember when I talked about baking things into our Docker image? That’s it… We have to include the Plugins in our Docker image. Let’s take a look at that Dockerfile and go through it.

As you can see our Dockerfile is really simple. It extends the latest Wordpress image and then installs 3 Plugins. It downloads, unzips, and copies each plugin to the wordpress/wp-content/ directory. When you launch your Wordpress site for the first time you’ll have to activate these plugins. The activation status is stored in MySQL so you won’t have to do it every time your ECS tasks recycle.


Alright, let’s get this architecture installed. First a few prerequisites.


Install the following prerequisites:


Now let’s install each stack one at a time.

  • VPC
  • ECS
  • RDS
  • ECR
  • Wordpress


This creates the Amazon Virtual Private Cloud that our ECS cluster and RDS database will run in.

Amazon Virtual Private Cloud (Amazon VPC) lets you provision a logically isolated section of the AWS Cloud where you can launch AWS resources in a virtual network that you define.

cd vpc
cim stack-up


This creates an Elastic Container Service that our EC2’s will run in.

Amazon Elastic Container Service (Amazon ECS) is a highly scalable, high-performance container orchestration service that supports Docker containers and allows you to easily run and scale containerized applications on AWS.

cd vpc
cim stack-up


This creates a Relational Database Service database cluster that our Wordpress application will use.

Amazon Relational Database Service (Amazon RDS) makes it easy to set up, operate, and scale a relational database in the cloud.

cd rds
export DatabaseUsername="???"; export DatabasePassword="???"; cim stack-up


This creates an Elastic Container Registry that will hold the docker images of our wordpress service.

Amazon Elastic Container Registry (ECR) is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images.

cd ecr
cim stack-up


Before we can launch this CloudFormation stack. We need to push our Wordpress image to ECR.

Push Image

cd wordpress/src

Registry Authentication

  • aws ecr get-login --registry-ids <account-id>
  • copy/past output to perform docker login, also append /headless-wp to the repository url.

Build Image

  • docker build -t headless-wp:<version> .

Push Image

  • docker tag headless-wp:<version> <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp:latest
  • docker tag headless-wp:<version> <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp:<version>
  • docker push <account-id>.dkr.ecr.<region>.amazonaws.com/headless-wp

Update Version

Make sure the Version parameter, in _cim.yml, matches the version tag from above. The ECS Task Definition will pull the image from ECR.

Stack up

Once the Version is set you can use cim stack-up to update the stack with the new version.

cd wordpress
cim stack-up

Congratulations, your new Wordpress site is now available.

First run through the Wordpress setup wizard.

Next enable some of the plugins we added.

Add a few blog posts and pages.

Then check out the API. Ex: https://<cdn-url>/wp-json/wp/v2/posts

Environment Variables

Congratulations on getting your Headless Wordpress installed. If you got stuck anywhere along the way please don’t hesitate to reach out to me for help.

One thing I want to explain is the Wordpress environment variables because they really tie everything together. They tell our Wordpress installation about the RDS database, the Media S3 bucket, and CloudFront CDN URL. Let’s take a look. These can be found in the Wordpress stack’s AWS::ECS::TaskDefinition.

The WORDPRESS_DB_* variables are straight from the RDS stack. CloudFormation allows you to Export Output variables which can be imported in other stacks.

The WORDPRESS_CONFIG_EXTRA variable is where we configure the WP Offload Media plugin. First we tell it to use our Task Role, AWS::IAM::Role, via the AS3CF_AWS_USE_EC2_IAM_ROLE var. Then we the AS3CF_SETTINGS var to setup the plugin.

Thanks for reading. I hope you enjoyed it!


how hackers start their afternoons.

Randy Findley

Written by

Software Engineer & Entrepreneur


how hackers start their afternoons.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade