Skip to content

RussellGilmore/red-instance

Repository files navigation

Red Instance

Red EC2 Module

A practical EC2 module — SSM-only by design. No SSH keys are created, stored, or attached; you reach the instance through AWS Session Manager.

Requirements:

  1. Terraform >= 1.15.0
  2. Trivy >= 0.68.2

Trivy can be installed via Homebrew on macOS with the command:

brew install aquasecurity/trivy/trivy

Security posture

  • No SSH key pair — access is via SSM Session Manager. No private key is generated, written to disk, or stored in Terraform state.
  • IMDSv2 required; root EBS volume encrypted
  • Instance role limited to AmazonSSMManagedInstanceCore plus an optional bucket-scoped S3 policy
  • You open only the ingress ports you serve — examples open 80/443, never 22
  • Scanned with Trivy and gitleaks; integration-tested with Terratest

Features

  1. Gives to ability for create a EC2 Instance
  2. EC2 is already setup for SSM Agent to be installed
  3. Dynamically Create Ingress Security Rules
  4. Optionally create all network infrastructure needed for public access
  5. Optionally create public DNS record for the Red Instance
  6. Optionally pass user data into instance creation
  7. Optionally enabled S3 Bucket IAM Role Access

Usage

Self-contained (creates a minimal public VPC) — see examples/complete:

provider "aws" {
  region = "us-east-1"
}

module "instance" {
  source = "RussellGilmore/red-instance/aws"

  project_name  = "my-project"
  instance_name = "web"

  ingress_rules = [{
    description = "HTTPS from anywhere"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }]
}

Connect with: aws ssm start-session --target <instance_id>.

To place the instance in an existing network (e.g. red-network), set create_vpc = false and pass vpc_id/subnet_id — see examples/with-network.

Requirements

Name Version
terraform >= 1.15.0
aws >= 6.47.0

Providers

Name Version
aws >= 6.47.0

Modules

No modules.

Resources

Name Type
aws_eip.red_instance_eip resource
aws_iam_instance_profile.red_instance_profile resource
aws_iam_role.red_role resource
aws_iam_role_policy.s3_bucket_policy resource
aws_iam_role_policy_attachment.red_ssm_policy_attachment resource
aws_instance.red-instance resource
aws_internet_gateway.igw resource
aws_route53_record.red_instance_dns resource
aws_route_table.public resource
aws_route_table_association.public resource
aws_security_group.red_sg resource
aws_subnet.public resource
aws_vpc.main resource
aws_ami.red_ami data source
aws_route53_zone.zone data source

Inputs

Name Description Type Default Required
additional_tags Additional tags to apply to all resources created by this module. map(string) {} no
allocate_eip Controls whether an Elastic IP should be allocated. bool true no
ami_name The name (or name pattern) of the AMI to use for the instance. string "ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-arm64-server-20250610" no
ami_owner The owner account ID of the AMI. string "099720109477" no
apex_domain Apex domain whose hosted zone holds the DNS record. string "" no
availability_zone Availability zone for the created subnet. Leave empty for default placement. string "" no
create_vpc Create a minimal public VPC (single subnet + IGW) for the instance. Set false to place the instance in an existing VPC via vpc_id/subnet_id. bool true no
disable_api_stop Controls whether API stop is disabled. bool false no
disable_api_termination Controls whether API termination is disabled. bool false no
dns_name FQDN for the public DNS record. string "" no
enable_public_dns Create a public Route53 A record pointing at the instance's EIP. bool false no
enable_s3_bucket_policy Attach an S3 access policy (scoped to s3_bucket_name) to the instance role. bool false no
ingress_rules List of ingress rules for the instance security group. Access is via SSM Session Manager by default; only open inbound ports you actually serve (e.g. 80/443).
list(object({
description = string
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
n/a yes
instance_name The name of the instance. string n/a yes
instance_tags Tags to apply only to the EC2 instance resource. map(string) {} no
instance_type The instance type to use for the instance. string "t4g.small" no
project_name Project name used for naming and the Project tag. string n/a yes
s3_bucket_name Name of the S3 bucket the instance role may access. string "" no
subnet_id ID of an existing subnet to use when create_vpc is false. string "" no
user_data_script_path Path to a user data script to run on first boot. string "" no
volume_size The size of the root volume in GB. number 30 no
vpc_id ID of an existing VPC to use when create_vpc is false. string "" no

Outputs

Name Description
instance_id The ID of the EC2 instance.
public_dns The public DNS name of the instance.
public_ip The public IP address of the instance (EIP when allocated).
security_group_id The ID of the instance security group.
subnet_id The ID of the created subnet, or a note when an existing subnet was supplied.
vpc_id The ID of the created VPC, or a note when an existing VPC was supplied.

About

A simple standalone AWS EC2 Terraform infrastructure module that can deployed in preexisiting network infrastructure or can setup it's own public network configuration.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors