Skip to content

Commit e92d1bd

Browse files
authored
Initial release of serverless-static-wordpress (#1)
1 parent 682cd83 commit e92d1bd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3859
-0
lines changed

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @petewilcock
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
name: test-suite-master
3+
# yamllint disable-line rule:truthy
4+
on:
5+
push:
6+
branches:
7+
- master
8+
jobs:
9+
tflint:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/[email protected]
13+
- name: setup Terraform
14+
uses: hashicorp/[email protected]
15+
with:
16+
terraform_version: 0.15.5
17+
- name: Terraform init
18+
run: terraform init --backend=false
19+
- name: tflint
20+
uses: reviewdog/action-tflint@master
21+
with:
22+
github_token: ${{ secrets.ACTIONS_TOKEN }}
23+
reporter: github-check
24+
filter_mode: added
25+
flags: --module
26+
level: error
27+
tfsec:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/[email protected]
31+
- name: setup Terraform
32+
uses: hashicorp/[email protected]
33+
with:
34+
terraform_version: 0.15.5
35+
- name: Terraform init
36+
run: terraform init --backend=false
37+
- name: tfsec
38+
uses: reviewdog/action-tfsec@master
39+
with:
40+
github_token: ${{ secrets.ACTIONS_TOKEN }}
41+
reporter: github-check
42+
filter_mode: added
43+
level: warning
44+
misspell:
45+
runs-on: ubuntu-latest
46+
steps:
47+
- uses: actions/[email protected]
48+
- name: misspell
49+
uses: reviewdog/action-misspell@v1
50+
with:
51+
github_token: ${{ secrets.ACTIONS_TOKEN }}
52+
locale: "US"
53+
reporter: github-check
54+
filter_mode: added
55+
level: error
56+
yamllint:
57+
runs-on: ubuntu-latest
58+
steps:
59+
- uses: actions/[email protected]
60+
- name: yamllint
61+
uses: reviewdog/[email protected]
62+
with:
63+
github_token: ${{ secrets.ACTIONS_TOKEN }}
64+
reporter: github-check
65+
filter_mode: added
66+
level: error

.github/workflows/testsuite.yaml

+93
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
name: test-suite
3+
# yamllint disable-line rule:truthy
4+
on:
5+
pull_request:
6+
jobs:
7+
pre-commit:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/[email protected]
11+
- name: Set up Python
12+
uses: actions/[email protected]
13+
- name: Install prerequisites
14+
run: ./bin/install-ubuntu.sh
15+
- name: Terraform init
16+
run: terraform init --backend=false
17+
- name: pre-commit
18+
uses: pre-commit/[email protected]
19+
env:
20+
AWS_DEFAULT_REGION: eu-west-1
21+
# many of these are covered by better reviewdog linters below
22+
SKIP: >-
23+
terraform_tflint_deep,
24+
no-commit-to-branch,
25+
terraform_tflint_nocreds,
26+
terraform_tfsec
27+
- uses: stefanzweifel/[email protected]
28+
if: ${{ failure() }}
29+
with:
30+
commit_message: Apply automatic changes
31+
commit_options: "--no-verify"
32+
# Optional commit user and author settings
33+
commit_user_name: Linter Bot
34+
commit_user_email: [email protected]
35+
commit_author: Linter Bot <[email protected]>
36+
tflint:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/[email protected]
40+
- name: setup Terraform
41+
uses: hashicorp/[email protected]
42+
with:
43+
terraform_version: 0.15.5
44+
- name: Terraform init
45+
run: terraform init --backend=false
46+
- name: tflint
47+
uses: reviewdog/action-tflint@master
48+
with:
49+
github_token: ${{ secrets.ACTIONS_TOKEN }}
50+
reporter: github-pr-check
51+
filter_mode: added
52+
flags: --module
53+
level: error
54+
tfsec:
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/[email protected]
58+
- name: setup Terraform
59+
uses: hashicorp/[email protected]
60+
with:
61+
terraform_version: 0.15.5
62+
- name: Terraform init
63+
run: terraform init --backend=false
64+
- name: tfsec
65+
uses: reviewdog/action-tfsec@master
66+
with:
67+
github_token: ${{ secrets.ACTIONS_TOKEN }}
68+
reporter: github-pr-check
69+
filter_mode: added
70+
level: warning
71+
misspell:
72+
runs-on: ubuntu-latest
73+
steps:
74+
- uses: actions/[email protected]
75+
- name: misspell
76+
uses: reviewdog/action-misspell@v1
77+
with:
78+
github_token: ${{ secrets.ACTIONS_TOKEN }}
79+
locale: "US"
80+
reporter: github-pr-check
81+
filter_mode: added
82+
level: error
83+
yamllint:
84+
runs-on: ubuntu-latest
85+
steps:
86+
- uses: actions/[email protected]
87+
- name: yamllint
88+
uses: reviewdog/[email protected]
89+
with:
90+
github_token: ${{ secrets.ACTIONS_TOKEN }}
91+
reporter: github-pr-check
92+
filter_mode: added
93+
level: error

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Build artifacts
2+
modules/cloudfront/lambda_redirect/dst/*
3+
modules/codebuild/codebuild_files/wordpress_docker.zip
4+
modules/codebuild/codebuild_files/php.ini
5+
6+
# Local .terraform directories
7+
**/.terraform/*
8+
9+
# .tfstate files
10+
# *.tfstate
11+
# *.tfstate.*
12+
.terraform.lock.hcl
13+
plan.plan
14+
# Crash log files
15+
crash.log
16+
17+
# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
18+
# .tfvars files are managed as part of configuration and so should be included in
19+
# version control.
20+
#
21+
# example.tfvars
22+
23+
# Ignore override files as they are usually used to override resources locally and so
24+
# are not checked in
25+
override.tf
26+
override.tf.json
27+
*_override.tf
28+
*_override.tf.json
29+
30+
# Include override files you do wish to add to version control using negated pattern
31+
#
32+
# !example_override.tf
33+
34+
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
35+
# example: *tfplan*
36+
37+
.idea

.header.md

+168
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# terraform-aws-serverless-static-wordpress
2+
3+
[![Test Suite](https://github.com/techtospeech/terraform-aws-serverless-static-wordpress/workflows/test-suite-master/badge.svg?branch=master&event=push)](https://github.com/techtospeech/terraform-aws-serverless-static-wordpress/actions/workflows/testsuite-master.yaml?query=branch%3Amaster+event%3Apush+workflow%3Atest-suite)
4+
<a href="https://twitter.com/intent/follow?screen_name=TechToSpeech"><img src="https://img.shields.io/twitter/follow/TechToSpeech?style=social&logo=twitter" alt="follow on Twitter"></a>
5+
6+
## Introduction
7+
8+
Serverless Static Wordpress is a Community Terraform Module from TechToSpeech that needs nothing more than a registered
9+
domain name with its DNS pointed at AWS.
10+
11+
It creates a complete infrastructure framework that allows you to launch a temporary, transient Wordpress container.
12+
You then log in and customize it like any Wordpress site, and finally publish it as a static site fronted by a global
13+
CloudFront CDN and S3 Origin. When you’re done you shut down the Wordpress container and it costs you almost nothing.
14+
15+
The emphasis is on extremely minimal configuration as the majority of everything you’d need is pre-installed and
16+
pre-configured in line with industry best practices and highly efficient running costs.
17+
18+
## Architecture Overview
19+
20+
![Architecture](docs/serverless-static-wordpress.png)
21+
22+
## Pre-requisites
23+
24+
- A domain name either hosted with AWS, or with its DNS delegated to a Route53 hosted zone.
25+
- A VPC configured with at least one public subnet in your desired deployment region.
26+
27+
## Provider Set-up
28+
29+
Terraform best practice is to configure providers at the top-level module and pass them downwards through implicit
30+
inheritance or explicit passing. Whilst the module and child-modules reference `required_providers`, it is also necessary
31+
for you to provide a regional alias for operations that _must_ be executed in us-east-1 (CloudFront, ACM, and WAF).
32+
As such you should include the following in your provider configuration:
33+
34+
```
35+
terraform {
36+
required_version = "> 0.15.1"
37+
required_providers {
38+
aws = {
39+
source = "hashicorp/aws"
40+
version = "~> 3.0"
41+
configuration_aliases = [aws.ue1]
42+
}
43+
}
44+
}
45+
46+
provider "aws" {
47+
alias = "ue1"
48+
region = "us-east-1"
49+
}
50+
51+
```
52+
53+
The `ue1` alias is essential for this module to work correctly.
54+
55+
## Module instantiation example
56+
57+
```
58+
locals {
59+
aws_account_id = "998877676554"
60+
aws_region = "eu-west-1"
61+
site_name = "peterdotcloud"
62+
profile = "peterdotcloud"
63+
site_domain = "peter.cloud"
64+
}
65+
66+
data "aws_caller_identity" "current" {}
67+
68+
module "peterdotcloud_website" {
69+
source = "TechToSpeech/serverless-static-wordpress/aws"
70+
version = "0.1.0"
71+
main_vpc_id = "vpc-e121c09b"
72+
subnet_ids = ["subnet-04b97235","subnet-08fb235","subnet-04b97734"]
73+
aws_account_id = data.aws_caller_identity.current.account_id
74+
75+
# site_name will be used to prepend resource names - use no spaces or special characters
76+
site_name = local.site_name
77+
site_domain = local.site_domain
78+
wordpress_subdomain = "wordpress"
79+
hosted_zone_id = "Z00437553UWAVIRHANGCN"
80+
s3_region = local.aws_region
81+
82+
# Send ECS and RDS events to Slack
83+
slack_webhook = "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"
84+
ecs_cpu = 1024
85+
ecs_memory = 2048
86+
cloudfront_aliases = ["www.peter.cloud", "peter.cloud"]
87+
waf_enabled = true
88+
89+
# Provides the toggle to launch Wordpress container
90+
launch = 0
91+
92+
## Passing in Provider block to module is essential
93+
providers = {
94+
aws.ue1 = aws.ue1
95+
}
96+
}
97+
```
98+
99+
Do not to set `launch` to 1 initially as the module uses a Codebuild pipeline to take a vanilla version
100+
of the Wordpress docker container and rebake it to include all of the pre-requisites required to publish the Wordpress
101+
site to S3.
102+
103+
The step to push the required Wordpress container from Dockerhub to your own ECR repository can be tied into your
104+
module instantiation using our [helper module](https://github.com/TechToSpeech/terraform-aws-ecr-mirror) as follows:
105+
106+
Note this requires Docker to be running on your Terraform environment with either a named AWS profile or credentials
107+
otherwise available.
108+
```
109+
module "docker_pullpush" {
110+
source = "TechToSpeech/ecr-mirror/aws"
111+
version = "0.0.6"
112+
aws_account_id = data.aws_caller_identity.current.account_id
113+
aws_region = local.aws_region
114+
docker_source = "wordpress:php7.4-apache"
115+
aws_profile = "peterdotcloud"
116+
ecr_repo_name = module.peterdotcloud_website.wordpress_ecr_repository
117+
ecr_repo_tag = "base"
118+
depends_on = [module.peterdotcloud_website]
119+
}
120+
```
121+
122+
The CodeBuild pipeline takes a couple of minutes to run and pushes back a 'latest' tagged version of the container,
123+
which is what will be used for the Wordpress container. This build either needs to be triggered manually from the
124+
CodeBuild console, or you can use this snippet to trigger the build as part of your Terraform flow:
125+
126+
```
127+
resource "null_resource" "trigger_build" {
128+
triggers = {
129+
codebuild_etag = module.peterdotcloud_website.codebuild_package_etag
130+
}
131+
provisioner "local-exec" {
132+
command = <<-EOT
133+
aws codebuild start-build --project-name "${module.peterdotcloud_website.codebuild_project_name}"
134+
--profile "${local.profile}" --region "${local.aws_region}"
135+
EOT
136+
}
137+
depends_on = [
138+
module.peterdotcloud_website, module.docker_pullpush
139+
]
140+
}
141+
```
142+
143+
Whilst this might feel convoluted (and you might ask: why not just provide a public customized Docker image?), it was
144+
felt important that users should 'own' their own version of the Wordpress container, built transparently from the official Wordpress docker image with full provenance.
145+
146+
Finally, if you wish to fully automate the creation _and_ update of the domain's nameservers if it's registered in
147+
Route53 within the same account, you can add these additional snippets to include this in your flow.
148+
149+
```
150+
resource "aws_route53_zone" "apex" {
151+
name = "peter.cloud"
152+
}
153+
154+
resource "null_resource" "update_nameservers" {
155+
triggers = {
156+
nameservers = aws_route53_zone.apex.id
157+
}
158+
provisioner "local-exec" {
159+
command = <<-EOT
160+
aws route53domains update-domain-nameservers --region us-east-1 --domain-name "${local.site_domain}"
161+
--nameservers Name="${aws_route53_zone.apex.name_servers.0}" Name="${aws_route53_zone.apex.name_servers.1}"
162+
Name="${aws_route53_zone.apex.name_servers.2}" Name="${aws_route53_zone.apex.name_servers.3}" --profile peterdotcloud
163+
EOT
164+
}
165+
depends_on = [aws_route53_zone.apex]
166+
}
167+
```
168+
See [examples](docs/examples) for full set-up example.

0 commit comments

Comments
 (0)