Infrastructure as Code: Terraform with RAW Cloud
Clicking through dashboards to provision servers does not scale. Infrastructure as Code (IaC) lets you define servers, networks, and configurations in version-controlled files — reproducible, auditable, and automated. Here is how to use Terraform with RAW Cloud to manage bare metal infrastructure programmatically.
Why Terraform for Bare Metal
Terraform treats infrastructure as declarative code. You describe the desired state, and Terraform figures out what to create, update, or destroy. For bare metal on RAW, this means:
- Spin up 10 servers with one command
- Version-control your entire infrastructure in Git
- Reproduce identical environments for staging and production
- Destroy and rebuild infrastructure in seconds
- Integrate server provisioning into CI/CD pipelines
Step 1: Install Terraform
# macOS
brew install terraform
# Linux (Ubuntu/Debian)
wget -O - https://apt.releases.hashicorp.com/gpg | 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" | tee /etc/apt/sources.list.d/hashicorp.list
apt update && apt install terraform
# Verify
terraform versionStep 2: Configure the RAW Provider
RAW exposes a REST API for server management. Terraform talks to this API through a provider. Create a main.tf file:
terraform {
required_providers {
raw = {
source = "rawhq/raw"
version = "~> 1.0"
}
}
}
provider "raw" {
api_key = var.raw_api_key
}
variable "raw_api_key" {
type = string
sensitive = true
}Set your API key as an environment variable instead of hardcoding it:
export TF_VAR_raw_api_key="your-api-key-here"Step 3: Define Server Resources
Create a servers.tf file to define your infrastructure:
# Production web server
resource "raw_server" "web" {
name = "web-prod-1"
plan = "bm-4c-8g"
region = "eu-fsn"
image = "ubuntu-24.04"
ssh_keys = [var.ssh_key_id]
tags = {
environment = "production"
role = "web"
}
}
# Database server with more resources
resource "raw_server" "db" {
name = "db-prod-1"
plan = "bm-8c-32g"
region = "eu-fsn"
image = "ubuntu-24.04"
ssh_keys = [var.ssh_key_id]
tags = {
environment = "production"
role = "database"
}
}
# Output the server IPs
output "web_ip" {
value = raw_server.web.ipv4_address
}
output "db_ip" {
value = raw_server.db.ipv4_address
}Step 4: Plan and Apply
# Initialize the provider
terraform init
# Preview what will be created
terraform plan
# Apply the changes (creates the servers)
terraform apply
# View current state
terraform showTerraform shows you exactly what it will create before making any changes. The plan step is your safety net — review it before every apply.
State Management
Terraform stores the current state of your infrastructure in a terraform.tfstate file. For team environments, store state remotely:
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "raw/production.tfstate"
region = "eu-central-1"
}
}Remote state enables team collaboration, state locking (prevents concurrent modifications), and versioned history of every infrastructure change. Never commit terraform.tfstate to Git — it may contain sensitive values like IP addresses and resource IDs.
Multi-Environment Setup
Use Terraform workspaces or variable files to manage staging and production from the same codebase:
# Using tfvars files per environment
# production.tfvars
server_plan = "bm-8c-32g"
server_count = 3
environment = "production"
# staging.tfvars
server_plan = "bm-4c-8g"
server_count = 1
environment = "staging"# Deploy to staging
terraform apply -var-file="staging.tfvars"
# Deploy to production
terraform apply -var-file="production.tfvars"This pattern keeps your infrastructure DRY. One set of Terraform files, multiple environments, each with appropriate sizing and cost.
Scaling with Count
Provision multiple identical servers with a single resource block:
variable "web_server_count" {
default = 3
}
resource "raw_server" "web_cluster" {
count = var.web_server_count
name = format("web-prod-%d", count.index + 1)
plan = "bm-4c-8g"
region = "eu-fsn"
image = "ubuntu-24.04"
ssh_keys = [var.ssh_key_id]
}
output "web_cluster_ips" {
value = raw_server.web_cluster[*].ipv4_address
}Change web_server_count from 3 to 5, run terraform apply, and two new servers appear. Scale down and Terraform destroys the extras. Predictable, repeatable, and version-controlled.
Why RAW for Terraform Workflows
Cloud providers like AWS have hundreds of resource types and complex networking. RAW keeps it simple: servers, SSH keys, and an API. Terraform configs stay clean and readable. Provisioning a server takes seconds, not minutes. And at $6/mo per server, you can afford proper staging environments without burning budget on idle cloud VMs.