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

Vengala Vinay

Having 9+ 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 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Disaster Recovery 101: Architecting Auto-Failovers for Redis and PHP Deployments on OVH
  • How We Audited a High-Traffic WooCommerce Enterprise Stack on Google Cloud and Mitigated Race conditions during high-concurrency payment processing
  • Disaster Recovery 101: Architecting Auto-Failovers for Elasticsearch and Magento 2 Deployments on DigitalOcean
  • An Auditor’s Checklist for Securing WordPress Backends on OVH
  • Step-by-Step: Diagnosing Perl script high CPU throttling due to unoptimized regular expressions on AWS Servers

Copyright © 2026 · Vinay Vengala