How to Use Terraform to Launch an EC2 Instance with Security Groups and Key Pairs

Launching EC2 instances manually through the AWS console gets old fast. This Terraform EC2 instance tutorial shows DevOps engineers, cloud architects, and AWS administrators how to automate EC2 deployments using infrastructure as code.

You’ll learn to create reusable, version-controlled infrastructure that scales with your needs. This guide walks you through AWS Terraform security groups configuration and Terraform SSH key pairs setup, so your instances stay secure from day one.

We’ll cover setting up your Terraform development environment with the AWS provider, creating robust security group rules that protect your instances, and configuring SSH access through proper key pair management. By the end, you’ll have a complete EC2 instance Terraform configuration that you can deploy, modify, and tear down with simple commands.

Set Up Your Terraform Development Environment

Install Terraform on your local machine

Getting Terraform installed is your first step toward automating AWS infrastructure. Download the latest version from HashiCorp’s official website, matching your operating system. For Windows users, extract the executable to a folder in your PATH. Mac users can install via Homebrew with brew install terraform. Linux users can download the binary and move it to /usr/local/bin/. Run terraform --version to confirm installation works properly.

Configure AWS CLI credentials and permissions

Your Terraform EC2 instance tutorial requires proper AWS authentication. Install the AWS CLI and run aws configure to set up your access key ID and secret access key. Create an IAM user with programmatic access and attach policies like AmazonEC2FullAccess and AmazonVPCFullAccess. Store credentials in ~/.aws/credentials or use environment variables. Never hardcode credentials directly in your Terraform files for security reasons.

Create and organize your project directory structure

Organizing your Terraform AWS provider setup properly saves headaches later. Create a root directory for your project with subdirectories for modules, environments, and configurations. Structure it like: terraform-ec2/main.tf, terraform-ec2/variables.tf, terraform-ec2/outputs.tf, and terraform-ec2/terraform.tfvars. This clean organization makes your EC2 instance Terraform configuration maintainable and scalable as your infrastructure grows.

Verify connectivity to AWS services

Testing your connection prevents deployment failures down the road. Run aws sts get-caller-identity to verify your credentials work correctly. Check that your IAM user has the right permissions by listing EC2 instances with aws ec2 describe-instances. Initialize your Terraform project with terraform init to download the AWS provider. This validation step confirms your setup is ready for launching EC2 instances and managing AWS infrastructure automation through Terraform.

Define Essential AWS Provider Configuration

Specify the AWS provider and required version

Setting up your Terraform AWS provider configuration is the foundation of any successful EC2 deployment. Start by creating a versions.tf file to define the required Terraform version and AWS provider constraints. This approach ensures consistent deployments across different environments and prevents version conflicts that could break your infrastructure code.

terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Set your target AWS region and availability zone

Your AWS provider block determines where your EC2 instance will be deployed. Choose regions based on your users’ proximity, compliance requirements, and service availability. Popular choices include us-east-1 for North America or eu-west-1 for Europe. Always specify availability zones for better resource distribution and disaster recovery planning.

provider "aws" {
  region = "us-east-1"
  
  default_tags {
    tags = {
      Environment = "development"
      Project     = "terraform-ec2-tutorial"
    }
  }
}

Configure authentication methods for secure access

Terraform supports multiple AWS authentication methods for secure access. The most common approaches include AWS CLI profiles, environment variables, or IAM roles for EC2. For local development, configure AWS CLI with aws configure and use named profiles. For production environments, leverage IAM roles attached to EC2 instances or CI/CD systems to avoid hardcoding credentials in your Terraform configuration files.

provider "aws" {
  region  = "us-east-1"
  profile = "terraform-user"
}

Create Security Groups for Network Protection

Define inbound traffic rules for SSH and application access

Create targeted AWS Terraform security groups that control exactly who can connect to your EC2 instance. Start by defining SSH access on port 22 for your specific IP address or trusted networks. Add HTTP (port 80) and HTTPS (port 443) rules for web applications. Use CIDR blocks like 0.0.0.0/0 for public access or restrict to specific IP ranges for enhanced security.

resource "aws_security_group" "web_sg" {
  name_prefix = "web-security-group"
  description = "Security group for web server"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["YOUR_IP/32"]
    description = "SSH access"
  }

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    description = "HTTP access"
  }
}

Configure outbound traffic permissions

Set up outbound rules to control what your EC2 instance can access on the internet. Most applications need unrestricted outbound access for package updates and external API calls. Define explicit egress rules for better security posture, allowing specific ports and protocols rather than blanket permissions.

egress {
  from_port   = 0
  to_port     = 0
  protocol    = "-1"
  cidr_blocks = ["0.0.0.0/0"]
  description = "All outbound traffic"
}

egress {
  from_port   = 443
  to_port     = 443
  protocol    = "tcp"
  cidr_blocks = ["0.0.0.0/0"]
  description = "HTTPS outbound"
}

Add descriptive tags for resource management

Apply consistent tags to your Terraform security group rules for easy identification and cost tracking. Include environment, project name, owner, and creation date tags. These tags help with AWS resource management, billing allocation, and automated cleanup processes.

tags = {
  Name        = "web-server-sg"
  Environment = "production"
  Project     = "webapp"
  Owner       = "devops-team"
  CreatedBy   = "terraform"
}

Reference security groups in your main configuration

Link your security groups to EC2 instances using the resource reference syntax. Use aws_security_group.web_sg.id to dynamically reference security group IDs. This approach creates proper dependencies and ensures Terraform deploys resources in the correct order during your EC2 instance Terraform configuration deployment.

resource "aws_instance" "web_server" {
  ami                    = "ami-0abcdef1234567890"
  instance_type          = "t3.micro"
  vpc_security_group_ids = [aws_security_group.web_sg.id]
  
  tags = {
    Name = "web-server"
  }
}

Generate and Configure SSH Key Pairs

Create AWS key pairs through Terraform resources

Setting up SSH key pairs for your EC2 instances requires the aws_key_pair resource in your Terraform configuration. You can generate a new key pair using the tls_private_key resource, which creates both private and public keys programmatically. This approach ensures your Terraform SSH key pairs are version-controlled and reproducible across environments.

resource "tls_private_key" "ec2_key" {
  algorithm = "RSA"
  rsa_bits  = 4096
}

resource "aws_key_pair" "ec2_keypair" {
  key_name   = "my-ec2-key"
  public_key = tls_private_key.ec2_key.public_key_openssh
}

resource "local_file" "private_key" {
  content  = tls_private_key.ec2_key.private_key_pem
  filename = "${path.module}/my-ec2-key.pem"
}

Import existing public keys for authentication

When you already have SSH keys, import them using the public_key parameter in the aws_key_pair resource. Read existing public keys from files using the file() function, making it easy to reuse keys across multiple Terraform EC2 instance configurations. This method works perfectly for teams sharing common authentication keys.

resource "aws_key_pair" "existing_keypair" {
  key_name   = "existing-key"
  public_key = file("~/.ssh/id_rsa.pub")
}

Set proper file permissions and storage locations

Private keys must have restricted permissions (600) to prevent unauthorized access. Use the local_file resource with proper file permissions, and consider using Terraform’s sensitive output values to handle private keys securely. Store private keys outside your project directory and add them to .gitignore to avoid accidentally committing sensitive data.

resource "local_file" "private_key_secure" {
  content         = tls_private_key.ec2_key.private_key_pem
  filename        = "${path.module}/keys/private-key.pem"
  file_permission = "0600"
}

Build Your EC2 Instance Configuration

Select the appropriate Amazon Machine Image (AMI)

Choosing the right AMI forms the foundation of your EC2 instance Terraform configuration. AWS provides hundreds of pre-configured images, but most deployments benefit from official Amazon Linux 2 or Ubuntu Server LTS versions for their stability and security updates. You can reference AMIs using data sources to automatically fetch the latest version, or specify exact AMI IDs for consistent deployments across environments.

data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

Choose instance type based on performance requirements

Instance types determine your server’s CPU, memory, storage, and network capacity. The t3.micro instance works well for development and low-traffic applications, while production workloads might require compute-optimized c5 instances or memory-optimized r5 types. Consider your application’s resource demands, expected traffic patterns, and budget constraints when making this decision.

variable "instance_type" {
  description = "EC2 instance type"
  type        = string
  default     = "t3.micro"
}

Associate security groups and key pairs with the instance

Security groups and SSH key pairs protect your EC2 instance from unauthorized access. Reference the security groups created in previous steps using their resource names, and specify your key pair name to enable SSH connectivity. This association happens during instance launch and can’t be changed afterward, so plan carefully.

resource "aws_instance" "web_server" {
  ami                    = data.aws_ami.amazon_linux.id
  instance_type          = var.instance_type
  key_name              = aws_key_pair.main.key_name
  vpc_security_group_ids = [aws_security_group.web.id]
}

Configure storage volumes and networking settings

Root volume configuration controls your instance’s primary storage characteristics. Specify volume size, type (gp2, gp3, or io1), and encryption settings based on your performance and security requirements. Network settings include subnet placement, public IP assignment, and availability zone selection to ensure proper connectivity and redundancy.

resource "aws_instance" "web_server" {
  # ... other configuration ...
  
  root_block_device {
    volume_type           = "gp3"
    volume_size          = 20
    encrypted            = true
    delete_on_termination = true
  }

  subnet_id                   = data.aws_subnet.default.id
  associate_public_ip_address = true
}

Add metadata and tags for identification

Tags help organize and identify your AWS resources across different environments and projects. Include essential tags like Environment, Project, Owner, and CreatedBy for better resource management. User data scripts can automate initial server configuration, software installation, and service startup processes during the first boot.

resource "aws_instance" "web_server" {
  # ... other configuration ...

  user_data = base64encode(<<-EOF
    #!/bin/bash
    yum update -y
    yum install -y httpd
    systemctl start httpd
    systemctl enable httpd
  EOF
  )

  tags = {
    Name        = "terraform-web-server"
    Environment = "development"
    Project     = "terraform-tutorial"
    CreatedBy   = "terraform"
  }
}

Deploy and Validate Your Infrastructure

Run terraform plan to preview changes

Before deploying your Terraform EC2 instance tutorial, always run terraform plan to preview exactly what resources will be created. This command shows you the execution plan without making any actual changes to your AWS EC2 automation Terraform setup. Review the output carefully to ensure your EC2 instance Terraform configuration, Terraform AWS security groups, and Terraform SSH key pairs are configured correctly. The plan output displays resource creation, modification, or destruction details, helping you catch potential issues before deployment.

Execute terraform apply to create resources

Deploy your Terraform infrastructure deployment by running terraform apply. This command creates your EC2 instance, security groups, and key pairs based on your configuration files. Terraform will show you the same plan output and ask for confirmation before proceeding. Type “yes” to confirm and watch as Terraform provisions your AWS EC2 automation Terraform resources. The process typically takes 2-3 minutes, and you’ll see real-time status updates as each resource gets created in your AWS account.

Verify successful EC2 instance launch and connectivity

Check the AWS EC2 console to confirm your instance launched successfully and shows a “running” state. Verify that your Terraform AWS security groups are properly attached and configured with the correct inbound rules. Note the instance’s public IP address, which you’ll need for SSH access. Your EC2 instance management Terraform deployment should display all resource details in the console, including the associated key pair and security group configurations that enable secure connectivity.

Test SSH access using your configured key pair

Connect to your newly launched instance using SSH and your Terraform SSH key pairs. Run ssh -i /path/to/your-private-key.pem ec2-user@your-instance-public-ip to establish a secure connection. If you can successfully log in and see the command prompt, your launch EC2 with Terraform deployment is working correctly. Test basic commands like ls and pwd to confirm full functionality. Your Terraform security group rules should allow SSH traffic on port 22 while blocking unauthorized access from other sources.

Manage and Maintain Your Terraform Infrastructure

Implement state file backup and versioning strategies

Protecting your Terraform state file is crucial for maintaining infrastructure consistency across team environments. Store your state remotely using S3 with versioning enabled and DynamoDB for state locking to prevent concurrent modifications. Configure backend settings in your Terraform configuration to automatically handle state synchronization. Regular backups ensure you can recover from accidental deletions or corruption, especially when managing critical EC2 instance infrastructure deployments.

Update and modify existing resources safely

Making changes to your EC2 instance Terraform configuration requires careful planning to avoid service disruption. Always run terraform plan before applying modifications to preview exactly what changes will occur to your infrastructure. Use Terraform’s built-in resource targeting with -target flags when you need to update specific components like security group rules or instance types. Test changes in development environments first, and consider using blue-green deployment strategies for critical production systems.

Clean up resources using terraform destroy when needed

Proper resource cleanup prevents unnecessary AWS charges and maintains clean infrastructure environments. Run terraform destroy to remove all resources defined in your configuration, including EC2 instances, security groups, and key pairs. Before destroying, verify which resources will be affected by reviewing the destruction plan output. For selective cleanup, use resource targeting or remove specific resources from your configuration files and run terraform apply to update the state accordingly.

Setting up EC2 instances with Terraform gives you the power to manage your cloud infrastructure like code, making deployments consistent and repeatable. You’ve learned how to configure your development environment, set up AWS providers, create security groups that protect your resources, handle SSH key pairs securely, and build robust EC2 configurations. These building blocks work together to create a solid foundation for your cloud infrastructure.

The real magic happens when you start treating your infrastructure as a living, breathing codebase that you can version, review, and deploy with confidence. Remember to regularly validate your deployments and keep your Terraform state files secure. Start small with a single instance, get comfortable with the workflow, and then expand to more complex setups. Your future self will thank you for taking the time to master these fundamentals now.