• 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 PHP Clusters on Google Cloud Using Terraform

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

Terraform Provider Configuration for Google Cloud

To begin provisioning resources on Google Cloud Platform (GCP) using Terraform, we need to configure the Google Cloud provider. This involves specifying the project ID and the region where our infrastructure will reside. For enhanced security and manageability, we’ll also define a service account with the necessary permissions. This service account should be created beforehand with roles like ‘Compute Admin’ and ‘Service Account User’.

Create a file named main.tf and add the following configuration. Replace your-gcp-project-id with your actual GCP project ID and your-gcp-region with your desired region (e.g., us-central1).

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

provider "google" {
  project = "your-gcp-project-id"
  region  = "your-gcp-region"
}

# It's highly recommended to use a dedicated service account for Terraform.
# Ensure this service account has the necessary roles (e.g., Compute Admin, Service Account User).
# You can authenticate Terraform by setting the GOOGLE_APPLICATION_CREDENTIALS environment variable
# to the path of your service account key file.
# Example: export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-key.json"

VPC Network and Subnet Configuration

A robust network infrastructure is the foundation of any secure deployment. We’ll define a custom Virtual Private Cloud (VPC) network and a subnet within it. This provides better control over network traffic and IP addressing. We’ll also configure a firewall rule to allow SSH access (port 22) from a specific IP range for administrative purposes. For production, consider restricting this further or using IAP (Identity-Aware Proxy).

resource "google_compute_network" "vpc_network" {
  name                    = "php-cluster-vpc"
  auto_create_subnetworks = false
  routing_mode            = "REGIONAL"
}

resource "google_compute_subnetwork" "subnet" {
  name          = "php-cluster-subnet"
  ip_cidr_range = "10.0.1.0/24"
  region        = var.gcp_region # Assuming var.gcp_region is defined or hardcoded
  network       = google_compute_network.vpc_network.id
}

resource "google_compute_firewall" "ssh_firewall" {
  name    = "allow-ssh"
  network = google_compute_network.vpc_network.name

  allow {
    protocol = "tcp"
    ports    = ["22"]
  }

  # Restrict source_ranges to your management IP or VPN subnet for security.
  # For demonstration, using a broad range, but this should be tightened.
  source_ranges = ["0.0.0.0/0"] # !! PRODUCTION: Restrict this to your specific IP/range !!

  target_tags = ["ssh-enabled"] # Apply this tag to instances that should allow SSH
}

# Define a variable for region if not hardcoded in provider block
variable "gcp_region" {
  description = "The GCP region to deploy resources in."
  type        = string
  default     = "us-central1" # Example default
}

Managed Instance Group (MIG) for PHP Application Servers

To ensure high availability and scalability for our PHP application, we’ll deploy a Managed Instance Group (MIG). This group will manage a set of identical Compute Engine instances. We’ll use a custom machine image that has PHP, a web server (like Nginx or Apache), and our application code pre-installed. Auto-scaling will be configured based on CPU utilization.

First, let’s define the instance template. This template specifies the machine type, boot disk image, network interfaces, and startup script for each instance in the MIG. The startup script is crucial for bootstrapping the application environment if not fully baked into the image.

resource "google_compute_instance_template" "php_app_template" {
  name_prefix  = "php-app-template-"
  machine_type = "e2-medium" # Choose an appropriate machine type
  tags         = ["http-server", "ssh-enabled"]

  disk {
    source_image = "debian-cloud/debian-11" # Replace with your custom PHP image if available
    auto_delete  = true
    boot         = true
  }

  network_interface {
    subnetwork = google_compute_subnetwork.subnet.id
    # Access config for a public IP. For internal-only access, remove this.
    access_config {
      // Ephemeral IP
    }
  }

  # Example startup script to install Nginx and PHP if not in image
  # In a production scenario, a pre-built custom image is preferred for faster boot times
  # and more consistent deployments.
  metadata_startup_script = <<-EOT
    #!/bin/bash
    apt-get update -y
    apt-get install -y nginx php php-fpm php-mysql # Add other PHP extensions as needed

    # Configure Nginx to serve your PHP application
    # This is a simplified example. You'll need to adapt it to your app's structure.
    cat < /etc/nginx/sites-available/default
    server {
        listen 80 default_server;
        root /var/www/html; # Your application's web root
        index index.php index.html index.htm;

        location / {
            try_files \$uri \$uri/ /index.php?\$query_string;
        }

        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust PHP version if necessary
        }
    }
    EOF

    systemctl restart nginx
    systemctl enable nginx

    # Deploy your application code here (e.g., via git clone, gsutil cp)
    # Example:
    # git clone https://your-repo.com/your-app.git /var/www/html
    # chown -R www-data:www-data /var/www/html
  EOT

  lifecycle {
    create_before_destroy = true
  }
}

resource "google_compute_instance_group_manager" "php_app_mig" {
  name               = "php-app-mig"
  base_instance_name = "php-app"
  zone               = "us-central1-a" # Should match a zone within your region
  target_size        = 2 # Initial number of instances

  version {
    instance_template = google_compute_instance_template.php_app_template.id
    name              = "primary"
  }

  # Auto-scaling configuration
  auto_healing_policies {
    health_check = google_compute_health_check.php_health_check.id
    initial_delay_sec = 300
  }

  update_policy {
    type = "PROACTIVE"
    minimal_action = "REPLACE"
  }

  # Auto-scaling based on CPU utilization
  autoscaling_policy {
    max_num_replicas = 10
    min_num_replicas = 2
    cooldown_period_sec = 60

    cpu_utilization {
      target = 0.6 # Target 60% CPU utilization
    }
  }
}

# Health check for the MIG
resource "google_compute_health_check" "php_health_check" {
  name                = "php-app-health-check"
  check_interval_sec  = 5
  timeout_sec         = 5
  healthy_threshold   = 2
  unhealthy_threshold = 2

  http_health_check {
    port         = 80
    request_path = "/" # Adjust to your application's health check endpoint
  }
}

Load Balancer for Traffic Distribution

To distribute incoming traffic across the PHP application instances and provide a single point of access, we’ll set up a Google Cloud Load Balancer. We’ll use a Global External HTTP(S) Load Balancer, which is suitable for web applications. This involves creating a backend service that points to our MIG, a URL map, and a target proxy.

# Forwarding rule for the load balancer
resource "google_compute_forwarding_rule" "http_forwarding_rule" {
  name                  = "php-app-http-forwarding-rule"
  ip_protocol           = "TCP"
  load_balancing_scheme = "EXTERNAL"
  port_range            = "80"
  target                = google_compute_target_http_proxy.http_proxy.id
  ip_address            = "0.0.0.0" # Any IP address
}

# Target HTTP proxy
resource "google_compute_target_http_proxy" "http_proxy" {
  name    = "php-app-http-proxy"
  url_map = google_compute_url_map.url_map.id
}

# URL map
resource "google_compute_url_map" "url_map" {
  name            = "php-app-url-map"
  default_service = google_compute_backend_service.php_backend_service.id
}

# Backend service
resource "google_compute_backend_service" "php_backend_service" {
  name                  = "php-app-backend-service"
  protocol              = "HTTP"
  port_name             = "http"
  timeout_sec           = 10
  enable_cdn            = false
  load_balancing_scheme = "EXTERNAL"

  backend {
    group = google_compute_instance_group_manager.php_app_mig.instance_group
  }

  health_checks = [google_compute_health_check.php_health_check.id]
}

# Output the load balancer IP address
output "load_balancer_ip" {
  description = "The IP address of the HTTP load balancer."
  value       = google_compute_forwarding_rule.http_forwarding_rule.ip_address
}

Database Provisioning (e.g., Cloud SQL for MySQL)

A secure PHP application typically requires a database. For this example, we’ll provision a Cloud SQL instance for MySQL. It’s crucial to configure this securely, including setting strong passwords, enabling private IP, and restricting network access.

resource "google_sql_database_instance" "php_db" {
  name             = "php-app-db"
  region           = var.gcp_region
  database_version = "MYSQL_8_0"
  project          = "your-gcp-project-id" # Ensure this is set

  settings {
    tier = "db-f1-micro" # Choose an appropriate tier
    ip_configuration {
      ipv4_enabled    = false # Disable public IP for security
      private_network = google_compute_network.vpc_network.id
    }
    backup_configuration {
      enabled = true
    }
    # Consider enabling point-in-time recovery for production
    # point_in_time_recovery_enabled = true
  }

  # Prevent accidental deletion of the database
  deletion_protection = true
}

resource "google_sql_database" "app_db" {
  name     = "app_database"
  instance = google_sql_database_instance.php_db.name
  charset  = "utf8mb4"
  collation = "utf8mb4_unicode_ci"
}

resource "google_sql_user" "app_user" {
  name     = "app_user"
  instance = google_sql_database_instance.php_db.name
  host     = "%" # Restrict this to specific IPs or localhost if possible
  password = random_password.db_password.result
}

resource "random_password" "db_password" {
  length           = 16
  special          = true
  override_special = "_%@"
}

# Output the database connection name and user for application configuration
output "db_connection_name" {
  description = "The connection name of the Cloud SQL instance."
  value       = google_sql_database_instance.php_db.connection_name
}

output "db_user" {
  description = "The database username."
  value       = google_sql_user.app_user.name
}

output "db_password" {
  description = "The database password."
  value       = random_password.db_password.result
  sensitive   = true # Mark as sensitive to prevent accidental logging
}

Securing the Deployment

Security is paramount. Beyond the network configurations and private IP for the database, consider these additional measures:

  • Secrets Management: Use GCP Secret Manager or HashiCorp Vault to store database credentials, API keys, and other sensitive information. Inject these secrets into your application environment securely, rather than hardcoding them or storing them in Terraform state.
  • IAM Roles: Apply the principle of least privilege for the Terraform service account and any service accounts used by your Compute Engine instances.
  • Firewall Rules: Continuously review and tighten firewall rules. For example, instead of allowing SSH from 0.0.0.0/0, use a bastion host or GCP’s Identity-Aware Proxy (IAP) for secure SSH access.
  • Instance Images: Use hardened, minimal OS images. Regularly patch and update your custom images to address security vulnerabilities.
  • Application Security: Implement standard PHP security practices such as input validation, parameterized queries to prevent SQL injection, and secure session management.
  • HTTPS: For production, configure the load balancer with an SSL certificate (e.g., Google-managed SSL certificates) to enable HTTPS.

Deployment Workflow

Once you have your Terraform configuration files (main.tf, variables.tf, etc.) in place:

  • Initialize Terraform: Run terraform init in your project directory. This downloads the necessary provider plugins.
  • Review the Plan: Execute terraform plan. This command shows you exactly what Terraform will create, modify, or destroy in your GCP environment. Carefully review this output.
  • Apply the Configuration: Run terraform apply. Terraform will prompt you to confirm the changes before provisioning the resources.
  • Destroy Resources (when needed): To tear down the entire infrastructure, use terraform destroy.

This comprehensive Terraform setup provides a secure, scalable, and automated way to provision your PHP application clusters on Google Cloud. Remember to adapt the configurations, especially security settings like IP ranges and instance types, to your specific production requirements.

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

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store
  • How to refactor legacy event ticket registers queries using modern WP_Query and custom Transient caching
  • Step-by-Step Guide: Offloading high-frequency member profile directories metadata writes to a Redis KV store

Categories

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

Recent Posts

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (726)
  • Debugging & Troubleshooting (662)
  • Security & Compliance (647)
  • SEO & Growth (492)

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