Skip to content

Commit

Permalink
feat: aws validator terraform example (#3170)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulbalaji authored Jan 25, 2024
1 parent 72774b3 commit 0e8e169
Show file tree
Hide file tree
Showing 18 changed files with 762 additions and 0 deletions.
2 changes: 2 additions & 0 deletions rust/terraform/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.terraform
.terraform.lock.*
7 changes: 7 additions & 0 deletions rust/terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Terraform Module for Hyperlane Validator

This Terraform module is designed to set up the necessary infrastructure for a Hyperlane validator on AWS. It automates the creation of resources such as ECS clusters, VPCs, subnets, and security groups required for running a validator node.

> **Note:** This module is intended to be an example of running a validator for a core supported network. You may have to modify the validator module to support more advanced configurations. It is recommended to test thoroughly before using in a production environment.
For more information, read the [Deploy with Terraform](https://hyp-v3-docs-git-feat-aws-agent-guide-abacus-works.vercel.app/docs/operate/deploy-with-terraform) documentation.
100 changes: 100 additions & 0 deletions rust/terraform/globals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
provider "aws" {
region = var.aws_region # Set the AWS region for the provider
}

resource "aws_ecs_cluster" "validator_cluster" {
name = "hyperlane-validator-cluster" # Name of the ECS cluster for the validator
}

resource "aws_vpc" "validator_vpc" {
cidr_block = "10.0.0.0/16" # Define the IP range for the VPC
enable_dns_support = true # Enable DNS support in the VPC
enable_dns_hostnames = true # Enable DNS hostnames in the VPC
}

data "aws_availability_zones" "available" {} # Fetch the list of available AZs

resource "aws_subnet" "public_subnet" {
vpc_id = aws_vpc.validator_vpc.id # Associate with the VPC
cidr_block = "10.0.2.0/24" # Define the IP range for the public subnet
availability_zone = data.aws_availability_zones.available.names[0] # Use the first available AZ
map_public_ip_on_launch = true # Automatically assign public IP on instance launch
}

resource "aws_subnet" "validator_subnet" {
vpc_id = aws_vpc.validator_vpc.id # Associate with the VPC
cidr_block = "10.0.1.0/24" # Define the IP range for the validator subnet
availability_zone = data.aws_availability_zones.available.names[0] # Use the first available AZ
map_public_ip_on_launch = false # Do not assign public IP on instance launch
}

resource "aws_internet_gateway" "vpc_igw" {
vpc_id = aws_vpc.validator_vpc.id # Attach the internet gateway to the VPC
}

resource "aws_eip" "nat_gateway_eip" {
domain = "vpc" # Allocate an Elastic IP in the VPC domain
}

resource "aws_nat_gateway" "validator_nat_gateway" {
allocation_id = aws_eip.nat_gateway_eip.id # Associate the EIP with the NAT gateway
subnet_id = aws_subnet.public_subnet.id # Place the NAT gateway in the public subnet
depends_on = [aws_internet_gateway.vpc_igw] # Ensure IGW is created before the NAT gateway
}

resource "aws_route_table" "public_route_table" {
vpc_id = aws_vpc.validator_vpc.id # Associate the route table with the VPC

route {
cidr_block = "0.0.0.0/0" # Route all traffic
gateway_id = aws_internet_gateway.vpc_igw.id # Through the internet gateway
}
}

resource "aws_route_table" "private_route_table" {
vpc_id = aws_vpc.validator_vpc.id # Associate the route table with the VPC

route {
cidr_block = "0.0.0.0/0" # Route all traffic
nat_gateway_id = aws_nat_gateway.validator_nat_gateway.id # Through the NAT gateway
}
}

resource "aws_route_table_association" "public_subnet_association" {
subnet_id = aws_subnet.public_subnet.id # Associate the public subnet
route_table_id = aws_route_table.public_route_table.id # With the public route table
}

resource "aws_route_table_association" "private_subnet_association" {
subnet_id = aws_subnet.validator_subnet.id # Associate the validator subnet
route_table_id = aws_route_table.private_route_table.id # With the private route table
}

resource "aws_security_group" "validator_sg" {
name = "validator-sg" # Name of the security group for the validator
vpc_id = aws_vpc.validator_vpc.id # Associate with the VPC

# prometheus
ingress {
from_port = 9090 # Prometheus metrics port
to_port = 9090
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # Allow traffic from any IP
}

# efs mounting
ingress {
from_port = 2049 # NFS port for EFS
to_port = 2049
protocol = "tcp"
cidr_blocks = [aws_subnet.validator_subnet.cidr_block] # Allow traffic from the validator subnet
}

# all egress
egress {
from_port = 0 # Allow all outbound traffic
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"] # To any IP
}
}
20 changes: 20 additions & 0 deletions rust/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Configure a Hyperlane Validator
# Replaces https://docs.hyperlane.xyz/docs/operate/validators/run-validators
module "your_validator_name" {
source = "./modules/validator"

validator_name = "your-validator-name"
origin_chain_name = "originChainName"

aws_region = var.aws_region
validator_cluster_id = aws_ecs_cluster.validator_cluster.id
validator_subnet_id = aws_subnet.validator_subnet.id
validator_sg_id = aws_security_group.validator_sg.id
validator_nat_gateway_id = aws_nat_gateway.validator_nat_gateway.id

# Disabling the validator task allows you to set up all the required infrastructure
# without running the actual validator yet. This is useful when setting up a validator for
# the first time, so that you can find out the validator address and fund it before it
# performs the announcement transaction.
# validator_task_disabled = true
}
42 changes: 42 additions & 0 deletions rust/terraform/modules/efs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# This resource defines an EFS file system that acts as persistent storage for the validator.
# The `creation_token` is used to ensure idempotent creation of the file system.
resource "aws_efs_file_system" "validator_fs" {
creation_token = var.creation_token # Unique token to guarantee the idempotence of the resource

# Tags are key-value pairs that help with the organization and identification of AWS resources.
tags = {
Name = var.creation_token # Name tag using the creation token for easy identification
}
}

# The EFS access point serves as a custom entry point into the file system.
# It enforces the specified POSIX user and group, and the root directory settings.
resource "aws_efs_access_point" "validator_ap" {
file_system_id = aws_efs_file_system.validator_fs.id # Associates the access point with the file system

# The POSIX user configuration sets the owner's user and group IDs for all file system requests.
posix_user {
gid = var.posix_user_gid # POSIX group ID
uid = var.posix_user_uid # POSIX user ID
}

# The root directory configuration specifies the path and creation settings within the EFS.
root_directory {
path = var.root_directory_path # The path where the root directory is mounted

# The creation info sets the ownership and permissions for the root directory upon creation.
creation_info {
owner_gid = var.posix_user_gid # Group ID of the directory owner
owner_uid = var.posix_user_uid # User ID of the directory owner
permissions = var.root_directory_permissions # Permissions for the root directory
}
}
}

# This resource creates a mount target within a specific subnet, allowing EC2 instances to access the EFS file system.
# The mount target is secured by associating it with one or more security groups.
resource "aws_efs_mount_target" "validator_mt" {
file_system_id = aws_efs_file_system.validator_fs.id # Associates the mount target with the file system
subnet_id = var.subnet_id # The subnet ID where the mount target is placed
security_groups = var.security_group_ids # Security groups that define the access rules for the mount target
}
19 changes: 19 additions & 0 deletions rust/terraform/modules/efs/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
output "file_system_id" {
description = "The ID of the EFS file system"
value = aws_efs_file_system.validator_fs.id
}

output "access_point_id" {
description = "The ID of the EFS access point"
value = aws_efs_access_point.validator_ap.id
}

output "mount_target_id" {
description = "The ID of the EFS mount target"
value = aws_efs_mount_target.validator_mt.id
}

output "access_point_arn" {
description = "The ARN of the EFS access point"
value = aws_efs_access_point.validator_ap.arn
}
38 changes: 38 additions & 0 deletions rust/terraform/modules/efs/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
variable "creation_token" {
description = "Unique string to ensure the idempotent creation of the file system"
type = string
}

variable "subnet_id" {
description = "The ID of the subnet to create the mount target in"
type = string
}

variable "security_group_ids" {
description = "A list of security group IDs to associate with the mount target"
type = list(string)
}

variable "posix_user_gid" {
description = "The POSIX group ID for the EFS access point"
type = number
default = 1000
}

variable "posix_user_uid" {
description = "The POSIX user ID for the EFS access point"
type = number
default = 1000
}

variable "root_directory_path" {
description = "Path to the root directory on the EFS volume"
type = string
default = "/hyperlane_db"
}

variable "root_directory_permissions" {
description = "Permissions to apply to the root directory on the EFS volume"
type = string
default = "700"
}
Loading

0 comments on commit 0e8e169

Please sign in to comment.