Infrastructure as Code: Provisioning Secure WooCommerce Clusters on OVH Using Terraform
OVHcloud Provider Configuration for Terraform
To provision resources on OVHcloud using Terraform, we first need to configure the OVHcloud provider. This involves specifying your OVHcloud API credentials and the region where you intend to deploy your infrastructure. It’s crucial to manage these credentials securely, ideally using environment variables or a dedicated secrets management system rather than hardcoding them directly into your Terraform configuration.
Here’s a basic example of how to set up the OVHcloud provider in your main.tf file:
# main.tf
terraform {
required_providers {
ovh = {
source = "ovh/ovh"
version = "~> 1.0" # Specify a version constraint
}
}
}
provider "ovh" {
endpoint = "ovh-eu" # Or "ovh-us", "ovh-ca", "runabove-ca" etc.
# It's highly recommended to use environment variables for credentials
# export OVH_APPLICATION_KEY="your_application_key"
# export OVH_APPLICATION_SECRET="your_application_secret"
# export OVH_CONSUMER_KEY="your_consumer_key"
# Alternatively, you can specify them directly (NOT RECOMMENDED FOR PRODUCTION)
# application_key = var.ovh_application_key
# application_secret = var.ovh_application_secret
# consumer_key = var.ovh_consumer_key
}
# Example of using variables for credentials (if not using env vars)
# variable "ovh_application_key" {
# description = "OVH Application Key"
# type = string
# sensitive = true
# }
# variable "ovh_application_secret" {
# description = "OVH Application Secret"
# type = string
# sensitive = true
# }
# variable "ovh_consumer_key" {
# description = "OVH Consumer Key"
# type = string
# sensitive = true
# }
Securing OVHcloud API Credentials
Managing API keys is a critical security concern. For production environments, avoid hardcoding credentials. The OVHcloud Terraform provider supports authentication via environment variables, which is the preferred method. Ensure these environment variables are set in your CI/CD pipeline or local development environment before running Terraform commands.
The required environment variables are:
OVH_APPLICATION_KEY: Your OVH API Application Key.OVH_APPLICATION_SECRET: Your OVH API Application Secret.OVH_CONSUMER_KEY: Your OVH API Consumer Key.
You can obtain these keys by creating an application in the OVHcloud control panel under “API Consoles” > “Create a new application”. Grant it the necessary permissions (e.g., read/write access to infrastructure, databases, etc.).
Provisioning a Virtual Private Server (VPS) for WooCommerce
For a typical WooCommerce setup, a robust VPS is a good starting point. We’ll provision a VPS instance, configure its network, and set up basic security measures. For high availability and scalability, you would later consider load balancers, multiple web servers, and managed databases, but this example focuses on a single, secure VPS.
# vps.tf
resource "ovh_vps" "woocommerce_webserver" {
name = "woocommerce-webserver"
plan_name = "starter-1-1" # Example plan, choose based on your needs
region = "GRA" # Example region (Gravelines, France)
ssh_key_name = "my-terraform-key" # Name of your SSH key in OVHcloud
cloud_init = filebase64("cloud-init.yaml") # Base64 encoded cloud-init script
ipv6_enable = true
# Additional options like disk, network interfaces can be configured here
}
resource "ovh_vps_user_data" "woocommerce_webserver_user_data" {
service_name = ovh_vps.woocommerce_webserver.id
content = file("cloud-init.yaml") # Path to your cloud-init file
}
# Example of creating an SSH key if it doesn't exist
# resource "ovh_vps_ssh_key" "tf_generated_key" {
# name = "my-terraform-key"
# public_key = file("~/.ssh/id_rsa.pub") # Path to your public SSH key
# }
# Output the public IP address of the VPS
output "woocommerce_webserver_public_ip" {
description = "Public IP address of the WooCommerce web server"
value = ovh_vps.woocommerce_webserver.public_ip_address
}
Cloud-Init for Initial Server Setup
cloud-init is essential for automating the initial setup of your VPS. This script runs on the first boot and can perform tasks like updating packages, installing essential software (web server, PHP, database client), configuring firewalls, and setting up users. This ensures your server is ready for WooCommerce deployment with minimal manual intervention.
# cloud-init.yaml
#cloud-config
package_update: true
package_upgrade: true
packages:
- nginx
- php-fpm
- php-mysql
- php-gd
- php-xml
- php-mbstring
- php-curl
- mariadb-client # Or mysql-client if using MySQL
- ufw # Uncomplicated Firewall
runcmd:
# Configure UFW (Uncomplicated Firewall)
- ufw allow ssh
- ufw allow http
- ufw allow https
- ufw enable # Enable the firewall
# Configure Nginx for a basic PHP setup (adjust as needed)
- sed -i 's/fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;/fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;\\n fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;/g' /etc/nginx/snippets/fastcgi-php.conf
- echo "server { listen 80; server_name _; root /var/www/html; index index.php index.html index.htm; location / { try_files \$uri \$uri/ /index.php?\$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust PHP version if necessary } }" > /etc/nginx/sites-available/default
- systemctl restart nginx
- systemctl enable nginx
# Create a placeholder index.php for testing
- echo "<?php phpinfo(); ?>" > /var/www/html/index.php
# Secure MariaDB/MySQL installation (interactive prompts need to be handled differently for full automation)
# For a fully automated secure installation, consider pre-seeding answers or using configuration management tools.
# Example: mysql_secure_installation --use-default --root-password=YOUR_SECURE_PASSWORD --allow-root --skip-test-db
# This requires careful handling of sensitive data.
# Ensure PHP-FPM is running and enabled
- systemctl enable php7.4-fpm # Adjust PHP version
- systemctl start php7.4-fpm # Adjust PHP version
write_files:
# Example: Create a basic wp-config.php placeholder (will be overwritten by deployment script)
- path: /var/www/html/wp-config.php
permissions: '0644'
owner: www-data:www-data
content: |
<?php
define( 'DB_NAME', 'wordpress_db' );
define( 'DB_USER', 'wordpress_user' );
define( 'DB_PASSWORD', 'your_strong_password' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8' );
define( 'DB_COLLATE', '' );
$table_prefix = 'wp_';
define( 'WP_DEBUG', false );
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __FILE__ => dirname( __FILE__ ) . '/' );
}
require_once( ABSPATH . 'wp-settings.php' );
?>
# Optional: Add a user for deployment
# users:
# - name: deployer
# groups: sudo
# shell: /bin/bash
# sudo: "ALL=(ALL) NOPASSWD:ALL"
# ssh_authorized_keys:
# - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD... your_public_key ... user@host
Database Provisioning (Managed Database Service)
For a production WooCommerce site, running the database on the same VPS is not recommended due to performance and isolation concerns. OVHcloud offers managed database services (e.g., MySQL, PostgreSQL). We’ll provision a managed MySQL instance.
# database.tf
resource "ovh_db_instance" "woocommerce_db" {
engine = "mysql"
version = "8.0" # Specify desired MySQL version
plan_name = "db.s.2" # Example plan, choose based on your needs
region = "GRA" # Must match VPS region for optimal performance
name = "woocommerce-db"
network_type = "private" # Use private network for security and performance
disk_size_gb = 20
# Additional options like backup, replicas can be configured here
}
# Output database connection details (handle sensitive data with care)
output "woocommerce_db_host" {
description = "Hostname of the managed MySQL database"
value = ovh_db_instance.woocommerce_db.hostname
}
output "woocommerce_db_port" {
description = "Port of the managed MySQL database"
value = ovh_db_instance.woocommerce_db.port
}
output "woocommerce_db_name" {
description = "Name of the managed MySQL database"
value = ovh_db_instance.woocommerce_db.database_name
}
# Note: User and password for the database are managed separately by OVHcloud.
# You can retrieve them via the OVHcloud API or control panel.
# For programmatic access, you might need to use the OVH API to fetch these credentials.
Network Security and Firewall Configuration
Security is paramount. We’ll leverage OVHcloud’s network firewall capabilities to restrict access to the VPS. Only necessary ports (SSH, HTTP, HTTPS) should be open, and ideally, SSH access should be further restricted by IP address if possible.
# firewall.tf
# This example assumes you are using OVHcloud's Public Cloud Gateway Firewall.
# If you are using dedicated servers, the approach might differ (e.g., iptables managed via cloud-init).
resource "ovh_cloud_project_network_private" "wc_private_network" {
service_name = "your-ovh-cloud-project-id" # Replace with your actual OVH Cloud Project ID
name = "woocommerce-private-net"
region = "GRA"
}
resource "ovh_cloud_project_gateway_firewall" "wc_firewall" {
service_name = "your-ovh-cloud-project-id" # Replace with your actual OVH Cloud Project ID
name = "woocommerce-firewall"
region = "GRA"
description = "Firewall for WooCommerce cluster"
}
resource "ovh_cloud_project_gateway_firewall_rule" "allow_ssh" {
service_name = ovh_cloud_project_gateway_firewall.wc_firewall.service_name
firewall_id = ovh_cloud_project_gateway_firewall.wc_firewall.id
action = "accept"
protocol = "tcp"
destination_port = 22
source = "YOUR_OFFICE_IP/32" # Restrict SSH to your trusted IP address
# Or use a subnet: source = "192.168.1.0/24"
# If you need to allow SSH from anywhere (less secure): source = "0.0.0.0/0"
}
resource "ovh_cloud_project_gateway_firewall_rule" "allow_http" {
service_name = ovh_cloud_project_gateway_firewall.wc_firewall.service_name
firewall_id = ovh_cloud_project_gateway_firewall.wc_firewall.id
action = "accept"
protocol = "tcp"
destination_port = 80
source = "0.0.0.0/0" # Allow HTTP from anywhere
}
resource "ovh_cloud_project_gateway_firewall_rule" "allow_https" {
service_name = ovh_cloud_project_gateway_firewall.wc_firewall.service_name
firewall_id = ovh_cloud_project_gateway_firewall.wc_firewall.id
action = "accept"
protocol = "tcp"
destination_port = 443
source = "0.0.0.0/0" # Allow HTTPS from anywhere
}
# Rule to deny all other incoming traffic by default
resource "ovh_cloud_project_gateway_firewall_rule" "deny_all" {
service_name = ovh_cloud_project_gateway_firewall.wc_firewall.service_name
firewall_id = ovh_cloud_project_gateway_firewall.wc_firewall.id
action = "deny"
protocol = "any"
destination_port = "any"
source = "0.0.0.0/0"
position = 999 # Ensure this rule is last
}
# Associate the firewall with the private network
resource "ovh_cloud_project_gateway_firewall_association" "wc_firewall_association" {
service_name = ovh_cloud_project_gateway_firewall.wc_firewall.service_name
firewall_id = ovh_cloud_project_gateway_firewall.wc_firewall.id
network_id = ovh_cloud_project_network_private.wc_private_network.id
}
# Note: You would typically associate your VPS with this private network.
# This might involve configuring network interfaces on the VPS or using OVHcloud's
# Public Cloud networking features to attach the VPS to the private network.
# The exact method depends on how you're managing your VPS networking.
Deployment Workflow and Next Steps
Once you have your Terraform configuration files (main.tf, vps.tf, database.tf, firewall.tf, cloud-init.yaml) in place:
- Initialize Terraform: Run
terraform initin your project directory. This downloads the OVHcloud provider. - Review the plan: Run
terraform plan. This will show you all the resources Terraform will create, modify, or destroy. Carefully review this output to ensure it matches your expectations. - Apply the configuration: Run
terraform apply. Terraform will prompt you to confirm the changes before proceeding with the provisioning.
After the infrastructure is provisioned:
- Configure DNS: Point your domain’s A/AAAA records to the public IP address of your WooCommerce VPS.
- Install WooCommerce: Connect to your VPS via SSH and proceed with installing WordPress and WooCommerce. This typically involves downloading WordPress, configuring the web server (if not fully done by cloud-init), setting up the database connection in
wp-config.php, and running the WordPress installation wizard. - SSL Certificate: Install an SSL certificate (e.g., using Let’s Encrypt with Certbot) for HTTPS.
- Database Credentials: Retrieve the actual database username and password from OVHcloud for your managed database instance and update your
wp-config.phpaccordingly.
For a production-ready cluster, consider implementing:
- Load Balancer: To distribute traffic across multiple web servers.
- Auto-scaling: To automatically adjust the number of web servers based on traffic load.
- Managed Kubernetes (e.g., OVHcloud Managed Kubernetes Service): For containerized deployments, offering greater flexibility and scalability.
- Object Storage: For media files and backups.
- CDN: For faster content delivery.
- Advanced Monitoring and Logging: To track performance and troubleshoot issues.