Integration & Automation

Create a more secure LAMP stack with AWS WAF (web application firewall)

LAMP stacks—with their classic layered architecture using a Linux foundation followed by Apache, MySQL, and PHP—provide time-tested software for delivering high-performance web applications. Like any open-source projects, LAMP stacks may be vulnerable to common web exploits and bots. This means that LAMP stacks may be subject to compromised security, limited availability, or excessive consumption of resources.

Deploying a web application firewall can help you secure LAMP stacks against web-application vulnerabilities and distributed denial of service (DDoS) attacks.

You can build a LAMP-stack application from scratch or by following this Amazon Web Services (AWS) tutorial: Install a LAMP web server on the Amazon Linux AMI. The tutorial, however, does not delve into ways you can secure a LAMP-stack application against web-application vulnerabilities and distributed denial of service (DDoS) attacks.

In this post, we walk through automation steps to deploy a highly available LAMP-stack application using an Application Load Balancer, Amazon Route 53, and—to help secure your application—an AWS WAF web application firewall and a Transport Layer Security (TLS) certificate using AWS Certificate Manager (ACM). We show how to launch a classic three-tier stack consisting of a presentation tier, application tier, and data tier. This architecture can host a variety of popular web applications—such as WordPress, Wikipedia, and Drupal—in minutes.

About this blog post
Time to read ~9 min.
Time to complete ~10 min.
Cost to complete ~$0
Learning level Advanced (300)
AWS services AWS Identity and Access Management (IAM)
Amazon Route 53
AWS Certificate Manager (ACM)
AWS Command Line Interface (AWS CLI)
AWS Cloud Development Kit (AWS CDK)


In this walkthrough, you deploy the following high-level architecture:

architecture diagram


Before you begin the walkthrough, you need the following:

Walkthrough: Create a more secure LAMP stack with AWS WAF

Deploying individual AWS resources manually can be complex and error-prone. Our walkthrough deploys and updates AWS resources in an automated, declarative, infrastructure-as-code style. After you provision a LAMP stack in this way, customers can create more secure, highly available LAMP-stack applications that they can provision and manage in an orderly, predictable fashion.

In this walkthrough, you provision the LAMP-stack application with resources:

  • You create an AWS WAF that protects the LAMP-stack application against common web exploits, such as Structured Query Language (SQL) injection and cross-site scripting.
  • You launch an Amazon Elastic Compute Cloud (Amazon EC2) Auto Scaling group where you deploy the LAMP stack.
  • You create an Amazon Route 53 alias record to route traffic to the Application Load Balancer.

This walkthrough comprises these main steps:

Step 1. Clone the GitHub repository.
Step 2. Set up the environment and bootstrapping.
Step 3. Create the LAMP stack.
Step 4. Create a Route 53 alias record.
Step 5. Test your LAMP-stack application.

Step 1. Clone the GitHub repository

Clone the aws-cdk-deploy-lamp-with-waf-r53-alb GitHub repository as follows:

  1. Change the current working directory to the location where you want the cloned directory.
  2. Clone the repository to your development environment terminal as follows:

$ git clone

The repository contains the following reusable resources:

  • CDK application
  • Amazon EC2
  • AWS IAM role
  • AWS Auto Scaling
  • Amazon Route 53
  • Application Load Balancer

This is the repo’s directory structure:

directory structure

Step 2. Set up the environment and bootstrapping

  1. Create a virtual environment and install dependencies.
    1. Navigate to the root of the directory that you just created: $ cd cdk-lampstack
    2. Create a virtual Python environment for CDK: $ python3 -m venv .env
    3. Activate the virtual environment: $ source .env/bin/activate
    4. Install the required dependencies: $ pip3 install -r requirements.txt
  2. Configure the AWS CLI. For details, refer to Configuring the AWS CLI. Ensure that the IAM user or role is granted least permissive access.
  3. If deploying AWS CDK apps into your AWS environment requires that you provision resources, the AWS CDK must perform the deployment. The process of provisioning these initial resources is called bootstrapping. In this case, run the following command to bootstrap your AWS environment, filling in the items in brackets:

$ cdk bootstrap aws://<account-number>/<region>

Step 3. Create the LAMP stack

In this section, you configure the CDK context parameters that will be used to provision the LAMP stack in your AWS account. You deploy two stacks, WafRegionalStack and CdkLampstackStack.

  1. On your development-environment terminal, run the vi command, filling in the items in brackets:
$ vi
# (Update the variables for your environment)
var_region = '<region>'
var_vpc_id = "<vpc-id>" # Import an Exist VPC
var_account_id = '<aws-account-number>'
var_ec2_type = "<t2.micro>"
cert_arn = "<certificate-arn>" # An Amazon Resource Name (ARN) in the form arn:aws:acm:region:account:certificate/certificate_ID
  1. From the root of the project directory, list these stacks by running the cdk ls command:
$ cdk ls
  1. Still in the root of the project directory, provision the LAMP stack by running the cdk deploy --all command:
$ cdk deploy ––all
Type "y" to agree the question of "Do you wish to deploy these changes"
<< Take around 5 mins>>
<< Once finished, CDK print outputs to the CLI as below: >>

✅ WafRegionalStack

WafRegionalStack.WafAclArn = arn:aws:wafv2:us-east-1:<account-id>:regional/webacl/waf-regional/951ce2be-bfcf-4db4-926d-9fbbbea1b193

Stack ARN:

✅ CdkLampstackStack

CdkLampstackStack.LoadBalancer =

Stack ARN:
arn:aws:cloudformation:us-east-1: :<account-id>:stack/CdkLampstackStack/824b3c80-8bab-11ec-b72a-12fb6e4d7bd1

Step 4. Create a Route 53 alias record

In this section, you create an Amazon Route 53 alias record for your domain and map it to the DNS name of the Application Load Balancer that you just created. (This DNS name, as listed in the CdkLampstackStack Outputs section, is CdkLampstackStack.LoadBalancer.)

  1. Sign in to the AWS Management Console, and open the Route 53 console.
  2. In the navigation pane, choose Hosted zones.
  3. On the Hosted zones page, choose the name of the hosted zone that you want to create records in.
  4. Choose Create record.
  5. Choose and define the applicable routing policy and values as follows.
    • Routing policy: Choose Simple routing.
    • Record name: Enter the name of a subdomain that you want to route traffic. Keep blank to use the default value, which is the name of the hosted zone.
    • Value/route traffic to: Choose Endpoint, and choose a load balancer from the list. If you have many load balancers, you can enter the first few characters of the DNS name to filter the list.
    • Record type: Select A — IPv4 address or AAAA — IPv6 address.
    • Evaluate target health: Keep the default value.

You have now provisioned the LAMP-stack application.

Step 5. Test your LAMP-stack application

  1. (Optional) Modify the AWS WAF GeoMatch rule, shown here.

Details of the Geomatch rule (screenshot).

For example, you can use the GeoMatch rule to block or allow access to your site from specific countries. By default, access is limited to requests coming from the United States so that you can test your setup. If you are deploying this architecture from a county other than the United States, modify the rule with the country you are deploying from. For more information, refer to Geographic match rule statement.

Also, a custom response is configured in the GeoMatch rule, modifying the response code from HTTP 403 to a human-readable message for the end user. You can add your own custom content to the document root so that it appears instead of the default test page.

  1. Confirm that the website is live. To do so, enter the Route 53 DNS address in a web browser. If you haven’t uploaded any custom content, you see the default Amazon Linux AMI test page, confirming that the Apache HTTP server is operating properly.
  2. (Optional) Visit the website from a location outside of the country that you specified in the AWS WAF GeoMatch rule. For example, if you configured the rule to allow traffic from within the United States only, and you try to visit the site from another country, you should see the following message: You are not allowed to access this website from outside the United States.


To avoid ongoing charges in your AWS account, delete the AWS resources created in this walkthrough.

  1. On your development environment terminal, navigate to the root of the repo and run the following command:

$ cdk destroy –all

  1. Sign in to the AWS Management Console, and delete any resources that you created manually.


In this blog post, we walked you through creating a highly available, more secure LAMP stack with AWS WAF web application firewall, Route 53 domain, and AWS Certificate Manager. We used AWS CDK to define the LAMP-stack infrastructure as code and provision it without performance impact or operational overhead. Companies of any size can adopt this approach to build more secure, high-performing, resilient, and efficient infrastructure for their LAMP-stack applications and workloads.

Further reading:

About the authors

Ali Asfour headshot

Ali Asfour

Ali, a senior security consultant with AWS Professional Services, enjoys working closely with customers and supporting their digital transformation and AWS adoption journey. He focuses on DevOps, containers, and security.

Arun Chandapillai headshot

Arun Chandapillai

Arun, a senior cloud infrastructure architect with AWS Professional Services, champions diversity and inclusion. He’s passionate about helping his customers accelerate IT modernization through business-first cloud-adoption strategies to build, deploy, and manage applications and infrastructure in the cloud. Arun is an automotive enthusiast, an avid speaker, and a philanthropist who believes that you get (back) what you give.