Infrastructure as Code with Terraform on Cloud Servers: A Complete Guide

What is Infrastructure as Code?
Infrastructure as Code (IaC) treats your server infrastructure the same way you treat application code. Instead of manually clicking through dashboards or running ad-hoc commands, you define your desired infrastructure state in configuration files. Terraform, developed by HashiCorp, is the industry-standard tool for IaC across multiple cloud providers.
With ServerRaja cloud servers, Terraform lets you define your entire infrastructure stack in version-controlled files that can be reviewed, tested, and deployed just like application code.
Installing Terraform
Install Terraform on your local machine or CI/CD runner:
# Ubuntu/Debian
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform# CentOS/RHEL sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo sudo yum install terraform
# Verify installation terraform version ```
Terraform Project Structure
Organize your infrastructure code with a clear directory structure:
infrastructure/
├── main.tf # Main resource definitions
├── variables.tf # Input variable declarations
├── outputs.tf # Output value definitions
├── providers.tf # Provider configuration
├── terraform.tfvars # Variable values (not committed to git)
├── versions.tf # Required provider versions
└── modules/
├── networking/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── compute/
├── main.tf
├── variables.tf
└── outputs.tf
Writing Your First Configuration
Create the provider configuration in `providers.tf`:
terraform {
required_version = ">= 1.5.0"required_providers { openstack = { source = "terraform-provider-openstack/openstack" version = "~> 1.54.0" } }
backend "s3" { bucket = "terraform-state" key = "production/terraform.tfstate" region = "us-east-1" } }
provider "openstack" { auth_url = var.auth_url region = var.region tenant_name = var.tenant_name user_name = var.username password = var.password } ```
Define variables in `variables.tf`:
variable "auth_url" {
description = "OpenStack authentication URL"
type = string
}variable "region" { description = "Cloud region" type = string default = "us-east-1" }
variable "instance_count" { description = "Number of web servers" type = number default = 2 }
variable "instance_flavor" { description = "Server size" type = string default = "v2-4c8g" } ```
Provisioning Cloud Resources
Create compute instances in `main.tf`:
resource "openstack_compute_instance_v2" "web_server" {
count = var.instance_count
name = "web-server-${count.index + 1}"
image_name = "Ubuntu-22.04"
flavor_name = var.instance_flavor
key_pair = openstack_compute_keypair_v2.deployer.name
security_groups = [openstack_networking_secgroup_v2.web.name]network { uuid = openstack_networking_network_v2.internal.id }
user_data = <<-EOF #!/bin/bash apt-get update apt-get install -y nginx systemctl enable nginx systemctl start nginx EOF
tags = ["web", "production"] }
resource "openstack_compute_keypair_v2" "deployer" { name = "terraform-deployer" public_key = file("~/.ssh/id_ed25519.pub") } ```
Define networking resources:
resource "openstack_networking_network_v2" "internal" {
name = "internal-network"
admin_state_up = true
}resource "openstack_networking_subnet_v2" "internal" { name = "internal-subnet" network_id = openstack_networking_network_v2.internal.id cidr = "10.0.1.0/24" ip_version = 4
dns_nameservers = ["8.8.8.8", "8.8.4.4"] }
resource "openstack_networking_secgroup_v2" "web" { name = "web-security-group" description = "Security group for web servers" }
resource "openstack_networking_secgroup_rule_v2" "ssh" { direction = "ingress" ethertype = "IPv4" protocol = "tcp" port_range_min = 22 port_range_max = 22 remote_ip_prefix = "0.0.0.0/0" security_group_id = openstack_networking_secgroup_v2.web.id }
resource "openstack_networking_secgroup_rule_v2" "http" { direction = "ingress" ethertype = "IPv4" protocol = "tcp" port_range_min = 443 port_range_max = 443 remote_ip_prefix = "0.0.0.0/0" security_group_id = openstack_networking_secgroup_v2.web.id } ```
Using Terraform Modules
Create reusable modules to avoid repetition. Here is a networking module:
# modules/networking/main.tf
resource "openstack_networking_network_v2" "this" {
name = var.network_name
admin_state_up = true
}resource "openstack_networking_subnet_v2" "this" { name = "${var.network_name}-subnet" network_id = openstack_networking_network_v2.this.id cidr = var.cidr dns_nameservers = var.dns_servers }
output "network_id" { value = openstack_networking_network_v2.this.id }
output "subnet_id" { value = openstack_networking_subnet_v2.this.id } ```
Call the module from your root configuration:
module "networking" {
source = "./modules/networking"
network_name = "production"
cidr = "10.0.0.0/16"
dns_servers = ["8.8.8.8", "1.1.1.1"]
}
Terraform Workflow Commands
The standard Terraform workflow follows these steps:
# Initialize the working directory
terraform init# Preview changes before applying terraform plan -out=tfplan
# Review the plan output carefully terraform show tfplan
# Apply the changes terraform apply tfplan
# View current state terraform show
# List all managed resources terraform state list
# Destroy infrastructure when no longer needed terraform destroy ```
State Management Best Practices
Terraform state tracks the mapping between your configuration and real infrastructure. Use remote state backends like S3 or Terraform Cloud, enable state locking, and never edit state files manually. Implement state separation for different environments:
# Move a resource in state without recreating
terraform state mv openstack_compute_instance_v2.web_server openstack_compute_instance_v2.app_server# Import existing infrastructure terraform import openstack_compute_instance_v2.existing_server <server-id> ```
Conclusion
Terraform brings discipline, repeatability, and version control to infrastructure management on ServerRaja cloud servers. Start by codifying your existing infrastructure using `terraform import`, then adopt a workflow where all changes go through plan and apply. Pair Terraform with your CI/CD pipeline for fully automated infrastructure deployments.