Hosting a static WordPress Site on AWS S3
Tags: aws, s3, docker, wordpress
Published: 2022-01-27 10:45:26

AWS S3 is a good choice for hosting static WordPress sites. It's secure and inexpensive, and frees up time which would otherwise be spent ensuring plugins, themes, and security procedures were appropriately configured.

The article describes one approach for generating the static site. The local development environment requires Docker Compose, and the only requisite plugin is the [Simply Static WP Plugin](https://wordpress.org/plugins/simply-static/), which exports the static site to a zip file before being uploading to S3.

Prerequisites
- Docker Engine
- Docker Compose
- S3 bucket configured to host a static website 

## Preparing the WordPress Site

A quick start guide for running WordPress with Docker Compose can be found at [docs.docker.com](https://docs.docker.com/samples/wordpress/). I've included the reference _docker-compose.yml_ file included in that startup guide in the snippet below. It can be used to build a local WordPress instance by running the command **docker-compose up -d**. The resulting containerized version of WordPress will be available at  **http://localhost:8000**.

```
version: "3.9"

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    extra_hosts:
      - localhost:172.23.0.3
      - localhost:172.23.0.1
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  wordpress_data: {}
```

## Export Static Site

The static site generation part of this work can begin once the WordPress site has been fully configured. Configuration includes selection of the site's theme. Installation of plugins which support the site's functionality. Addition of site specific content, as well as any other customizations required to produce the final result.

- 1 Navigate to _Plugins\Add New\_ and search for _Simply Stati_c.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d2tj2ej2jvzgpp8bafro.png)
 
- 2 Once installed, navigate to _Simply Static\Settings_ and ensure the following options are configured for destination URLs and delivery method

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7aeq5gspkpynhjhj5ps.png)

- 3 Update the location for Temporary Files by navigating to _Simply Static\Settings\Advanced_. (This path will write to our wordpress_data volume)
 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9sr894bozr5srlplgad5.png)

- 4 Generate static files by navigating to _Simply Static\Generate_ and clicking the Generate Static Files button

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x93l3bnm2yfpj9vdaxwx.png)

- 5 Once step 4 is complete, click the link to download the static content. Inspect the contents of the .zip file. It should include the following items

1. - index.html
2. - wp-content/
3. - wp-includes/

## Uploading to AWS S3
In this step, output from running the Simply Static Plugin, is uploaded to S3. 

At the point, the S3 bucket should be configured for [static website hosting](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EnableWebsiteHosting.html). This can be enabled through all the usual AWS paths (REST API, SDK, CLI, CloudFormation). We will be sticking with the console.

- Click on the S3 bucket. Navigate to the Properties tab. Scroll down to the section titled Static website hosting. Enable and select Host a static website as the hosting type. Update the Index document field with the index.html landing page. Save changes.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvxeqx318to3uoz22r2h.png)
Now upload the contents of the Zip file (index.html, wp-content, wp-includes) using the Upload option on the S3 bucket landing page.

The shiny new static WordPress site will now be accessible using the public URL for the site (available under the Properties tab for the S3 bucket under the section _Static website hosting_).

## Secure S3 Bucket with Origin Access Identity (OAI)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dsseepxy099ekkd176zl.png)
 

The S3 bucket can be secured behind a CloudFront distribution to give greater control over access to the S3 bucket. The S3 bucket should be marked private. An [Origin Access Identity (OAI)](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html) will be created and associated with a CloudFront distribution. The S3 bucket permissions are then updated to allow the CloudFront distribution to use the OAI to access the static site. The following snippet illustrates the bucket policy which will allow the CloudFront distribution access. Full details can be found on [docs.aws.amazon.com](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html).

```json
{
    "Version": "2012-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <distribution ID>"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<s3-bucket>/*"
        }
    ]
}
```


## Future Enhancements

The previous guide acts as an introduction to getting a static WordPress site up and running in AWS. In a follow-up article, I refine this current setup and include automation for building and deploying to S3. If you have any comments or suggestions on how this process could be refined, please leave them in the comments section below.