• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » Infrastructure as Code: Provisioning Secure WordPress Clusters on Google Cloud Using Terraform

Infrastructure as Code: Provisioning Secure WordPress Clusters on Google Cloud Using Terraform

Terraform Project Structure and Provider Configuration

We’ll begin by establishing a robust Terraform project structure. This modular approach enhances maintainability and reusability. Our core configuration will reside in the main.tf file, defining the Google Cloud provider and essential resources. For security, we’ll leverage Google Cloud’s Identity and Access Management (IAM) for service account authentication.

First, ensure you have authenticated Terraform with Google Cloud. The recommended method is to create a dedicated service account with appropriate permissions (e.g., Compute Admin, Storage Admin, IAM User) and download its JSON key file. Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of this key file.

main.tf

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 4.0"
    }
  }
}

provider "google" {
  project = var.gcp_project_id
  region  = var.gcp_region
}

variable "gcp_project_id" {
  description = "The GCP project ID to deploy resources into."
  type        = string
}

variable "gcp_region" {
  description = "The GCP region to deploy resources into."
  type        = string
  default     = "us-central1"
}

variable "gcp_zone" {
  description = "The GCP zone to deploy resources into."
  type        = string
  default     = "us-central1-a"
}

variable "network_name" {
  description = "Name for the VPC network."
  type        = string
  default     = "wordpress-vpc"
}

variable "subnet_name" {
  description = "Name for the subnet."
  type        = string
  default     = "wordpress-subnet"
}

variable "subnet_cidr" {
  description = "CIDR block for the subnet."
  type        = string
  default     = "10.0.1.0/24"
}

variable "wordpress_instance_name" {
  description = "Name for the WordPress Compute Engine instance."
  type        = string
  default     = "wordpress-web"
}

variable "wordpress_machine_type" {
  description = "Machine type for the WordPress Compute Engine instance."
  type        = string
  default     = "e2-medium"
}

variable "wordpress_disk_size" {
  description = "Size of the boot disk for the WordPress instance in GB."
  type        = number
  default     = 20
}

variable "wordpress_image" {
  description = "The boot disk image for the WordPress instance."
  type        = string
  default     = "debian-cloud/debian-11"
}

variable "db_instance_name" {
  description = "Name for the Cloud SQL instance."
  type        = string
  default     = "wordpress-db"
}

variable "db_version" {
  description = "The database version for Cloud SQL."
  type        = string
  default     = "POSTGRES_13" # Or MYSQL_8_0
}

variable "db_tier" {
  description = "The machine type for the Cloud SQL instance."
  type        = string
  default     = "db-f1-micro"
}

variable "db_disk_size" {
  description = "Size of the data disk for the Cloud SQL instance in GB."
  type        = number
  default     = 10
}

variable "db_user" {
  description = "Username for the database."
  type        = string
  default     = "wp_user"
}

variable "db_password" {
  description = "Password for the database."
  type        = string
  sensitive   = true
}

variable "db_name" {
  description = "Name of the database."
  type        = string
  default     = "wordpress_db"
}

variable "firewall_rule_name" {
  description = "Name for the firewall rule."
  type        = string
  default     = "wordpress-allow-http-https"
}

variable "ssh_user" {
  description = "Username for SSH access to the WordPress instance."
  type        = string
  default     = "admin"
}

variable "ssh_public_key_path" {
  description = "Path to the SSH public key file for instance access."
  type        = string
}

output "wordpress_instance_ip" {
  description = "The external IP address of the WordPress instance."
  value       = google_compute_instance.wordpress.network_interface[0].access_config[0].nat_ip
}

output "db_instance_connection_name" {
  description = "The connection name of the Cloud SQL instance."
  value       = google_sql_database_instance.wordpress_db.connection_name
}

output "db_instance_private_ip" {
  description = "The private IP address of the Cloud SQL instance."
  value       = google_sql_database_instance.wordpress_db.private_ip_address
}

Networking and Security Group Configuration

A secure WordPress deployment necessitates a well-defined Virtual Private Cloud (VPC) network and appropriate firewall rules. We will create a custom VPC network and a subnet to isolate our WordPress resources. Subsequently, we’ll configure a firewall rule to allow inbound HTTP and HTTPS traffic to our WordPress instance.

VPC Network and Subnet

resource "google_compute_network" "wordpress_vpc" {
  name                    = var.network_name
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
}

resource "google_compute_subnetwork" "wordpress_subnet" {
  name          = var.subnet_name
  ip_cidr_range = var.subnet_cidr
  region        = var.gcp_region
  network       = google_compute_network.wordpress_vpc.id
}

Firewall Rule

resource "google_compute_firewall" "wordpress_firewall" {
  name    = var.firewall_rule_name
  network = google_compute_network.wordpress_vpc.name

  allow {
    protocol = "tcp"
    ports    = ["80", "443"]
  }

  # Allow SSH access from a specific IP range for management.
  # Consider using a more restrictive range or bastion host for production.
  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  source_ranges = ["0.0.0.0/0"] # WARNING: This allows SSH from anywhere. Restrict this in production.
  target_tags   = ["wordpress"] # Apply this tag to the WordPress instance
}

Security Note: The source_ranges = ["0.0.0.0/0"] for SSH is a significant security risk in production environments. It’s crucial to restrict this to known IP addresses or implement a bastion host for secure SSH access. For this example, we’ll use it for simplicity, but it must be hardened.

Cloud SQL Instance for WordPress Database

A managed database service like Google Cloud SQL is essential for a production-ready WordPress setup. It handles patching, backups, and high availability. We’ll provision a Cloud SQL instance, configure it with a specific version, and create a database and user for WordPress.

resource "google_sql_database_instance" "wordpress_db" {
  name             = var.db_instance_name
  region           = var.gcp_region
  database_version = var.db_version
  settings {
    tier = var.db_tier
    ip_configuration {
      ipv4_enabled    = true
      private_network = google_compute_network.wordpress_vpc.id
    }
    backup_configuration {
      enabled = true
      binary_log_enabled = (var.db_version == "MYSQL_8_0" || var.db_version == "MYSQL_5_7") # Required for point-in-time recovery for MySQL
    }
    # For higher availability, consider:
    # availability_type = "REGIONAL"
  }

  # Prevent accidental deletion of the database instance
  deletion_protection = true
}

resource "google_sql_database" "wordpress_db_name" {
  name     = var.db_name
  instance = google_sql_database_instance.wordpress_db.name
  charset  = "UTF8"
}

resource "google_sql_user" "wordpress_db_user" {
  name     = var.db_user
  instance = google_sql_database_instance.wordpress_db.name
  host     = "%" # Allows connection from any host within the authorized network
  password = var.db_password
}

Important: The private_network setting ensures the Cloud SQL instance is only accessible from within your VPC. This is a critical security measure. For MySQL, enabling binary_log_enabled is necessary for point-in-time recovery.

WordPress Compute Engine Instance

The heart of our WordPress deployment is a Compute Engine instance. We’ll configure it with a suitable machine type, boot disk, and importantly, a startup script to automate the installation and configuration of WordPress, Apache/Nginx, PHP, and the database connection.

Startup Script for WordPress Installation

#!/bin/bash

# Update package list and install necessary packages
sudo apt-get update -y
sudo apt-get install -y apache2 php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip unzip wget

# Download WordPress
cd /var/www/html
wget https://wordpress.org/latest.zip
unzip latest.zip
mv wordpress/* .
rm -rf wordpress latest.zip

# Set ownership and permissions for WordPress files
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html

# Configure WordPress wp-config.php
sudo cp wp-config-sample.php wp-config.php

# Replace database credentials in wp-config.php
# IMPORTANT: Ensure the DB_PASSWORD variable is securely passed or managed.
sudo sed -i "s/database_name_here/${DB_NAME}/" wp-config.php
sudo sed -i "s/username_here/${DB_USER}/" wp-config.php
sudo sed -i "s/password_here/${DB_PASSWORD}/" wp-config.php
sudo sed -i "s/localhost/${DB_HOST}/" wp-config.php # Use Cloud SQL Proxy or private IP

# Generate unique security keys and salts
curl -s https://api.wordpress.org/secret-key/1.1/salt/ >> wp-config.php

# Restart Apache
sudo systemctl restart apache2

# Install Cloud SQL Auth Proxy (for connecting to Cloud SQL)
# This requires the instance connection name to be passed.
# For simplicity, we'll assume direct private IP access is configured.
# If using Cloud SQL Auth Proxy, you'd need to download and run it as a service.

# Example for direct private IP connection (if configured in wp-config.php)
# Ensure DB_HOST is set to the private IP of the Cloud SQL instance.
# If using Cloud SQL Auth Proxy, DB_HOST would be '127.0.0.1:3306' (for MySQL) or similar.

echo "WordPress installation complete."

Compute Engine Instance Resource

resource "google_compute_instance" "wordpress" {
  name         = var.wordpress_instance_name
  machine_type = var.wordpress_machine_type
  zone         = var.gcp_zone
  tags         = ["wordpress"]

  boot_disk {
    initialize_params {
      image = var.wordpress_image
      size  = var.wordpress_disk_size
    }
  }

  network_interface {
    subnetwork = google_compute_subnetwork.wordpress_subnet.id
    access_config {
      // Ephemeral IP, remove for static IP
    }
  }

  metadata_startup_script = templatefile("${path.module}/scripts/startup.sh", {
    DB_NAME     = var.db_name
    DB_USER     = var.db_user
    DB_PASSWORD = var.db_password
    DB_HOST     = google_sql_database_instance.wordpress_db.private_ip_address # Use private IP for direct connection
  })

  # SSH Key configuration
  metadata {
    ssh-keys = "${var.ssh_user}:${file(var.ssh_public_key_path)}"
  }

  # Ensure the database is created before the instance starts up
  depends_on = [
    google_sql_database.wordpress_db_name,
    google_sql_user.wordpress_db_user
  ]
}

The metadata_startup_script uses templatefile to inject sensitive variables like database credentials and the Cloud SQL private IP address directly into the startup script. This avoids hardcoding them. The depends_on block ensures that the Cloud SQL resources are provisioned and ready before the Compute Engine instance attempts to start.

Deployment and Management

With the Terraform configuration in place, deploying your secure WordPress cluster is straightforward. Ensure you have a terraform.tfvars file or provide variables via the command line.

terraform.tfvars Example

gcp_project_id       = "your-gcp-project-id"
gcp_region           = "us-central1"
gcp_zone             = "us-central1-a"
db_password          = "your-strong-db-password"
ssh_public_key_path  = "~/.ssh/id_rsa.pub" # Path to your SSH public key
# Add any other variables you wish to override from defaults

Terraform Commands

# Initialize Terraform
terraform init

# Review the execution plan
terraform plan

# Apply the configuration to provision resources
terraform apply

# Destroy the resources when no longer needed
terraform destroy

After running terraform apply, Terraform will output the external IP address of your WordPress instance. You can then access your WordPress site by navigating to this IP address in your web browser. The database will be accessible via its private IP address from within the VPC, or through the Cloud SQL Auth Proxy if you choose to implement that for enhanced security and easier management.

Further Enhancements and Security Considerations

This setup provides a foundational secure WordPress cluster. For production environments, consider the following enhancements:

  • Load Balancing: Deploy multiple WordPress instances behind a Google Cloud Load Balancer for high availability and scalability.
  • Managed Instance Groups: Use Managed Instance Groups (MIGs) to automatically scale your WordPress instances based on load.
  • Static IP Address: Assign a static external IP address to your WordPress instance for a stable endpoint.
  • SSL/TLS: Configure SSL certificates for HTTPS. This can be managed at the load balancer level or on the instance itself.
  • Cloud SQL High Availability: Configure the Cloud SQL instance for regional availability.
  • Secrets Management: For production, avoid passing secrets directly in .tfvars. Use a secrets manager like Google Secret Manager or HashiCorp Vault.
  • SSH Access: Implement a bastion host or use Identity-Aware Proxy (IAP) for secure SSH access instead of opening port 22 to the internet.
  • Monitoring and Logging: Integrate with Google Cloud’s operations suite (formerly Stackdriver) for comprehensive monitoring and logging.
  • Content Delivery Network (CDN): Utilize Cloud CDN for caching static assets and improving performance.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala