Introduction
In today’s cloud-first world, managing infrastructure manually is no longer practical. Terraform, a powerful Infrastructure as Code (IaC) tool, combined with AWS Lightsail, offers a streamlined approach to deploying and managing web applications. This guide focuses on deploying a WordPress infrastructure using Terraform to automate AWS Lightsail resources.
By using Terraform with AWS Lightsail, you’ll benefit from:
- Consistent, version-controlled infrastructure
- Automated deployment processes
- Reduced human error
- Cost-effective resource management
We’ll build a complete WordPress deployment including multiple instances, a managed MySQL database, and a load balancer for high availability. For more information on AWS Lightsail read Deploying Applications on AWS Lightsail to get started.
Prerequisites
Before beginning this project, ensure you have:
- An active AWS account with appropriate permissions
- Terraform (version 0.12 or later) installed on your local machine
- AWS CLI installed and configured
- Basic familiarity with WordPress administration
- Understanding of basic networking concepts
Understanding the Components
AWS Lightsail Overview
AWS Lightsail is Amazon’s simplified cloud platform offering:
Features and Benefits:
- Pre-configured application stacks
- Simplified virtual server management
- Managed databases
- Integrated load balancers
- Fixed, predictable pricing
- Easy scaling options
Available Resources:
- Virtual Private Servers (instances)
- Managed databases
- Load balancers
- Static IPs
- DNS management
Project Architecture
Our WordPress deployment consists of:
- Multiple WordPress instances for redundancy
- A managed MySQL database for data persistence
- Load balancer for traffic distribution
- Networking components for security and access
Setting Up the Development Environment
Installing Required Tools
- Terraform Installation:
# macOS (using Homebrew)
brew install terraform
# Linux
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install terraform
- AWS CLI Setup:
# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
Configuring AWS Credentials
aws configure
Project Directory Structure
wordpress-lightsail/
├── main.tf
├── variables.tf
├── outputs.tf
└── terraform.tfvars
Initial Terraform Configuration
Create a new directory and initialize Terraform:
mkdir wordpress-lightsail
cd wordpress-lightsail
terraform init
Creating the Base Infrastructure
Provider Configuration
provider "aws" {
region = var.region
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
This configuration does two important things:
- Sets up the AWS provider using the region specified in our variables
- Specifies that we need the AWS provider from HashiCorp’s registry at version 4.x to ensure compatibility with our code and prevent unexpected changes from newer provider versions
Variables and Data Sources
Create variables.tf
:
variable "region" {
description = "AWS region"
default = "us-east-1"
}
variable "project_name" {
description = "Project name for resource naming"
default = "wptest"
}
variable "environment" {
description = "Deployment environment"
default = "dev"
}
variable "instance_count" {
description = "Number of WordPress instances"
default = 2
}
variable "db_username" {
description = "MySQL user name"
default = "wordpress"
}
variable "db_password" {
description = "MySQL password"
default = "Really-$ecret-passw0rd!"
}
variable "domain_name" {
description = "Wordpress Domain"
default = "fake-domain.local"
}
These variables define the core configuration values for our infrastructure. The region, project name, and environment variables will be used for resource naming and location. Instance count controls the number of WordPress servers we’ll deploy, while the database variables store credentials (which in production should be handled more securely through a secret management service).
Basic Resource Structure
Follow these naming conventions:
- Use lowercase with hyphens
- Include project name in resource names
- Add purpose-specific suffixes
- Tag all resources appropriately
Database Deployment
MySQL Database Configuration
resource "aws_lightsail_database" "wordpress_db" {
relational_database_name = "${var.project_name}-db"
availability_zone = "${var.region}a"
blueprint_id = "mysql_8_0"
bundle_id = "micro_2_0"
master_database_name = "wordpress"
master_username = var.db_username
master_password = var.db_password
backup_retention_enabled = true
}
This code creates a MySQL 8.0 database instance in the specified availability zone. The micro_2_0
bundle provides enough resources for a small WordPress site while keeping costs down. We enable backup retention to ensure data durability, and configure the database with credentials from our variables.
Security Considerations
- Store sensitive data appropriately. Storing Sensitive Information in AWS Parameter Store with Terraform
- Use strong password policies
- Implement backup retention
- Configure appropriate firewall rules
Performance Settings
- Choose appropriate bundle size based on workload
- Enable automated backups
- Configure monitoring alerts
- Set up maintenance windows
WordPress Instance Deployment
Instance Configuration
resource "aws_lightsail_instance" "wordpress" {
count = var.instance_count
name = "${var.project_name}-instance-${count.index}"
availability_zone = "${var.region}a"
blueprint_id = "wordpress"
bundle_id = "small_2_0"
user_data = <<-EOF
#!/bin/bash
# Configure WordPress database connection
wp_config="/opt/bitnami/wordpress/wp-config.php"
sed -i "s/define( 'DB_HOST', '.*' );/define( 'DB_HOST', '${aws_lightsail_database.wordpress_db.master_endpoint_address}' );/" $wp_config
sed -i "s/define( 'DB_NAME', '.*' );/define( 'DB_NAME', 'wordpress' );/" $wp_config
sed -i "s/define( 'DB_USER', '.*' );/define( 'DB_USER', '${var.db_username}' );/" $wp_config
sed -i "s/define( 'DB_PASSWORD', '.*' );/define( 'DB_PASSWORD', '${var.db_password}' );/" $wp_config
EOF
}
This code creates multiple WordPress instances using a count based on our instance_count
variable. Each instance uses Lightsail’s WordPress blueprint and includes a startup script that automatically configures the WordPress database connection to use our external MySQL database instead of the default local database.
Static IP Assignment
resource "aws_lightsail_static_ip" "wordpress" {
count = var.instance_count
name = "${var.project_name}-static-ip-${count.index}"
}
resource "aws_lightsail_static_ip_attachment" "wordpress" {
count = var.instance_count
static_ip_name = aws_lightsail_static_ip.wordpress[count.index].name
instance_name = aws_lightsail_instance.wordpress[count.index].name
}
Static IPs ensure our WordPress instances maintain the same public IP addresses even after restarts or replacements. The first resource creates static IP addresses, while the second attaches them to our WordPress instances. This prevents downtime due to IP changes when instances are restarted and simplifies DNS configuration if needed.
Load Balancer Setup
Load Balancer Configuration
resource "aws_lightsail_lb" "wordpress" {
name = "${var.project_name}-lb"
health_check_path = "/"
instance_port = 80
tags = {
Environment = var.environment
}
}
resource "aws_lightsail_lb_attachment" "wordpress" {
count = var.instance_count
lb_name = aws_lightsail_lb.wordpress.name
instance_name = aws_lightsail_instance.wordpress[count.index].name
}
The load balancer distributes traffic across multiple WordPress instances for improved reliability and performance. The first resource creates the load balancer that checks instance health by accessing the root path (“/”) and forwards traffic to port 80. The second resource attaches each WordPress instance to the load balancer, ensuring traffic is distributed across all available instances, improving both reliability and performance.
SSL/TLS Setup
resource "aws_lightsail_lb_certificate" "wordpress" {
name = "${var.project_name}-cert"
lb_name = aws_lightsail_lb.wordpress.name
domain_name = var.domain_name
}
This code provisions an SSL/TLS certificate for secure HTTPS connections to your WordPress site. The certificate is automatically attached to the load balancer and will be used for encrypted connections to your domain.
Networking and Security
Firewall Rules
resource "aws_lightsail_instance_public_ports" "wordpress" {
count = var.instance_count
instance_name = aws_lightsail_instance.wordpress[count.index].name
port_info {
protocol = "tcp"
from_port = 80
to_port = 80
}
port_info {
protocol = "tcp"
from_port = 443
to_port = 443
}
}
This configuration opens HTTP (port 80) and HTTPS (port 443) access to our WordPress instances, allowing web traffic while keeping other ports closed for security. By explicitly defining only the necessary ports, we reduce the attack surface and improve the overall security posture of our infrastructure.
Domain Setup
resource "aws_lightsail_domain" "wordpress" {
domain_name = var.domain_name
}
resource "aws_lightsail_domain_entry" "wordpress" {
domain_name = aws_lightsail_domain.wordpress.domain_name
type = "CNAME"
name = "www"
target = aws_lightsail_lb.wordpress.dns_name
}
Configure DNS settings to make the WordPress site accessible via your domain name. The first resource registers your domain with Lightsail’s DNS service. The second creates a CNAME record that points “www.yourdomain.com” to your load balancer, allowing users to access your WordPress site using the www subdomain.
Deployment Process
Terraform Workflow
- Initialize the working directory:
terraform init
- Review the execution plan:
terraform plan
- Apply the configuration:
terraform apply
Validation Steps
- Verify WordPress accessibility
- Test database connectivity
- Confirm load balancer distribution
- Check SSL certificate validity
- Validate domain resolution
Maintenance and Operations
Monitoring Setup
- Enable Lightsail monitoring
- Configure CloudWatch alerts
- Set up performance metrics
- Monitor resource utilization
Backup Strategies
- Enable automated database backups
- Configure instance snapshots
- Implement disaster recovery plan
- Test restore procedures regularly
Update Procedures
- Create instance snapshots
- Apply WordPress updates
- Update database versions
- Rotate SSL certificates
- Review security patches
Best Practices and Optimization
Security Recommendations
- Use strong passwords
- Implement least privilege access
- Enable HTTPS only
- Regular security audits
- Keep WordPress core and plugins updated
Cost Optimization
- Right-size instances
- Monitor resource usage
- Clean up unused resources
- Use fixed-price bundles
- Enable cost alerts
Conclusion
This guide has demonstrated how to deploy a scalable WordPress infrastructure using Terraform and AWS Lightsail. By following these practices, you can create a reliable, maintainable, and cost-effective WordPress deployment.
Next Steps
- Implement monitoring and alerting
- Set up continuous deployment
- Configure backup automation
- Implement security hardening
Appendix
Command Cheatsheet
# Initialize Terraform
terraform init
# Format configuration
terraform fmt
# Validate configuration
terraform validate
# Plan deployment
terraform plan
# Apply changes
terraform apply
# Destroy resources terraform destroy