What Is Infrastructure as Code?
Infrastructure as Code (IaC) is a software engineering practice that treats infrastructure configuration—servers, databases, networks, security groups—as versioned, testable code rather than manual, ad-hoc configurations. Instead of clicking through cloud provider consoles or running shell scripts by hand, teams define infrastructure using declarative or imperative languages, then commit that code to version control alongside application source.
For WordPress fleet operators managing dozens or hundreds of sites across regions, IaC is transformative. It replaces brittle manual processes with reproducible, auditable infrastructure definitions that scale consistently from one server to one thousand.
The Core Business Case: Why WordPress Fleets Need IaC
Vilee LLC operates 520+ online businesses globally across the US, EU, and Southeast Asia. Each business runs on WordPress infrastructure—web servers, databases, CDNs, backup systems. Without IaC:
- Configuration drift: One server gets a security patch; another doesn’t. Environment inconsistency cascades into production bugs.
- Slow scaling: Adding 50 new WordPress instances means 50 manual provisioning steps, each prone to typos or missed steps.
- Risky updates: Upgrading PHP or applying security patches manually across a fleet risks broken deployments and data loss.
- No audit trail: Who changed what, when? Manual changes leave no record.
- Disaster recovery nightmare: If infrastructure burns down, rebuilding from memory or incomplete documentation wastes hours.
IaC solves these problems by making infrastructure definition explicit, version-controlled, and repeatable.
Core Benefits of Infrastructure as Code
Reproducibility
Run the same IaC configuration against any cloud provider (AWS, Google Cloud, Azure) and you get identical infrastructure. With Terraform, developers can provision identical environments with a single command, reducing human error and ensuring infrastructure uniformity. This means staging matches production exactly; dev environments mirror live behavior.
Version Control & Auditability
Infrastructure code lives in Git. Every change is tracked: who changed it, when, why (via commit messages), and it can be reviewed before merging. For compliance-heavy WordPress fleets handling e-commerce or sensitive data, this audit trail is essential. Rollback to a previous known-good infrastructure state with a single Git command.
Consistency Across Fleets
A single module definition applied to 500 WordPress servers guarantees they’re configured identically. Security hardening, PHP versions, Nginx optimization, database backups—all consistent. Commands executed via Ansible are idempotent, meaning they can be applied multiple times and will always result in the same outcome.
Fast Provisioning
Spinning up new WordPress infrastructure takes minutes instead of hours. Terraform can provision 10 EC2 instances, RDS database, security groups, load balancer, DNS records in parallel. For e-commerce fleets handling seasonal traffic spikes, this agility is a competitive advantage.
Fewer Configuration Drift Errors
Configuration drift—where actual infrastructure diverges from intended state—is a silent killer. One server missing a security patch; another running an outdated PHP version. IaC drift occurs when infrastructure resources differ from the configuration defined in code, invalidating the code as the single source of truth. Idempotent tools prevent drift by detecting and correcting deviations automatically.
Declarative vs. Imperative: Terraform vs. Ansible
Two dominant philosophies exist in IaC, each suited to different infrastructure tasks.
Declarative: Terraform
Terraform uses declarative configuration where you define the desired end state, and Terraform’s engine automatically determines the steps necessary to reach that state. Write once: “I want 5 EC2 instances, a load balancer, an RDS database in a VPC with specific security rules.” Terraform makes it so.
Strengths:
- Maintains state file—tracks what’s deployed and what’s not.
- Naturally supports multi-environment provisioning (dev, staging, prod).
- Terraform modules allow for reusable infrastructure components; breaking infrastructure into smaller reusable components reduces duplication.
- Immutable infrastructure: replace old resources rather than modify them in place (safer, more predictable).
- Excellent for day-0 provisioning (creating infrastructure from scratch).
Weakness: Less suited to sequential, step-by-step operational tasks like “upgrade PHP, then validate, then rollback on failure.”
Imperative: Ansible
Ansible takes a procedural approach where you define step-by-step instructions on how to achieve the desired result. Write playbooks: “Install Nginx, configure PHP-FPM, harden SSH, restart services.” Ansible executes in order.
Strengths:
- Agent-less: SSH to servers, no additional software to install.
- Excellent for day-1 configuration (post-provisioning software setup) and day-2 operations (patches, updates, ongoing management).
- Naturally idempotent: run playbooks repeatedly; unchanged servers skip unchanged tasks.
- Human-readable YAML syntax; lower learning curve than HCL.
- Can manage mutable infrastructure—patch servers in place rather than replacing them.
Weakness: No built-in state file; harder to track what’s deployed across large fleets.
Best Practice: Use Both
The most effective modern automation strategies use Terraform and Ansible together to achieve comprehensive infrastructure lifecycle management: Terraform for day 0 provisioning and Ansible for day 1 configuration and day 2 operations. Terraform provisions AWS resources; Ansible configures WordPress on those resources.
Managing Multiple WordPress Servers as Code
Consider Vilee’s real-world scenario: 520+ WordPress sites spread across regions. Three representative sites: US-based SaaS platform, EU e-commerce store, Southeast Asia marketplace.
Layer 1: Provision with Terraform
Define infrastructure in HCL:
# Terraform: variables.tf, main.tf
variable "site_count" { default = 3 }
variable "region" { type = string }
resource "aws_instance" "wordpress_server" {
count = var.site_count
instance_type = "t3.medium"
ami = data.aws_ami.ubuntu_22.id
tags = { Name = "wordpress-${count.index}" }
}
resource "aws_rds_instance" "wordpress_db" {
count = var.site_count
allocated_storage = 20
engine = "mysql"
instance_class = "db.t3.micro"
}
resource "aws_lb" "wordpress_alb" {
name = "wp-alb"
internal = false
}
Run terraform apply: instantly, AWS spins up 3 EC2 instances, 3 RDS databases, load balancer, security groups. Terraform stores state; future runs update only changed resources.
Layer 2: Configure with Ansible
Ansible is built for managing large server fleets; define the desired state once, and Ansible enforces it across every server in the fleet. Create an inventory of the 520 WordPress servers, then apply a playbook:
# Ansible: playbook.yml
---
- hosts: wordpress_servers
become: yes
tasks:
- name: Install LEMP stack
apt:
name: ["nginx", "php-fpm", "php-mysql", "mysql-client"]
state: present
- name: Configure PHP
template:
src: php.ini.j2
dest: /etc/php/8.2/fpm/php.ini
backup: yes
- name: Download WordPress
command: wp core download --allow-root
args:
chdir: /var/www/html
- name: Configure WordPress
command: wp config create --allow-root
args:
chdir: /var/www/html
- name: Restart Nginx
systemd:
name: nginx
state: restarted
Run ansible-playbook playbook.yml -i inventory.ini: all 520 servers configure in parallel (or in rolling batches). Change PHP version? Update the template, re-run playbook. Idempotency ensures servers already on that version skip that task.
Secrets Management in Infrastructure as Code
IaC code is version-controlled and shared. Database passwords, API keys, SSL certificates must never be hardcoded in code.
Best Practices
- AWS Secrets Manager: Store database passwords, API keys, SSL certs in Secrets Manager. Grant IAM permissions to instances that need them. Terraform references secrets at deploy time.
- HashiCorp Vault: Centralized secrets engine. Instances authenticate to Vault, receive temporary credentials on demand, credentials rotate automatically.
- Encrypted Variables: Ansible Vault encrypts sensitive variables in playbook files; decrypt at runtime with a password or key file.
- Automated Rotation: Implement policies to automatically rotate database passwords, API keys, and certificates, limiting the window of opportunity for attackers if a credential is compromised.
- Principle of Least Privilege: Configure IAM policies so each application or service accesses only the secrets it needs.
What NOT to Do
- Never commit plaintext secrets to Git (even private repos).
- Never hardcode credentials in Terraform .tfvars or Ansible group_vars.
- Never store credentials in Docker image layers.
- Don’t skip secret rotation—it’s automated if you set it up.
State Management & Terraform State Files
Terraform maintains a state file (terraform.tfstate) recording what’s deployed: EC2 instance IDs, RDS endpoints, security group rules. This state is the source of truth.
State Storage Best Practices
- Remote Backend: Store state in S3, not locally. Multiple engineers applying Terraform simultaneously without locking causes conflicts.
- State Locking: DynamoDB or Terraform Cloud prevents simultaneous writes; first apply acquires a lock, second blocks until first completes.
- Versioning: S3 versioning tracks state history; rollback to a prior state if disaster strikes.
- Encryption: Enable S3 encryption at rest and in transit; state files contain sensitive data (RDS passwords, private IPs).
- Access Control: Restrict who can read/write state via IAM. Only CI/CD pipelines and authorized engineers.
- Backup: Effective versioning and backup strategies are critical for maintaining integrity and availability; automatic versioning mechanisms help track changes to state files and enable easy rollback.
Modules & Reusable Infrastructure Code
Writing Terraform from scratch for each site is tedious. Modules package reusable infrastructure building blocks.
Example: WordPress Module
# terraform/modules/wordpress-site/main.tf
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
tags = { Name = var.site_name }
}
resource "aws_rds_instance" "db" {
allocated_storage = var.db_storage
engine = "mysql"
instance_class = var.db_instance_type
db_name = var.db_name
username = var.db_user
password = var.db_password # from Secrets Manager
}
resource "aws_security_group" "web" {
ingress { from_port = 80; to_port = 80; protocol = "tcp" }
ingress { from_port = 443; to_port = 443; protocol = "tcp" }
egress { from_port = 0; to_port = 0; protocol = "-1" }
}
Then use the module for each site:
# terraform/prod/main.tf
module "us_saas" {
source = "../modules/wordpress-site"
site_name = "us-saas"
instance_type = "t3.medium"
db_name = "wp_us_saas"
}
module "eu_ecommerce" {
source = "../modules/wordpress-site"
site_name = "eu-ecommerce"
instance_type = "t3.large"
db_name = "wp_eu_ecom"
}
module "apac_marketplace" {
source = "../modules/wordpress-site"
site_name = "apac-marketplace"
instance_type = "t3.xlarge"
db_name = "wp_apac_market"
}
Define once, reuse everywhere. Update the module (e.g., upgrade PHP version); all sites using it get the update with terraform apply.
Vilee LLC combines deep technical expertise in WordPress/WooCommerce development with AI-powered automation to operate 520+ profitable online businesses at scale.
Continuous Integration for Infrastructure
Treat infrastructure code like application code: test before deploying.
IaC Testing Pipeline
- Syntax Validation:
terraform validatechecks HCL syntax before apply. - Policy as Code: Tools like Sentinel (Terraform Cloud) enforce organizational policies (e.g., all RDS instances must be encrypted, all security groups must restrict SSH to VPN).
- Cost Estimation:
terraform planshows resource costs before apply; catch budget overruns early. - Security Scanning: GitHub Actions can trigger automated testing and validation of infrastructure changes before deployment.
- Staged Rollout: Merge Terraform to dev branch → CI validates and applies to dev environment → code review approved → merge to prod → CI applies to production.
Example GitHub Actions workflow:
# .github/workflows/terraform.yml
name: Terraform
on: [push, pull_request]
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: hashicorp/setup-terraform@v1
- run: terraform init
- run: terraform validate
- run: terraform plan -out=tfplan
- run: terraform apply tfplan
Idempotency: The IaC Superpower
A properly idempotent system can be run repeatedly without side effects. Run the same Ansible playbook 10 times; servers already in the desired state skip unchanged tasks.
Benefits:
- Recover from partial failures: playbook crashes mid-run? Re-run it; it picks up where it left off.
- Schedule maintenance safely: upgrade PHP on a 500-server fleet, re-run playbook each hour to catch drifted servers.
- On-board new engineers: run the full provisioning playbook for their dev environment; it’s idempotent, so running twice doesn’t break anything.
- Reduce support tickets: instead of manual fixes, “run this playbook” is the answer to 80% of operational issues.
IaC Configuration Drift & Detection
Even with IaC, drift happens: manual SSH changes, failed updates, cloud provider patches. Catch and prevent it.
Drift Detection
- Terraform Refresh:
terraform refreshqueries actual AWS state, updates local state file to match reality.terraform planthen shows drift. - Ansible Dry-Run:
ansible-playbook playbook.yml --checksimulates applying the playbook without actually changing anything; see what would change. - Regular Audits: Daily/weekly Terraform plan or Ansible check runs catch drift. Trigger alerts on detected drift.
- Immutable Infrastructure: Replace servers rather than patch. Drift is moot if servers live 30 days and are replaced, not modified in place.
Implementation Checklist for WordPress Fleets
| Phase | Task | Owner | Timeline |
|---|---|---|---|
| Week 1 | Set up Terraform and Ansible repos; version control | DevOps Lead | 2–3 days |
| Week 1 | Design VPC, subnets, security groups in Terraform | Cloud Architect | 2–3 days |
| Week 2 | Build EC2 + RDS Terraform modules; test locally with Terraform Cloud | DevOps Engineer | 3–5 days |
| Week 2–3 | Create Ansible playbooks for WordPress stack (Nginx, PHP, WP-CLI) | Systems Engineer | 5–7 days |
| Week 3 | Set up secrets (AWS Secrets Manager + IAM roles) | Security Engineer | 2–3 days |
| Week 3–4 | Build CI/CD pipeline (GitHub Actions or GitLab CI) | DevOps Engineer | 3–4 days |
| Week 4 | Test on staging: provision 5 sites, verify WordPress works | QA / DevOps | 2–3 days |
| Week 5 | Roll out to production; migrate 50 WordPress sites | DevOps Lead + Team | 5–7 days |
| Week 6+ | Monitor drift, optimize, scale to full fleet | On-call Engineer | Ongoing |
Common Gotchas & How to Avoid Them
- Terraform state in Git: Never commit
terraform.tfstate. Use remote backend (S3 + DynamoDB) from day one. - Secrets in code: Use AWS Secrets Manager, Vault, or encrypted Ansible Vault files. Never plaintext.
- Idempotency failures: Some tasks (e.g.,
ansible shell) are not idempotent by default. Use idempotent modules (file,copy,template) or addregister/whenconditionals. - Forgetting state locking: Two engineers run
terraform applysimultaneously; state file corrupts. Enable DynamoDB locking or Terraform Cloud. - Over-coupling modules: Avoid deeply nested module dependencies. Keep modules simple, focused, independent.
- Inadequate testing: Test Terraform + Ansible changes in a staging environment first. Use
terraform planandansible --check.
Why Vilee Chooses Infrastructure as Code
Operating 520+ WordPress sites globally demands automation. Manual provisioning doesn’t scale. IaC enables:
- Speed: Launch new sites in minutes, not hours.
- Consistency: Every site is configured identically, reducing support burden.
- Reliability: Automated deployments with built-in tests catch errors before production.
- Cost Control: Terraform plan shows costs before apply; scale down unused infrastructure instantly.
- Team Scaling: New engineers onboard by reading Terraform code + Ansible playbooks, not tribal knowledge or runbooks.
- Compliance: Version control provides audit trails; secrets encrypted and rotated automatically.
Next Steps: Getting Started
- Read: Familiarize yourself with Terraform HCL syntax and Ansible YAML playbooks. Set up Docker for WordPress development locally to test IaC changes risk-free.
- Start Small: Write Terraform to provision a single EC2 + RDS database. Use Ansible to install WordPress on it. Iterate.
- Version Control: Commit infrastructure code to Git. Use branches for features (e.g.,
feature/php-8.3-upgrade). Require code review before merging. - Automate Testing: Build a CI/CD pipeline that validates and tests IaC changes on every commit.
- Scale: Once single-site workflow is solid, package it into modules and replicate across 100, 500, 1000 sites.
- Monitor: Implement drift detection. Schedule regular Terraform plan / Ansible check runs to catch deviations.
For teams managing WordPress at scale, IaC is not optional—it’s the foundation of reliable, fast, cost-effective operations. Contact Vilee to discuss how Infrastructure as Code can transform your WordPress fleet.
FAQs
Can I use Terraform and Ansible together for WordPress?
Yes, and it’s best practice. Terraform handles day 0 provisioning (creating infrastructure) while Ansible handles day 1 configuration and day 2 operations (software deployment, updates, ongoing management). Terraform creates the servers; Ansible installs WordPress on them. This division of labor is powerful.
How do I handle secrets in Terraform and Ansible?
Never hardcode secrets. Use AWS Secrets Manager (Terraform can reference it), HashiCorp Vault, or Ansible Vault. Configure automated credential rotation to limit the window of opportunity for attackers if a credential is compromised. Grant access via IAM roles, not shared credentials.
What if my infrastructure drifts from code?
Use terraform refresh to sync state with reality, then terraform plan to see drift. For Ansible, run ansible-playbook --check to see what would change. Implement automated drift detection (daily Terraform plan runs, monitoring alerts on changes). Consider immutable infrastructure: replace drifted servers rather than patching them.
Frequently Asked Questions
Can I use Terraform and Ansible together for WordPress?
Yes, and it’s best practice. Terraform handles day 0 provisioning (creating infrastructure) while Ansible handles day 1 configuration and day 2 operations (software deployment, updates, ongoing management). Terraform creates the servers; Ansible installs WordPress on them. This division of labor is powerful.
How do I handle secrets in Terraform and Ansible?
Never hardcode secrets. Use AWS Secrets Manager (Terraform can reference it), HashiCorp Vault, or Ansible Vault. Configure automated credential rotation to limit the window of opportunity for attackers if a credential is compromised. Grant access via IAM roles, not shared credentials.
What if my infrastructure drifts from code?
Use terraform refresh to sync state with reality, then terraform plan to see drift. For Ansible, run ansible-playbook –check to see what would change. Implement automated drift detection (daily Terraform plan runs, monitoring alerts on changes). Consider immutable infrastructure: replace drifted servers rather than patching them.
