Provision an AWS VPC and Security Group with Terraform

Putting an instance in its own VPC means four Terraform resources: a VPC, a subnet, a security group, and the instance wired to all three. Here's the setup that opens only port 80 to the world.

DevOps Engineerawsec2vpc

The pieces

The Terraform

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = { Name = "web-vpc" }
}

resource "aws_subnet" "main" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
}

resource "aws_security_group" "web" {
  name   = "web"
  vpc_id = aws_vpc.main.id

  ingress {                       # only port 80, from anywhere
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {                        # allow all outbound
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_instance" "web" {
  ami                    = data.aws_ami.default.id
  instance_type          = "t3.micro"
  subnet_id              = aws_subnet.main.id          # in the subnet
  vpc_security_group_ids = [aws_security_group.web.id] # using the SG
}

The details that matter

Security group rules and common mistakes

A security group is stateful: if you allow an inbound request, the response is automatically allowed back out - no matching egress rule needed. Each rule lists ports plus a source, and the source can be a CIDR (cidr_blocks = ["10.0.0.0/16"]) or another security group id, which is the cleaner way to let one tier talk to another.

The mistakes that bite:

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

How do I create a VPC and security group in Terraform?

Declare aws_vpc (a CIDR like 10.0.0.0/16), an aws_subnet inside it, an aws_security_group with the ingress rules you want, then set the instance's subnet_id and vpc_security_group_ids to wire it to both.

How do I open only one port in an AWS security group?

Add a single ingress block for that port (e.g. from_port/to_port 80, protocol tcp, cidr_blocks 0.0.0.0/0). Security groups deny by default, so only the ports you list are open.

Do I need an egress rule for responses?

No - security groups are stateful, so the response to an allowed inbound request is automatically permitted. Egress rules only govern connections the instance initiates.

Does a security group need to be associated with a VPC?

Yes. A security group always belongs to a specific VPC and can only attach to resources in that same VPC - you cannot share one across VPCs.

What is the difference between a VPC and a security group?

A VPC is the isolated virtual network (subnets, routing); a security group is a stateful virtual firewall attached to resources inside that VPC, controlling inbound and outbound traffic at the instance level.

Keep learning

Fix the Nginx 502 Bad GatewayDevOps projectRecover a Crashed Linux ServiceDevOps projectCorrect a Postgres Port MismatchDevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →