PHP Webserver with loadbalancers
Note: This example is still undergoing tests!
If you encounter any issue trying to run this, please contact support@faxter.com
- Project Setup: Creates a Faxter project.
- Network Configuration: Sets up a private network with subnets and a router connecting to the external network.
- Security Groups: Defines security groups for the web servers and the database server to control traffic.
- SSH Keys: Manages SSH keys for secure access.
- Volumes: Creates a persistent volume for the MySQL database.
- Servers: Deploys three PHP web servers and one MySQL database server with appropriate cloud-init scripts.
- Load Balancer: Sets up a load balancer with a public IP to distribute traffic to the web servers.
Terraform Configuration
terraform {
required_providers {
faxter = {
source = "local/faxter/faxter"
version = "0.1.0"
}
}
required_version = ">= 1.0.0"
}
provider "faxter" {
token = var.faxter_token
}
variable "faxter_token" {
description = "API token for Faxter provider"
type = string
}
variable "ssh_public_key" {
description = "Path to SSH public key"
type = string
}
variable "project" {
description = "Project name"
type = string
}
# 1. Create a Private Network with Subnets
resource "faxter_network" "private_network" {
project = var.project
name = "private-network"
subnets {
name = "web-subnet"
cidr = "192.168.10.0/24"
gateway = "192.168.10.1"
static_routes {
destination = "192.168.11.0/24"
nexthop = "192.168.10.1"
}
}
subnets {
name = "db-subnet"
cidr = "192.168.11.0/24"
gateway = "192.168.11.1"
static_routes {
destination = "192.168.10.0/24"
nexthop = "192.168.11.1"
}
}
}
# 2. Set Up a Router to Connect the Private Network to the External Network
resource "faxter_router" "private_router" {
project = var.project
name = "private-router"
connect_external = true
subnets = [
faxter_network.private_network.subnets[0].name, # web-subnet
faxter_network.private_network.subnets[1].name # db-subnet
]
}
# 3. Define Security Groups
## 3.1 Security Group for Load Balancer
resource "faxter_security_group" "lb_sg" {
project = var.project
name = "lb-sg"
rules {
protocol = "tcp"
port_range_min = 80
port_range_max = 80
direction = "ingress"
remote_ip_prefix = "0.0.0.0/0" # Allow HTTP from anywhere
}
rules {
protocol = "tcp"
port_range_min = 443
port_range_max = 443
direction = "ingress"
remote_ip_prefix = "0.0.0.0/0" # Allow HTTPS from anywhere
}
rules {
protocol = "tcp"
port_range_min = 22
port_range_max = 22
direction = "ingress"
remote_ip_prefix = "0.0.0.0/0" # Replace with your IP or range
}
}
## 3.2 Security Group for Web Servers
resource "faxter_security_group" "web_sg" {
project = var.project
name = "web-sg"
rules {
protocol = "tcp"
port_range_min = 80
port_range_max = 80
direction = "ingress"
remote_group_id = faxter_security_group.lb_sg.id # Allow traffic from Load Balancer SG
}
rules {
protocol = "tcp"
port_range_min = 22
port_range_max = 22
direction = "ingress"
remote_ip_prefix = "0.0.0.0/0" # Replace with your IP or range
}
}
## 3.3 Security Group for Database Server
resource "faxter_security_group" "db_sg" {
project = var.project
name = "db-sg"
rules {
protocol = "tcp"
port_range_min = 3306
port_range_max = 3306
direction = "ingress"
remote_group_id = faxter_security_group.web_sg.id # Allow traffic from Web SG
}
rules {
protocol = "tcp"
port_range_min = 22
port_range_max = 22
direction = "ingress"
remote_ip_prefix = "0.0.0.0/0" # Replace with your IP or range
}
}
# 4. Manage SSH Keys
## 4.1 SSH Key for Web Servers
resource "faxter_ssh_key" "web_ssh" {
project = var.project
name = "web-ssh-key"
public_key = file(var.ssh_public_key)
}
## 4.2 SSH Key for Database Server
resource "faxter_ssh_key" "db_ssh" {
project = var.project
name = "db-ssh-key"
public_key = file(var.ssh_public_key)
}
# 5. Create a Volume for the MySQL Database
resource "faxter_volume" "db_volume" {
project = var.project
name = "db-data"
storage = 100 # Size in GB
}
# 6. Deploy the MySQL Database Server
resource "faxter_server" "db_server" {
depends_on = [ faxter_network.private_network ]
project = var.project
name = "mysql-db-server"
key_name = faxter_ssh_key.db_ssh.name
flavor = "gold" # Choose appropriate flavor
image = "Ubuntu2204"
security_groups = [faxter_security_group.db_sg.name]
sub_networks = [faxter_network.private_network.subnets[1].name] # db-subnet
request_floating_ip = false
volumes = [faxter_volume.db_volume.name]
cloud_init = base64encode(data.local_file.db_cloud_init.content)
}
data "local_file" "db_cloud_init" {
filename = "${path.module}/db_cloud_init.yaml"
}
# 7. Deploy Three PHP Web Servers
resource "faxter_server" "web_servers" {
depends_on = [ faxter_network.private_network ]
count = 3
project = var.project
name = "php-web-server-${count.index + 1}"
key_name = faxter_ssh_key.web_ssh.name
flavor = "silver" # Choose appropriate flavor
image = "Ubuntu2204"
security_groups = [faxter_security_group.web_sg.name]
sub_networks = [faxter_network.private_network.subnets[0].name] # web-subnet
request_floating_ip = false
cloud_init = base64encode(data.local_file.web_cloud_init.content)
}
data "local_file" "web_cloud_init" {
filename = "${path.module}/web_cloud_init.yaml"
}
# 8. Set Up the Load Balancer
resource "faxter_loadbalancer" "web_lb" {
depends_on = [
faxter_network.private_network, # Ensure the network is created and connected to router before loadbalancer deployment
faxter_router.private_router
]
project = var.project
name = "web-loadbalancer"
port = 80
sub_networks = [faxter_network.private_network.subnets[0].name] # web-subnet
request_floating_ip = true
ssl_enabled = false
security_groups = [faxter_security_group.lb_sg.name]
key_name = faxter_ssh_key.web_ssh.name
dynamic "servers" {
# for_each is your list of created servers
for_each = faxter_server.web_servers[*]
# content describes each 'servers { ... }' block
content {
ip = servers.value.ip_addresses[0]
port = 80
endpoint = "/"
}
}
}
db_cloud_init.yaml
#cloud-config
package_update: true
packages:
- mysql-server
runcmd:
# Configure MySQL
- systemctl enable mysql
- systemctl start mysql
- mysql -e "CREATE USER 'phpuser'@'%' IDENTIFIED BY 'YOUR_DB_PASSWORD';"
- mysql -e "CREATE DATABASE phpsite;"
- mysql -e "GRANT ALL PRIVILEGES ON phpsite.* TO 'phpuser'@'%';"
- mysql -e "FLUSH PRIVILEGES;"
# Format and mount the attached volume
- mkfs.ext4 /dev/vdb # Replace /dev/vdb with the appropriate device name for the attached volume
- mkdir -p /mnt/mysql_data
- mount /dev/vdb /mnt/mysql_data
- echo "/dev/vdb /mnt/mysql_data ext4 defaults 0 0" >> /etc/fstab
# Move MySQL data directory to the mounted volume
- systemctl stop mysql
- mv /var/lib/mysql /mnt/mysql_data/mysql
- ln -s /mnt/mysql_data/mysql /var/lib/mysql
- chown -R mysql:mysql /mnt/mysql_data/mysql
- systemctl start mysql
web_cloud_init.yaml
#cloud-config
package_update: true
packages:
- apache2
- php
- libapache2-mod-php
- git
runcmd:
- systemctl enable apache2
- systemctl start apache2
- rm -fr /var/www/html
- git clone https://github.com/banago/simple-php-website.git /var/www/html
- chown -R www-data:www-data /var/www/html
- systemctl restart apache2
terraform.tfvars
faxter_token = "YOUR_AKI_TOKEN"
ssh_public_key = "~/.ssh/id_rsa.pub"
project = "PROJECT_NAME"
Explanation & Placeholders
-
Private Network (faxter_network)
- Subnets: Two subnets are created: web-subnet for PHP web servers. db-subnet for the MySQL database server.
- CIDR Blocks: Adjust CIDR blocks (192.168.10.0/24 and 192.168.11.0/24) if needed.
- Router (faxter_router)
Connects the private network to the external/public network. Name: "private-router" can be changed as needed. 3. Security Groups (faxter_security_group)
- Web SG (web-sg): Allows HTTP (port 80) traffic from the Load Balancer security group. Allows SSH (port 22) from your specified IP.
- DB SG (db-sg): Allows MySQL (port 3306) traffic from the Web SG. Allows SSH (port 22) from your specified IP.
- Load Balancer SG (lb-sg): Allows HTTP (port 80) and HTTPS (port 443) from anywhere. Allows SSH (port 22) from your specified IP.
Placeholders to Replace:
- "YOUR_SSH_ACCESS_IP/32": Replace with your actual IP address or CIDR range for SSH access.
- "YOUR_PUBLIC_SSH_KEY": Replace with your actual SSH public key content.
- SSH Keys (faxter_ssh_key)
Web Servers SSH Key (web_ssh) and DB Server SSH Key (db_ssh):
- Replace "YOUR_PUBLIC_SSH_KEY" with your actual SSH public key.
-
Volume (faxter_volume)
-
Database Volume (db_volume):
- Name: "db-data" can be changed as needed.
- Storage: Adjust the storage size as required.
- MySQL Database Server (faxter_server.db_server)
- Cloud-Init Script:
- Installs MySQL server.
- Creates a MySQL user (phpuser) and database (phpsite).
- Placeholders to Replace:
- "YOUR_DB_PASSWORD": Replace with a secure password for the MySQL user.
-
PHP Web Servers (faxter_server.web_servers)
-
Count: Deploys three instances (count = 3).
- Cloud-Init Script:
- Installs Apache, PHP, and Git.
- Clones your PHP application from GitHub into /var/www/html.
- Placeholders to Replace:
- "YOUR_GITHUB_REPO": Replace with your actual GitHub repository URL.
-
Load Balancer (faxter_loadbalancer.web_lb)
-
Distributes incoming HTTP traffic to the three PHP web servers.
- Port: Listens on port 80.
- Public IP: Automatically requests a floating/public IP.
- SSL: Disabled (ssl_enabled = false). Enable and configure SSL as needed.
- Servers: Dynamically includes the three web servers by referencing their private IPs.
Additional Notes
- Security: Ensure that sensitive information like database passwords is managed securely, possibly using Terraform's sensitive variables.
- Scaling: Adjust the number of web servers (count) based on your scalability needs.
- Monitoring & Logging: Implement monitoring and logging solutions as needed for production environments.
- SSL Configuration: If you plan to enable HTTPS, ensure SSL certificates are properly managed and configured.