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

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

Terraform Project Structure and Provider Configuration

We’ll begin by establishing a robust Terraform project structure. This ensures maintainability and scalability for our DigitalOcean infrastructure. The core of our setup involves configuring the DigitalOcean provider, specifying API tokens, and defining region preferences. For security, it’s paramount to manage sensitive credentials like API tokens using environment variables or a dedicated secrets management system, rather than hardcoding them directly into your Terraform configuration files.

Create a directory for your Terraform project, for instance, shopify-cluster-tf. Inside this directory, create the following files:

  • main.tf: The primary configuration file.
  • variables.tf: Defines input variables for customization.
  • outputs.tf: Specifies output values from the deployment.
  • providers.tf: Configures the DigitalOcean provider.

providers.tf

This file declares the DigitalOcean provider and how Terraform will authenticate. Ensure the DIGITALOCEAN_TOKEN environment variable is set before running Terraform commands.

# providers.tf

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

provider "digitalocean" {
  token = var.do_token
}

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

variable "do_region" {
  description = "DigitalOcean region for resources"
  type        = string
  default     = "nyc3"
}

output "do_region" {
  description = "The DigitalOcean region used for deployment."
  value       = var.do_region
}

Defining VPC and Security Groups for Network Isolation

A Virtual Private Cloud (VPC) is essential for segmenting your network and controlling traffic flow. We’ll create a dedicated VPC for our Shopify cluster. Alongside the VPC, we’ll define security groups to act as virtual firewalls, allowing only necessary inbound and outbound traffic. This is a critical step in securing your Shopify deployment.

main.tf – VPC and Security Group Resources

# main.tf

resource "digitalocean_vpc" "shopify_vpc" {
  name     = "shopify-cluster-vpc"
  region   = var.do_region
  ip_range = "10.10.0.0/16" # Example private IP range
}

resource "digitalocean_droplet_firewall" "shopify_firewall" {
  name = "shopify-cluster-firewall"

  # Allow SSH access from anywhere (consider restricting this in production)
  inbound_rule {
    protocol    = "tcp"
    ports       = "22"
    sources {
      addresses = ["0.0.0.0/0"]
    }
  }

  # Allow HTTP and HTTPS for Shopify storefront traffic
  inbound_rule {
    protocol    = "tcp"
    ports       = "80"
    sources {
      addresses = ["0.0.0.0/0"]
    }
  }
  inbound_rule {
    protocol    = "tcp"
    ports       = "443"
    sources {
      addresses = ["0.0.0.0/0"]
    }
  }

  # Allow internal communication within the VPC (e.g., between web servers and database)
  inbound_rule {
    protocol    = "tcp"
    ports       = "0-65535" # Allow all TCP ports for internal communication
    sources {
      droplet_ids = [digitalocean_droplet.web_server.id, digitalocean_droplet.db_server.id] # Example, adjust as needed
    }
  }
  inbound_rule {
    protocol    = "udp"
    ports       = "0-65535" # Allow all UDP ports for internal communication
    sources {
      droplet_ids = [digitalocean_droplet.web_server.id, digitalocean_droplet.db_server.id] # Example, adjust as needed
    }
  }

  # Allow all outbound traffic (consider restricting this for enhanced security)
  outbound_rule {
    protocol    = "tcp"
    ports       = "0-65535"
    destinations {
      addresses = ["0.0.0.0/0"]
    }
  }
  outbound_rule {
    protocol    = "udp"
    ports       = "0-65535"
    destinations {
      addresses = ["0.0.0.0/0"]
    }
  }
  outbound_rule {
    protocol    = "icmp"
    destinations {
      addresses = ["0.0.0.0/0"]
    }
  }

  # Associate firewall with the VPC
  vpc_ids = [digitalocean_vpc.shopify_vpc.id]
}

# Placeholder for Droplet resources, will be defined in the next section
resource "digitalocean_droplet" "web_server" {}
resource "digitalocean_droplet" "db_server" {}

Note: In a production environment, you should significantly restrict SSH access to specific IP ranges or bastion hosts. Similarly, outbound rules should be as granular as possible.

Provisioning Web Servers and Database Instances

Now, let’s define the Droplets that will host our Shopify application and its database. We’ll configure them with appropriate SSH keys for secure access, assign them to our newly created VPC, and attach the security firewall. For a production Shopify setup, you’d typically have multiple web servers for high availability and a managed database service or a dedicated, highly available database Droplet.

main.tf – Droplet Resources

# main.tf (continued)

variable "ssh_key_fingerprint" {
  description = "Fingerprint of the SSH key to be added to Droplets"
  type        = string
  sensitive   = true
}

variable "droplet_image" {
  description = "The base image for the Droplets (e.g., Ubuntu 22.04)"
  type        = string
  default     = "ubuntu-22-04-x64"
}

variable "droplet_size" {
  description = "The size slug for the Droplets (e.g., s-2vcpu-4gb)"
  type        = string
  default     = "s-2vcpu-4gb"
}

resource "digitalocean_ssh_key" "deploy_key" {
  name       = "shopify-deploy-key"
  public_key = file("~/.ssh/id_rsa.pub") # Ensure this path is correct or use a variable
}

resource "digitalocean_droplet" "web_server" {
  name     = "shopify-web-01"
  region   = var.do_region
  size     = var.droplet_size
  image    = var.droplet_image
  vpc_uuid = digitalocean_vpc.shopify_vpc.id
  ssh_keys = [digitalocean_ssh_key.deploy_key.id]

  monitoring = true
  tags       = ["shopify", "web", "production"]

  connection {
    type        = "ssh"
    user        = "root" # Or your preferred user
    private_key = file("~/.ssh/id_rsa") # Ensure this path is correct or use a variable
    host        = self.ipv4_address
    timeout     = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "apt-get update -y",
      "apt-get install -y nginx", # Example: Install Nginx
      "systemctl enable nginx",
      "systemctl start nginx",
      # Add commands here to configure your Shopify application, e.g.,
      # cloning from Git, setting up environment variables, installing dependencies.
      # Example:
      # "apt-get install -y git",
      # "git clone https://github.com/your-shopify-app/your-app.git /var/www/html",
      # "cd /var/www/html && composer install --no-dev",
      # "cp .env.example .env",
      # "sed -i 's/DB_HOST=.*/DB_HOST=your_db_host/' .env", # Example env var update
      # "php artisan key:generate",
      # "php artisan migrate --force"
    ]
  }
}

resource "digitalocean_droplet" "db_server" {
  name     = "shopify-db-01"
  region   = var.do_region
  size     = "s-4vcpu-8gb" # Larger size for database
  image    = var.droplet_image
  vpc_uuid = digitalocean_vpc.shopify_vpc.id
  ssh_keys = [digitalocean_ssh_key.deploy_key.id]

  monitoring = true
  tags       = ["shopify", "database", "production"]

  connection {
    type        = "ssh"
    user        = "root" # Or your preferred user
    private_key = file("~/.ssh/id_rsa") # Ensure this path is correct or use a variable
    host        = self.ipv4_address
    timeout     = "2m"
  }

  provisioner "remote-exec" {
    inline = [
      "apt-get update -y",
      "apt-get install -y mysql-server", # Example: Install MySQL
      "systemctl enable mysql",
      "systemctl start mysql",
      # Add commands here to secure your MySQL installation and configure it for Shopify.
      # This might include creating users, databases, and setting up replication.
      # Example:
      # "mysql -e \"CREATE DATABASE shopify_db;\"",
      # "mysql -e \"CREATE USER 'shopify_user'@'%' IDENTIFIED BY 'your_secure_password';\"",
      # "mysql -e \"GRANT ALL PRIVILEGES ON shopify_db.* TO 'shopify_user'@'%';\"",
      # "mysql -e \"FLUSH PRIVILEGES;\"",
      # "sed -i 's/bind-address.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf", # Allow connections from VPC
      # "systemctl restart mysql"
    ]
  }
}

Important Considerations:

  • SSH Keys: Ensure your ~/.ssh/id_rsa (private key) and ~/.ssh/id_rsa.pub (public key) exist and are correctly referenced. For production, use dedicated SSH keys and manage them securely.
  • Database Security: The database provisioning commands are illustrative. For a production Shopify store, you must implement robust database security measures, including strong passwords, restricted user privileges, and potentially encryption at rest. Consider using DigitalOcean’s Managed Databases for a more secure and managed solution.
  • Application Deployment: The remote-exec provisioner is suitable for initial setup. For continuous deployment, integrate with CI/CD pipelines that handle application code updates.
  • High Availability: For a production Shopify cluster, you’ll need multiple web servers behind a load balancer and a highly available database setup (e.g., replication, managed database).

Configuring Load Balancing for High Availability

To ensure your Shopify store remains accessible even if a web server fails, a load balancer is crucial. DigitalOcean Load Balancers distribute incoming traffic across multiple Droplets. We’ll configure a load balancer to direct traffic to our web servers.

main.tf – Load Balancer Resource

# main.tf (continued)

resource "digitalocean_loadbalancer" "shopify_lb" {
  name     = "shopify-lb"
  region   = var.do_region
  vpc_uuid = digitalocean_vpc.shopify_vpc.id

  # Health check to ensure traffic is only sent to healthy Droplets
  healthcheck {
    port     = 80
    protocol = "http"
    path     = "/" # Or a specific health check endpoint for your app
  }

  # Forwarding rules for HTTP and HTTPS
  forwarding_rule {
    entry_protocol    = "http"
    entry_port        = 80
    target_protocol   = "http"
    target_port       = 80
    target_droplet_ids = [digitalocean_droplet.web_server.id] # Add more web servers here
  }

  forwarding_rule {
    entry_protocol    = "https"
    entry_port        = 443
    target_protocol   = "https"
    target_port       = 443
    target_droplet_ids = [digitalocean_droplet.web_server.id] # Add more web servers here
  }

  # Enable sticky sessions if your application requires it (e.g., for session state)
  # sticky_sessions {
  #   type = "cookies"
  # }

  tags = ["shopify", "loadbalancer", "production"]
}

# Update the web server resource to include the load balancer's IP in its configuration
# This is a simplified example; in a real scenario, you'd configure your web server
# to be aware of the load balancer and potentially handle SSL termination.
resource "digitalocean_droplet" "web_server" {
  # ... (previous configuration) ...

  provisioner "remote-exec" {
    inline = [
      "apt-get update -y",
      "apt-get install -y nginx",
      "systemctl enable nginx",
      "systemctl start nginx",
      # Example: Configure Nginx to proxy pass to the load balancer (if SSL termination is on LB)
      # Or configure it to listen on the VPC IP and let the LB handle external traffic.
      # For SSL termination on the LB, your web servers might not need direct public IPs.
      # If SSL is terminated on the web servers, you'd need to configure certificates.
      # Example for proxying to LB (if LB handles SSL):
      # "echo 'server { listen 80; server_name your-domain.com; location / { proxy_pass http://<LOAD_BALANCER_IP>; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }' > /etc/nginx/sites-available/shopify",
      # "ln -sf /etc/nginx/sites-available/shopify /etc/nginx/sites-enabled/",
      # "nginx -s reload"
    ]
  }
}

Note: The target_droplet_ids in the forwarding rules should dynamically include all your web server Droplets. If you have multiple web servers, you’ll need to manage this list. For SSL termination, you can either configure it on the load balancer itself (recommended for simplicity) or on each web server.

Outputting Key Information

Finally, define outputs to easily retrieve important information about your deployed infrastructure, such as the load balancer’s IP address and the VPC ID. This is invaluable for post-deployment management and integration with other systems.

outputs.tf

# outputs.tf

output "shopify_vpc_id" {
  description = "The ID of the created VPC for the Shopify cluster."
  value       = digitalocean_vpc.shopify_vpc.id
}

output "shopify_loadbalancer_ip" {
  description = "The public IP address of the Shopify load balancer."
  value       = digitalocean_loadbalancer.shopify_lb.ip
}

output "shopify_web_server_private_ip" {
  description = "The private IP address of the primary Shopify web server."
  value       = digitalocean_droplet.web_server.ipv4_address_private
}

output "shopify_db_server_private_ip" {
  description = "The private IP address of the Shopify database server."
  value       = digitalocean_droplet.db_server.ipv4_address_private
}

Deployment Workflow

With the Terraform configuration in place, the deployment process is straightforward:

  1. Initialize Terraform: Navigate to your project directory in the terminal and run:
    terraform init
  2. Set Environment Variables: Ensure your DigitalOcean API token is set.
    export DIGITALOCEAN_TOKEN="your_do_api_token"
  3. Review the Plan: Before applying any changes, review the execution plan to understand what Terraform will create, modify, or destroy.
    terraform plan -var="do_token=your_do_api_token" -var="ssh_key_fingerprint=your_ssh_key_fingerprint"

    Replace your_ssh_key_fingerprint with the actual fingerprint of your SSH key. You can find this by running ssh-keygen -lf ~/.ssh/id_rsa.pub.

  4. Apply the Configuration: If the plan looks correct, apply the changes to provision your infrastructure.
    terraform apply -var="do_token=your_do_api_token" -var="ssh_key_fingerprint=your_ssh_key_fingerprint"
  5. Destroy Resources (When Needed): To tear down the entire infrastructure, use the destroy command.
    terraform destroy -var="do_token=your_do_api_token" -var="ssh_key_fingerprint=your_ssh_key_fingerprint"

Advanced Security Considerations and Next Steps

This setup provides a foundational secure infrastructure for your Shopify cluster. For production readiness, consider the following:

  • Managed Databases: Utilize DigitalOcean Managed Databases for PostgreSQL or MySQL. This offloads database management, backups, and high availability to DigitalOcean, significantly enhancing security and reliability.
  • SSL/TLS Certificates: Implement SSL/TLS certificates for HTTPS. This can be managed on the load balancer or on each web server. Let’s Encrypt is a popular free option.
  • Secrets Management: Integrate with a dedicated secrets management solution (e.g., HashiCorp Vault, AWS Secrets Manager, or DigitalOcean Secrets) for API keys, database credentials, and other sensitive information.
  • Monitoring and Alerting: Set up comprehensive monitoring for your Droplets, load balancer, and application. Configure alerts for performance degradation, errors, and security events.
  • Automated Backups: Implement robust backup strategies for your database and application data.
  • CI/CD Integration: Automate your application deployments using CI/CD pipelines (e.g., GitLab CI, GitHub Actions, Jenkins) to ensure consistent and secure deployments.
  • Immutable Infrastructure: For enhanced security and predictability, consider adopting an immutable infrastructure approach where servers are replaced rather than updated in place.

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 thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala