Terraform configuration for provisioning a single server that runs both WordPress and MySQL. The cloud-init script will install and configure both services so that WordPress uses the local MySQL service.

terraform {
  required_providers {
    faxter = {
      source  = "local/faxter/faxter"
      version = "0.1.0"
    }
  }
  required_version = ">= 1.0.0"
}

provider "faxter" {
  token = var.faxter_token
}

# Variables
variable "faxter_token" {
  description = "API token for Faxter provider"
  type        = string
}

variable "ssh_key_name" {
  description = "SSH key name"
  type        = string
}

variable "ssh_public_key" {
  description = "Path to SSH public key"
  type        = string
}

variable "private_key_path" {
  description = "Path to SSH private key"
  type        = string
}

variable "project" {
  description = "Project name"
  type        = string
}

# Resources

# SSH Key
resource "faxter_ssh_key" "default" {
  name       = var.ssh_key_name
  public_key = file(var.ssh_public_key)
}

# Private Network
resource "faxter_network" "private" {
  project = var.project
  name = "private-network"
  subnets {
    name = "private-subnet"
    cidr = "192.168.100.0/24"
  }
}

# router
resource "faxter_router" "router" {
  project = var.project
  name = "router"
  subnets = [faxter_network.private.subnets[0].name]
}

# Security Group
resource "faxter_security_group" "web_db_sg" {
  project = var.project
  name = "web-db-sg"
  rules {
    protocol         = "tcp"
    port_range_min   = 22
    port_range_max   = 22
    direction        = "ingress"
    remote_ip_prefix = "0.0.0.0/0"
 }
  rules {
    protocol         = "tcp"
    port_range_min   = 80
    port_range_max   = 80
    direction        = "ingress"
    remote_ip_prefix = "0.0.0.0/0"
  }
  # ingress allow mysql from localhost
  rules {
    protocol         = "tcp"
    port_range_min   = 3306
    port_range_max   = 3306
    direction        = "ingress"
    remote_ip_prefix = "127.0.0.1/32"
  }
}

# Server with WordPress and MySQL
resource "faxter_server" "wordpress_mysql" {
  project          = var.project
  name             = "wordpress-mysql"
  flavor           = "titanium"
  image            = "Ubuntu2204"
  key_name         = faxter_ssh_key.default.name
  networks         = [faxter_network.private.name]
  security_groups  = [faxter_security_group.web_db_sg.name]
  cloud_init       = base64encode(data.local_file.wordpress_mysql_cloud_init.content)
}

# Cloud-Init Script for WordPress and MySQL
data "local_file" "wordpress_mysql_cloud_init" {
  filename = "${path.module}/wordpress_mysql_cloud_init.yaml"
}


# Output
output "server_ip" {
  value = faxter_server.wordpress_mysql.ip_addresses[0]
}

terraform.tfvars

faxter_token       = "YOUR_API_TOKEN"
ssh_key_name       = "wordpress_key"
ssh_public_key     = "~/.ssh/id_rsa.pub"
private_key_path   = "~/.ssh/id_rsa"
project            = "your_project_name"

Cloud-Init File (wordpress_mysql_cloud_init.yaml)

Save this file in the same directory as your Terraform configuration.

#cloud-config
package_update: true
package_upgrade: true
packages:
  - apache2
  - php
  - php-mysql
  - mysql-server
  - wget
  - unzip

runcmd:
  # Configure MySQL
  - systemctl enable mysql
  - systemctl start mysql
  - mysql -e "CREATE DATABASE wordpress;"
  - mysql -e "CREATE USER 'wordpressuser'@'localhost' IDENTIFIED BY 'password';"
  - mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpressuser'@'localhost';"
  - mysql -e "FLUSH PRIVILEGES;"

  # Configure Apache and PHP
  - wget https://wordpress.org/latest.zip -O /tmp/wordpress.zip
  - unzip /tmp/wordpress.zip -d /var/www/html/
  - mv /var/www/html/wordpress /var/www/html/wordpress-site
  - chown -R www-data:www-data /var/www/html/wordpress-site
  - chmod -R 755 /var/www/html/wordpress-site

  # Configure WordPress
  - cp /var/www/html/wordpress-site/wp-config-sample.php /var/www/html/wordpress-site/wp-config.php
  - sed -i "s/database_name_here/wordpress/" /var/www/html/wordpress-site/wp-config.php
  - sed -i "s/username_here/wordpressuser/" /var/www/html/wordpress-site/wp-config.php
  - sed -i "s/password_here/password/" /var/www/html/wordpress-site/wp-config.php

  # Restart Apache
  - systemctl enable apache2
  - systemctl restart apache2

Explanation

  1. Cloud-Init Script:

    • Updates and upgrades the server packages.
    • Installs apache2, php, php-mysql, and mysql-server.
    • Configures MySQL by creating a database and user for WordPress.
    • Downloads and configures WordPress, including setting file permissions.
    • Security Groups:

    • Allows HTTP traffic on port 80 and MySQL traffic restricted to the local host.

    • Server:

    • A single server running both Apache and MySQL with WordPress installed.

Steps to Deploy:

  1. Save the Terraform files and the wordpress_mysql_cloud_init.yaml file.
  2. Replace placeholders in terraform.tfvars or set the variables using the CLI.
  3. Run the following commands:
terraform init
terraform plan
terraform apply
  1. Access WordPress via the server's IP address on port 80.