Terraform modules for provisioning cloud instances
Terraform modules are available for automating the infrastructure provisioning of virtual machines. Depending on your selected cloud provider, additional resources or services such as security groups and firewalls must also be integrated to ensure the virtual machines can communicate effectively.
Each Terraform module consists of three core files:
main.tf
— contains the resource definitions and logic of the module.outputs.tf
— defines the outputs that the module returns.variables.tf
— defines the inputs that the module requires.
AWS Copied
All AWS Terraform modules available in this documentation require the following:
- Terraform version 1.0 or higher
- AWS provider version 4.0 or higher
- Configured AWS credentials
AWS Default VPC discovery module Copied
This module discovers existing AWS default VPC and subnet information without creating any resources. It returns the required VPC ID and subnet ID using minimal API calls. This module is also reusable for other modules requiring VPC information.
Requirements Copied
Aside from the common Terraform AWS module requirements, this module also specifically requires:
- The AWS default VPC must exist in the target region.
- The Default VPC must have at least one subnet.
Variables Copied
This module automatically discovers the default VPC and does not require any input variables.
Usage example Copied
# Discover default VPC
module "default_vpc" {
source = "../../modules/aws/default-vpc"
}
Outputs Copied
Name | Description |
---|---|
vpc_id | Default VPC resource ID |
subnet_id | First default subnet resource ID |
AWS EC2 instance module Copied
This module creates AWS EC2 instances with configurable network and security settings.
Requirements Copied
Aside from the common Terraform AWS module requirements, this module also specifically requires:
- Existing VPC and subnet.
- A security group configured.
- An AWS key pair for SSH access.
Setting up an IAM instance profile Copied
Before using this module, create an IAM instance profile for EC2 instances to securely access AWS services. The IAM instance profile created must be referenced in the iam_instance_profile
parameter of your module configuration.
# Create IAM role for EC2 instances
aws iam create-role --role-name EC2-S3-Access-Role --assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
]
}'
# Attach S3 access policy (adjust permissions as needed)
aws iam attach-role-policy --role-name EC2-S3-Access-Role \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
# Create instance profile
aws iam create-instance-profile --instance-profile-name EC2-S3-Access-Profile
# Associate role with instance profile
aws iam add-role-to-instance-profile \
--instance-profile-name EC2-S3-Access-Profile \
--role-name EC2-S3-Access-Role
Variables Copied
Configure the following variables:
Name | Description | Type | Default | Required |
---|---|---|---|---|
ami | AMI ID to use for the instance | string | yes | |
instance_type | EC2 instance type | string | yes | |
key_name | Name of the AWS key pair | string | yes | |
subnet_id | VPC subnet ID to launch instance in | string | yes | |
vpc_security_group_ids | List of security group IDs | list(string) | yes | |
iam_instance_profile | IAM instance profile name for AWS service access | string | null | no |
associate_public_ip_address | Associate public IP address | bool | false | no |
source_dest_check | Enable source/destination checking | bool | true | no |
tags | Map of tags to assign to the resource | map(string) | {} | no |
Instance types Copied
The following are common EC2 instance types:
Category | Type | Description |
---|---|---|
General purpose | t3.nano |
2 vCPU, 0.5GB RAM (burstable) |
General purpose | t3.micro |
2 vCPU, 1GB RAM (burstable, free tier eligible) |
General purpose | t3.small |
2 vCPU, 2GB RAM (burstable) |
General purpose | t3.medium |
2 vCPU, 4GB RAM (burstable) |
Compute optimized | c5.large |
2 vCPU, 4GB RAM |
Compute optimized | c5.xlarge |
4 vCPU, 8GB RAM |
Memory optimized | r5.large |
2 vCPU, 16GB RAM |
Memory optimized | r5.xlarge |
4 vCPU, 32GB RAM |
Usage example Copied
Basic example Copied
module "web_server" {
source = "../../modules/aws/instance"
ami = "ami-0c94855ba95b798c7" # Ubuntu 22.04 LTS
instance_type = "t3.micro"
key_name = "my-key-pair"
subnet_id = "subnet-12345678"
vpc_security_group_ids = ["sg-87654321"]
# IAM instance profile for AWS service access (optional)
iam_instance_profile = "EC2-S3-Access-Profile"
tags = {
Name = "web-server-01"
Environment = "Production"
Purpose = "WebServer"
}
}
Complete example with public IP Copied
module "public_instance" {
source = "../../modules/aws/instance"
ami = "ami-0c94855ba95b798c7"
instance_type = "t3.small"
key_name = "my-keypair"
subnet_id = module.default_vpc.subnet_id
vpc_security_group_ids = [module.security_group.id]
associate_public_ip_address = true
source_dest_check = false # For NAT instances
# IAM instance profile for S3 access
iam_instance_profile = "EC2-S3-Access-Profile"
tags = {
Name = "public-instance"
Environment = "Development"
Owner = "team@company.com"
Purpose = "Development Server"
}
}
Outputs Copied
Name | Description |
---|---|
instance_id | EC2 instance ID |
external_ip | Public IP address (if assigned) |
internal_ip | Private IP address |
iam_instance_profile | IAM instance profile attached to instance |
AWS Security group module Copied
This module creates AWS security groups with configurable ingress and egress rules for network access control.
Requirements Copied
Aside from the common Terraform AWS module requirements, this module also specifically requires:
- An existing VPC.
Variables Copied
Configure the following variables:
Name | Description | Type | Default | Required |
---|---|---|---|---|
name | Name of the security group | string | yes | |
vpc_id | ID of the VPC where security group will be created | string | yes | |
ingress_rules | List of ingress rules | list(object) | [] | no |
egress_rules | List of egress rules | list(object) | [] | no |
tags | Map of tags to assign to the security group | map(string) | {} | no |
Rule object structure Copied
Each rule in ingress_rules
and egress_rules
should have:
{
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
description = string
}
Protocol values Copied
tcp
- TCP protocoludp
- UDP protocolicmp
- ICMP protocol-1
- All protocols
Common port ranges Copied
The following are common port ranges:
Category | Type | Port |
---|---|---|
Web services | HTTP | 80 |
Web services | HTTPS | 443 |
Web services | Alternative HTTP | 8080 |
Web services | Alternative HTTPS | 8443 |
Database services | MySQL/MariaDB | 3306 |
Database services | PostgreSQL | 5432 |
Database services | SQL Server | 1433 |
Database services | CouchDB | 5984 |
Database services | MongoDB | 27017 |
System services | SSH | 22 |
System services | RDP (Windows) | 3389 |
System services | DNS | 53 |
System services | NTP | 123 |
Application ports | Geneos Gateway communication | 7000-7100 |
Usage example Copied
Web server security group Copied
module "web_security_group" {
source = "../../modules/aws/security_group"
name = "web-server-sg"
vpc_id = "vpc-12345678"
ingress_rules = [
{
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
description = "SSH from internal networks"
},
{
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTP from anywhere"
},
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS from anywhere"
}
]
egress_rules = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
description = "All outbound traffic"
}
]
tags = {
Name = "web-server-sg"
Environment = "Production"
Purpose = "WebServer"
}
}
Database security group Copied
module "database_security_group" {
source = "../../modules/aws/security_group"
name = "database-sg"
vpc_id = "vpc-12345678"
ingress_rules = [
{
from_port = 3306
to_port = 3306
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
description = "MySQL from application tier"
},
{
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
description = "PostgreSQL from application tier"
}
]
egress_rules = [
{
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
description = "HTTPS for updates"
}
]
}
Outputs Copied
Name | Description |
---|---|
id | Security group ID |
name | Security group name |
Azure Copied
Azure Network Interface Module Copied
Creates Azure Network Interfaces with dynamic IP configuration and security group association.
Azure Network Security Group Module Copied
Creates Azure Network Security Groups with configurable TCP inbound rules for network access control.
Azure Public IP Module Copied
Creates Azure Public IP addresses with configurable SKU, allocation method, and availability zone support.
Azure Virtual Machine Module Copied
Creates Azure Virtual Machines with SSH key authentication support.
Azure Virtual Network Module Copied
Creates Azure Virtual Networks with subnets for network isolation and connectivity.
Google Cloud Platform (GCP) Copied
All Google Cloud Terraform modules available in this documentation require the following:
- Terraform version 1.0 or higher
- Google provider version 4.0 or higher
- Google Cloud Platform project with Compute Engine API enabled
- Existing VPC network and subnet (or use default)
GCP Compute Engine instance module Copied
This module creates Google Cloud Compute Engine instances with SSH key support and flexible configuration options.
Requirements Copied
Aside from the common Terraform Google Cloud module requirements, this module also specifically requires:
- A service account with the
compute.instances.create
permission. - An existing service account to attach to instances with required IAM roles:
roles/storage.objectViewer
— for accessing cloud storage objects.roles/storage.bucketViewer
— for listing storage buckets.
- An SSH public key file.
Service account setup Copied
Before using this module, create a service account with the required permissions. The service account created must be referenced in the gcp_service_account_email
parameter of your module configuration.
# Create the service account
gcloud iam service-accounts create instance-sa \
--display-name="Instance Service Account" \
--project=your-project-id
# Assign required storage roles
gcloud projects add-iam-policy-binding your-project-id \
--member="serviceAccount:instance-sa@your-project-id.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"
gcloud projects add-iam-policy-binding your-project-id \
--member="serviceAccount:instance-sa@your-project-id.iam.gserviceaccount.com" \
--role="roles/storage.bucketViewer"
Variables Copied
Name | Description | Type | Default | Required |
---|---|---|---|---|
gcp_project_id | GCP project ID | string | yes | |
gcp_zone | GCP zone for instance placement | string | yes | |
vm_name | Virtual machine name | string | yes | |
vm_type | Machine type specification | string | yes | |
vm_image_family | Image family name | string | yes | |
vm_image_project | Image project name | string | yes | |
gcp_service_account_email | Service account email to attach to instance | string | yes | |
ssh_user | SSH username | string | yes | |
ssh_public_key_path | Path to SSH public key file | string | yes | |
gcp_service_account_scopes | Access scopes for service account | list(string) | [“cloud-platform”] | no |
network_name | VPC network name | string | “default” | no |
subnetwork_name | Subnet name | string | “default” | no |
vm_disk_size | Boot disk size in GB | number | 10 | no |
vm_disk_type | Boot disk type | string | “pd-standard” | no |
vm_status | Desired VM status | string | “RUNNING” | no |
vm_labels | Resource labels | map(string) | {} | no |
vm_metadata | Instance metadata | map(string) | {} | no |
Machine types Copied
The following are common machine types.
Category | Type | Description |
---|---|---|
General purpose (E2) | e2-micro |
1 vCPU, 1GB RAM (shared core, always free tier eligible) |
General purpose (E2) | e2-small |
1 vCPU, 2GB RAM (shared core) |
General purpose (E2) | e2-medium |
1 vCPU, 4GB RAM (shared core) |
General purpose (E2) | e2-standard-2 |
2 vCPU, 8GB RAM |
General purpose (E2) | e2-standard-4 |
4 vCPU, 16GB RAM |
General purpose (N2) | n2-standard-2 |
2 vCPU, 8GB RAM |
General purpose (N2) | n2-standard-4 |
4 vCPU, 16GB RAM |
General purpose (N2) | n2-standard-8 |
8 vCPU, 32GB RAM |
Compute optimized (C2) | c2-standard-4 |
4 vCPU, 16GB RAM |
Compute optimized (C2) | c2-standard-8 |
8 vCPU, 32GB RAM |
Memory optimized (M2) | m2-ultramem-208 |
208 vCPU, 5888GB RAM |
Memory optimized (M2) | m2-megamem-416 |
416 vCPU, 5888GB RAM |
Image families Copied
The following are common image families.
Operating system | Image | Description |
---|---|---|
Ubuntu | ubuntu-minimal-2204-lts |
Ubuntu 22.04 LTS (minimal installation) |
Ubuntu | ubuntu-2204-lts |
Ubuntu 22.04 LTS (full installation) |
Ubuntu | ubuntu-minimal-2004-lts |
Ubuntu 20.04 LTS (minimal installation) |
Ubuntu | ubuntu-2004-lts |
Ubuntu 20.04 LTS (full installation) |
Debian | debian-11 |
Debian 11 (Bullseye) |
Debian | debian-10 |
Debian 10 (Buster) |
CentOS/RHEL | centos-7 |
CentOS 7 |
CentOS/RHEL | rhel-8 |
Red Hat Enterprise Linux 8 |
Disk types Copied
The following are common disk types.
Type | Description |
---|---|
pd-standard |
Standard persistent disk (HDD, lowest cost) |
pd-balanced |
Balanced persistent disk (SSD, good performance/cost ratio) |
pd-ssd |
SSD persistent disk (highest performance) |
Zone examples Copied
The following are common zone examples.
Region | Zone | Area |
---|---|---|
US regions | us-central1-a , us-central1-b , us-central1-c |
Iowa |
US regions | us-east1-a , us-east1-b , us-east1-c |
South Carolina |
US regions | us-west1-a , us-west1-b , us-west1-c |
Oregon |
Europe regions | europe-west1-a , europe-west1-b , europe-west1-c |
Belgium |
Europe regions | europe-west2-a , europe-west2-b , europe-west2-c |
London |
Asia regions | asia-east1-a , asia-east1-b , asia-east1-c |
Taiwan |
Asia regions | asia-southeast1-a , asia-southeast1-b , asia-southeast1-c |
Singapore |
Usage example Copied
Basic instance Copied
module "web_server" {
source = "../../modules/gcp/instance"
gcp_project_id = "my-project-123"
gcp_zone = "us-central1-a"
vm_name = "web-server-01"
vm_type = "e2-medium"
vm_image_family = "ubuntu-minimal-2204-lts"
vm_image_project = "ubuntu-os-cloud"
network_name = "default"
subnetwork_name = "default"
ssh_user = "ubuntu"
ssh_public_key_path = "./id_rsa.pub"
# Service Account Configuration (Required)
gcp_service_account_email = "web-server-sa@my-project-123.iam.gserviceaccount.com"
gcp_service_account_scopes = ["cloud-platform"]
vm_labels = {
environment = "production"
purpose = "webserver"
team = "engineering"
}
}
Custom configuration Copied
module "app_server" {
source = "../../modules/gcp/instance"
gcp_project_id = var.gcp_project_id
gcp_zone = "us-central1-b"
vm_name = "app-server-01"
vm_type = "n2-standard-2"
vm_image_family = "ubuntu-2204-lts"
vm_image_project = "ubuntu-os-cloud"
vm_disk_size = 50
vm_disk_type = "pd-ssd"
vm_status = "RUNNING"
network_name = "my-custom-network"
subnetwork_name = "my-custom-subnet"
ssh_user = "appuser"
ssh_public_key_path = var.ssh_public_key_path
# Service Account Configuration (Required)
gcp_service_account_email = var.gcp_service_account_email
gcp_service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
vm_labels = {
environment = "staging"
purpose = "application"
team = "development"
cost_center = "engineering"
}
}
Outputs Copied
Name | Description |
---|---|
vm_name | VM instance name |
external_ip | External IP address |
internal_ip | Internal IP address |
service_account_email | Service account email attached to instance |
GCP Firewall module Copied
This module creates Google Cloud firewall rules to control the network traffic in VPC networks.
Requirements Copied
Aside from the common Terraform Google Cloud module requirements, this module also specifically requires:
- Configured GCP credentials.
Variables Copied
Name | Description | Type | Default | Required |
---|---|---|---|---|
name | Name of the firewall rule | string | yes | |
network | Name of VPC network | string | yes | |
protocol | Protocol (tcp, udp, icmp, all) | string | yes | |
direction | Traffic direction (INGRESS, EGRESS) | string | “INGRESS” | no |
ports | List of ports or port ranges | list(string) | [] | no |
source_ranges | List of source IP ranges | list(string) | [] | no |
target_tags | List of target network tags | list(string) | [] | no |
source_tags | List of source network tags | list(string) | [] | no |
priority | Rule priority (0-65534) | number | 1000 | no |
Protocol options Copied
tcp
- TCP protocoludp
- UDP protocolicmp
- ICMP protocolall
- All protocols (equivalent to IP protocol)
Direction options Copied
INGRESS
- inbound traffic rulesEGRESS
- outbound traffic rules
Port format examples Copied
Type | Ports |
---|---|
Individual ports | ports = ["22", "80", "443"] |
Port ranges | ports = ["7000-7100", "8080-8090"] |
Mixed ports and ranges | ports = ["22", "80", "443", "7000-7100"] |
Usage examples Copied
Basic web traffic rule Copied
module "web_firewall" {
source = "../../modules/gcp/firewall"
name = "allow-web-traffic"
network = "default"
protocol = "tcp"
ports = ["80", "443"]
source_ranges = ["0.0.0.0/0"]
direction = "INGRESS"
}
SSH access rule Copied
module "ssh_firewall" {
source = "../../modules/gcp/firewall"
name = "allow-ssh"
network = "default"
protocol = "tcp"
ports = ["22"]
source_ranges = ["10.0.0.0/8"]
target_tags = ["ssh-server"]
direction = "INGRESS"
}
Custom application rule Copied
module "app_firewall" {
source = "../../modules/gcp/firewall"
name = "allow-geneos-gateway"
network = "my-custom-network"
protocol = "tcp"
ports = ["7000-7100"]
source_ranges = ["192.168.1.0/24"]
target_tags = ["geneos-gateway"]
direction = "INGRESS"
}
Outputs Copied
Name | Description |
---|---|
name | Firewall rule name |
id | Firewall rule resource ID |
Priority guidelines Copied
The firewall rule priority determines which rule is evaluated first when multiple rules apply to the same network traffic. It is an integer from 0 to 65535, where lower values indicate higher priorities.
- 0-999 — indicates high priority, overriding lower priority rules.
- 1000 — the default priority, if no priority was defined during rule creation
- 1001-65534 — indicates lower priority.
Common Deployment Module Copied
A universal Terraform module for executing Ansible playbooks against target hosts using Terraform’s local-exec provisioner. This module provides a bridge between Terraform infrastructure provisioning and Ansible configuration management.