Skip to main content

Overview

The Shipyard Terraform modules are battle-tested, reusable infrastructure components designed for AWS. Each module follows best practices for security, high availability, and cost optimization.

Available Modules

VPC

Complete VPC with public/private subnets, NAT gateways, and VPC endpoints

EKS

Amazon EKS cluster with managed node groups, OIDC provider, and IAM roles

RDS

PostgreSQL/MySQL RDS instances with security groups and automated backups

Vault

HashiCorp Vault AWS resources with KMS auto-unseal and DynamoDB backend

EC2

EC2 instances with optional ALB, Tailscale, and HTTPS support

State

S3 and DynamoDB for Terraform remote state with locking

Quick Start

Using a Module

Reference modules directly from GitHub:
module "vpc" {
  source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=v1.0.0"

  vpc_name           = "production-vpc"
  vpc_cidr           = "10.0.0.0/16"
  aws_region         = "us-east-1"
  availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]

  public_subnet_cidrs  = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]

  enable_nat_gateway = true
  single_nat_gateway = false

  tags = {
    Environment = "production"
    Team        = "platform"
  }
}

Module Versioning

All modules support Git ref-based versioning:
# Use a specific version tag
source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=v1.0.0"

# Use a branch
source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=main"

# Use a commit SHA
source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=abc123"
Always pin to specific version tags in production to ensure reproducible deployments.

Module Organization

Each module follows a consistent structure:
terraform-modules/
├── vpc/
│   ├── main.tf           # Primary resources
│   ├── variables.tf      # Input variables
│   ├── outputs.tf        # Output values
│   ├── versions.tf       # Provider requirements
│   └── README.md         # Module documentation
├── eks/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   └── README.md
└── ...

Common Patterns

Composing Modules

Modules are designed to work together:
# Create VPC
module "vpc" {
  source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=v1.0.0"
  
  vpc_name           = "production"
  vpc_cidr           = "10.0.0.0/16"
  aws_region         = "us-east-1"
  availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
  
  public_subnet_cidrs  = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
}

# Create EKS cluster in the VPC
module "eks" {
  source = "[email protected]:opsnorth/terraform-modules.git//eks?ref=v1.0.0"
  
  cluster_name       = "production-eks"
  kubernetes_version = "1.34"
  private_subnet_ids = module.vpc.private_subnet_ids
}

# Create RDS instance in the VPC
module "rds" {
  source = "[email protected]:opsnorth/terraform-modules.git//rds?ref=v1.0.0"
  
  identifier = "production-db"
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
  
  allowed_security_group_ids = [module.eks.cluster_security_group_id]
}

Using Outputs

Modules expose outputs for cross-module references:
# VPC outputs
output "vpc_id" {
  value = module.vpc.vpc_id
}

output "private_subnet_ids" {
  value = module.vpc.private_subnet_ids
}

# EKS outputs
output "cluster_endpoint" {
  value = module.eks.cluster_endpoint
}

output "oidc_provider_arn" {
  value = module.eks.oidc_provider_arn
}

Requirements

Terraform Version

All modules require Terraform >= 1.0:
terraform {
  required_version = ">= 1.0"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.0"
    }
  }
}

AWS Provider

Configure the AWS provider in your root module:
provider "aws" {
  region = "us-east-1"
  
  default_tags {
    tags = {
      Terraform   = "true"
      Environment = "production"
      Project     = "shipyard"
    }
  }
}

AWS Credentials

Set AWS credentials using one of these methods:
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1"

Module Features

Security Best Practices

  • RDS: Encrypted storage by default
  • EBS: Encrypted root volumes
  • S3: Server-side encryption (AES256)
  • DynamoDB: Encryption enabled
  • VPC: Private subnets for workloads
  • Security Groups: Least privilege rules
  • NetworkPolicies: Kubernetes network segmentation
  • VPC Flow Logs: Optional traffic logging
  • IAM: Least privilege roles and policies
  • IRSA: EKS workload identity
  • KMS: Customer-managed encryption keys
  • Secrets: Vault integration for sensitive data
  • Multi-AZ: Resources across availability zones
  • RDS: Multi-AZ deployment option
  • EKS: Node groups in multiple subnets
  • NAT: Multiple NAT gateways for redundancy

Cost Optimization

Development

  • Single NAT gateway
  • t3.micro/t3.small instances
  • Single-AZ RDS
  • gp2 storage

Production

  • Multi-AZ NAT gateways
  • Production instance sizes
  • Multi-AZ RDS
  • gp3 storage with provisioned IOPS

Complete Example

Here’s a complete infrastructure setup using multiple modules:
terraform {
  required_version = ">= 1.0"
  
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "production/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-state-lock"
    encrypt        = true
  }
}

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

# State backend
module "state" {
  source = "[email protected]:opsnorth/terraform-modules.git//state?ref=v1.0.0"
  
  environment = "production"
}

# VPC
module "vpc" {
  source = "[email protected]:opsnorth/terraform-modules.git//vpc?ref=v1.0.0"
  
  vpc_name           = "production-vpc"
  vpc_cidr           = "10.0.0.0/16"
  aws_region         = "us-east-1"
  availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
  
  public_subnet_cidrs  = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
  
  enable_nat_gateway = true
  single_nat_gateway = false
  
  enable_s3_endpoint       = true
  enable_dynamodb_endpoint = true
}

# EKS
module "eks" {
  source = "[email protected]:opsnorth/terraform-modules.git//eks?ref=v1.0.0"
  
  cluster_name       = "production-eks"
  kubernetes_version = "1.34"
  private_subnet_ids = module.vpc.private_subnet_ids
  
  primary_node_group_instance_types = ["m5.large"]
  primary_node_group_desired_size   = 3
  primary_node_group_min_size       = 3
  primary_node_group_max_size       = 10
}

# RDS
module "rds" {
  source = "[email protected]:opsnorth/terraform-modules.git//rds?ref=v1.0.0"
  
  identifier = "production-db"
  db_name    = "appdb"
  username   = "admin"
  
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.private_subnet_ids
  
  instance_class    = "db.t3.medium"
  allocated_storage = 100
  
  multi_az                      = true
  backup_retention_period       = 30
  performance_insights_enabled  = true
  
  allowed_security_group_ids = [module.eks.cluster_security_group_id]
}

# Vault
module "vault" {
  source = "[email protected]:opsnorth/terraform-modules.git//vault?ref=v1.0.0"
  
  cluster_name      = "production-eks"
  environment       = "production"
  oidc_provider_arn = module.eks.oidc_provider_arn
  oidc_provider_url = module.eks.oidc_provider_url
}

outputs {
  vpc_id              = module.vpc.vpc_id
  eks_cluster_name    = module.eks.cluster_id
  rds_endpoint        = module.rds.db_instance_endpoint
  vault_kms_key_id    = module.vault.kms_key_id
}

Getting Help

Module Documentation

Each module has detailed README with examples, inputs, and outputs

GitHub Issues

Report bugs or request features in the repository

Terraform Docs

Official Terraform documentation for advanced usage

AWS Documentation

AWS service documentation for resource details

Next Steps

1

Choose Your Modules

Review the available modules and identify which ones you need for your infrastructure
2

Set Up State Backend

Create the state backend using the State module before deploying other resources
3

Deploy Core Infrastructure

Start with VPC and EKS for the foundation
4

Add Data Layer

Deploy RDS for databases and Vault for secrets management
5

Review Examples

Check the full infrastructure deployment guide in Infrastructure Overview

Build docs developers (and LLMs) love