• 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 DigitalOcean Using Terraform

Infrastructure as Code: Provisioning Secure PHP Clusters on DigitalOcean Using Terraform

Terraform Provider Configuration for DigitalOcean

To begin provisioning infrastructure on DigitalOcean using Terraform, we first need to configure the DigitalOcean provider. This involves specifying your API token and the region where your resources will be deployed. It’s crucial to manage your API token securely, ideally using environment variables rather than hardcoding it directly into your Terraform configuration files.

Create a file named main.tf in your Terraform project directory and add the following provider configuration:

terraform {
  required_providers {
    digitalocean = {
      source  = "digitalocean/digitalocean"
      version = "~> 2.0"
    }
  }
}

provider "digitalocean" {
  token = var.do_token
  # Alternatively, you can set the DIGITALOCEAN_TOKEN environment variable
  # token = env("DIGITALOCEAN_TOKEN")
}

variable "do_token" {
  description = "DigitalOcean API Token"
  type        = string
  sensitive   = true
}

variable "region" {
  description = "The DigitalOcean region to deploy resources in."
  type        = string
  default     = "nyc3"
}

In this configuration:

  • We declare the DigitalOcean provider and specify a version constraint.
  • The provider "digitalocean" block configures the connection. We’re using a variable var.do_token for the API token, which is marked as sensitive to prevent it from being displayed in Terraform output.
  • The region variable defaults to “nyc3” but can be overridden.

To use this, you’ll need to set the DO_TOKEN environment variable or pass the token during terraform apply. For local development, you can create a terraform.tfvars file (ensure it’s in your .gitignore):

do_token = "YOUR_DIGITALOCEAN_API_TOKEN"
region   = "nyc3"

Provisioning a Secure PHP Web Server Droplet

Now, let’s define a DigitalOcean Droplet that will host our PHP application. For security, we’ll configure SSH access using a key pair and set up a basic firewall. We’ll use a common Ubuntu image and a moderately sized Droplet.

Add the following resource block to your main.tf file:

resource "digitalocean_droplet" "php_web_server" {
  image    = "ubuntu-22-04-x64"
  name     = "php-web-server-01"
  region   = var.region
  size     = "s-2vcpu-4gb" # Adjust size as needed
  ssh_keys = [digitalocean_ssh_key.deployer.id]

  monitoring = true
  tags       = ["php-app", "webserver", "production"]

  connection {
    type        = "ssh"
    user        = "root" # Or your preferred user
    private_key = file("~/.ssh/id_rsa") # Path to your private SSH key
    timeout     = "5m"
  }

  provisioner "remote-exec" {
    inline = [
      "apt-get update -y",
      "apt-get upgrade -y",
      "apt-get install -y nginx php-fpm php-mysql git curl", # Basic PHP stack
      "ufw allow 'Nginx Full'",
      "ufw allow OpenSSH",
      "ufw --force enable",
      "systemctl enable nginx",
      "systemctl start nginx"
    ]
  }
}

resource "digitalocean_ssh_key" "deployer" {
  name       = "deployer-key"
  public_key = file("~/.ssh/id_rsa.pub") # Path to your public SSH key
}

output "php_web_server_ip" {
  description = "The public IP address of the PHP web server."
  value       = digitalocean_droplet.php_web_server.ipv4_address
}

Explanation of the Droplet resource:

  • image: Specifies the operating system image.
  • name: A unique name for the Droplet.
  • region: Uses the variable defined earlier.
  • size: The Droplet plan. Adjust based on your application’s needs.
  • ssh_keys: Links the Droplet to an SSH key managed by DigitalOcean. We define this key in the digitalocean_ssh_key.deployer resource.
  • monitoring: Enables DigitalOcean’s infrastructure monitoring.
  • tags: Useful for organizing and filtering resources.
  • connection block: Configures how Terraform connects to the Droplet for remote execution. Ensure the private_key path is correct.
  • provisioner "remote-exec": Executes commands on the Droplet after it’s created. This installs Nginx, PHP-FPM, and essential PHP extensions, and configures the UFW firewall.
  • digitalocean_ssh_key resource: Uploads your public SSH key to DigitalOcean, allowing passwordless SSH access.
  • output "php_web_server_ip": Exports the public IP address of the created Droplet, making it easy to access after provisioning.

Securing the Droplet with a Firewall and SSH Configuration

While the remote-exec provisioner installs and enables UFW (Uncomplicated Firewall), a more robust approach for production environments involves using a dedicated firewall resource or a more sophisticated configuration management tool. However, for a basic secure setup, the UFW commands are a good starting point. We’ve allowed Nginx Full (ports 80 and 443) and SSH (port 22).

For enhanced SSH security, consider the following:

  • Disable root login: After initial setup, create a non-root user and disable direct root SSH login in /etc/ssh/sshd_config.
  • Use key-based authentication only: Set PasswordAuthentication no in /etc/ssh/sshd_config.
  • Change default SSH port: While not a foolproof security measure, changing the default port (22) can reduce automated scan attempts.
  • Implement Fail2ban: Install and configure Fail2ban to protect against brute-force attacks.

These advanced SSH configurations are typically managed post-provisioning or through more advanced configuration management tools like Ansible, Chef, or Puppet, which can be integrated with Terraform.

Deploying a PHP Application with Terraform

To deploy your PHP application code, you can leverage Terraform’s file provisioner or a remote-exec provisioner to clone from a Git repository. For simplicity and demonstration, we’ll use remote-exec to clone a sample application.

First, ensure your PHP application is hosted in a Git repository (e.g., GitHub, GitLab). Let’s assume your repository is at [email protected]:your-username/your-php-app.git.

Modify the digitalocean_droplet resource to include a new provisioner:

resource "digitalocean_droplet" "php_web_server" {
  # ... (previous configuration) ...

  connection {
    type        = "ssh"
    user        = "root"
    private_key = file("~/.ssh/id_rsa")
    timeout     = "5m"
  }

  provisioner "remote-exec" {
    inline = [
      "apt-get update -y",
      "apt-get upgrade -y",
      "apt-get install -y nginx php-fpm php-mysql git curl",
      "ufw allow 'Nginx Full'",
      "ufw allow OpenSSH",
      "ufw --force enable",
      "systemctl enable nginx",
      "systemctl start nginx",
      # Deploy PHP application
      "rm -rf /var/www/html/*", # Clear default Nginx content
      "git clone [email protected]:your-username/your-php-app.git /var/www/html", # Clone your app
      "chown -R www-data:www-data /var/www/html", # Set correct ownership
      "chmod -R 755 /var/www/html" # Set appropriate permissions
    ]
  }
}

Important Considerations for Deployment:

  • SSH Keys for Git: For private Git repositories, you’ll need to ensure the SSH key used by Terraform (~/.ssh/id_rsa) has access to your Git provider. This might involve adding the public key to your Git hosting service or using a dedicated deployment key.
  • Database Configuration: This example assumes a simple deployment. For applications requiring a database, you would provision a DigitalOcean Managed Database or a separate database Droplet and configure your PHP application’s connection strings accordingly. This often involves passing database credentials as sensitive variables.
  • Environment Variables: Sensitive configuration like database credentials or API keys should be managed via environment variables on the server, not hardcoded in the application code. You can set these using another remote-exec provisioner or a configuration management tool.
  • Nginx Configuration: The default Nginx configuration might not be optimal for your PHP application. You’ll likely need to create a custom Nginx site configuration file (e.g., /etc/nginx/sites-available/your-app) and symlink it to /etc/nginx/sites-enabled/. This can also be done via remote-exec or by using Terraform’s template_file data source to generate the Nginx config.

Running Terraform and Verifying the Deployment

Once your main.tf file is complete, you can provision your infrastructure:

  • Initialize Terraform:
terraform init

This command downloads the DigitalOcean provider plugin.

  • Review the Execution Plan:
terraform plan

This shows you what Terraform will create, modify, or destroy.

  • Apply the Configuration:
terraform apply

Terraform will prompt you to confirm the changes. Type yes to proceed.

After the apply command completes, Terraform will output the public IP address of your web server:

Outputs:

php_web_server_ip = "YOUR_DROPLET_PUBLIC_IP"

You can then access your PHP application by navigating to this IP address in your web browser. Verify that Nginx is serving your application and that the firewall rules are active by attempting to access disallowed ports.

Next Steps and Advanced Considerations

This setup provides a foundational secure PHP cluster. For production readiness, consider:

  • Load Balancing: Deploy multiple web servers and use a DigitalOcean Load Balancer for high availability and scalability.
  • Database Management: Utilize DigitalOcean Managed Databases for a robust and managed database solution.
  • CI/CD Integration: Automate deployments using CI/CD pipelines (e.g., GitLab CI, GitHub Actions) that trigger Terraform and application deployments.
  • Configuration Management: For complex setups, integrate tools like Ansible or Chef to manage server configurations more declaratively and idempotently.
  • Monitoring and Alerting: Set up comprehensive monitoring for your Droplets and applications, integrating with services like Prometheus, Grafana, or Datadog.
  • Secrets Management: Use a dedicated secrets management solution (e.g., HashiCorp Vault, AWS Secrets Manager) instead of relying solely on environment variables or Terraform variables for highly sensitive data.

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

  • Step-by-Step: Diagnosing indexing lock conflicts and high CPU during bulk stock updates on DigitalOcean Servers
  • How to Debug and Fix memory leaks and socket exhaustion in daemon processes in Modern C++ Applications
  • Infrastructure as Code: Provisioning Secure PHP Clusters on DigitalOcean Using Terraform
  • Fixing Slow Largest Contentful Paint (LCP) caused by unoptimized database queries in Legacy Laravel Codebases Without Breaking API Contracts
  • An Auditor’s Checklist for Securing Laravel Backends on Google Cloud

Copyright © 2026 · Vinay Vengala