This is how I do it.
Explore the docs Β»
Report Bug
.
Request Feature
Ben's Terraform AWS Account Defaults Module. Configures various defaults and network for your AWS account. Non-optionally sets basic account-wide billing alerts to help avoid run-away costs.
- EC2 Serial Console Access ENABLED by Default
- EBS Default KMS Key set to the AWS Managed KMS Key
- EBS Encryption ENABLED by Default
- πΈ Note potential costs from KMS @ $0.03 per 10,000 requests
- ECS EC2 Provisioned Trunking DISABLED by Default
- ECS Container Insights ENABLED by Default
- πΈ Note potential costs from CloudWatch custom Metrics @ $5.40/Service/Month
- IAM Allow Users to Change their own Password ENABLED
- IAM Hard Password Expiry DISABLED
- IAM Max Password Age 90 Days
- IAM Min Password Length 32
- IAM Password Reuse Prevention for the last 5 passwords
- IAM Password Complexity lowercase, uppercase, numbers, symbols all required
- VPC User-specified network
- πΈπ¨Possible configuration costs from NAT Gateways @ $32.85/nat/month. See more in the usage and cost sections below.
- πΈ Note potential costs from IPv4 Addresses
The basic defaults are straight forward with variations on network configuration presenting various options. See the Costs section for the implications of network topology on cost.
module "context" {
source = "bendoerr-terraform-modules/context/null"
version = "xxx"
namespace = "btm"
role = "production"
region = "us-east-1"
project = "defaults"
}
module "defaults" {
source = "bendoerr-terraform-modules/defaults/aws"
version = "xxx"
context = module.context.shared
budget_monthly_limit = 10.00
budget_alert_emails = "[email protected]"
iam_alias_postfix = "core"
network = {
idr = "10.10.0.0/16"
enable_nat = false
one_nat = false
enable_private = false
subnets = [
{
az = "us-east-1a"
public = "10.10.1.0/24"
private = ""
},
]
}
}
output "vpc_id" {
value = module.defaults.vpc_id
}
output "vpc_public_subnet_ids" {
value = module.defaults.vpc_public_subnet_ids
}
For cost, this is my default network configuration. Each ENI assigned within this subnet will have an associated IPv4 address attached to it as well. At the moment this is the most cost-effective solution as there is no charge for active IPv4 address. π¨ However, starting in February 2024 active IPv4 addresses will incur a $0.005/hour charge.
network = {
cidr = "10.10.0.0/16"
enable_nat = false
one_nat = false
enable_private = false
subnets = [
{
az = "us-east-1a"
public = "10.10.1.0/24"
private = ""
},
{
az = "us-east-1b"
public = "10.10.2.0/24"
private = ""
},
{
az = "us-east-1c"
public = "10.10.3.0/24"
private = ""
},
{
az = "us-east-1d"
public = "10.10.4.0/24"
private = ""
},
{
az = "us-east-1e"
public = "10.10.5.0/24"
private = ""
},
{
az = "us-east-1f"
public = "10.10.6.0/24"
private = ""
},
]
}
At a base level this configuration incurs no cost. However, take note of future IPv4 active addresses beginning to cost mention above.
Important Data Transfer Costs to Keep in Mind: While the VPC at rest does not cost, be sure to estimate Data Transfer OUT from AWS to the Internet which is charged at $0.09/GB beyond the first 100GB/per customer for the first 10TB/month. Also note that IPv4 data transferred between Availability Zones within the same region cost $0.01/GB in each direction. IPv6 only incurs this cost if transferred to a different VPC.
Project: With Public Subnets Only
Module path: examples/complete
Name Monthly Qty Unit Monthly Cost
OVERALL TOTAL $0.00
ββββββββββββββββββββββββββββββββββ
27 cloud resources were detected:
β 0 were estimated
β 25 were free, rerun with --show-skipped to see details
β 2 are not supported yet, rerun with --show-skipped to see details
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββ
β Project β Monthly cost β
β£ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ«
β With Public Subnets Only β $0.00 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ»βββββββββββββββ
If for some reason you would like private subnets without access to the internet this configuration can achieve that.
network = {
cidr = "10.10.0.0/16"
enable_nat = false
one_nat = false
enable_private = true
subnets = [
{
az = "us-east-1a"
public = "10.10.1.0/24"
private = "10.10.16.0/20"
},
{
az = "us-east-1b"
public = "10.10.2.0/24"
private = "10.10.32.0/20"
},
{
az = "us-east-1c"
public = "10.10.3.0/24"
private = "10.10.48.0/20"
},
{
az = "us-east-1d"
public = "10.10.4.0/24"
private = "10.10.64.0/20"
},
{
az = "us-east-1e"
public = "10.10.5.0/24"
private = "10.10.80.0/20"
},
{
az = "us-east-1f"
public = "10.10.6.0/24"
private = "10.10.96.0/20"
},
]
}
At a base level this configuration incurs no cost. However, take note of future IPv4 active addresses beginning to cost mention above.
Important Data Transfer Costs to Keep in Mind: While the VPC at rest does not cost, be sure to estimate Data Transfer OUT from AWS to the Internet which is charged at $0.09/GB beyond the first 100GB/per customer for the first 10TB/month. Also note that IPv4 data transferred between Availability Zones within the same region cost $0.01/GB in each direction. IPv6 only incurs this cost if transferred to a different VPC.
Project: With Public & Private Subnets no/NAT
Module path: examples/complete
Name Monthly Qty Unit Monthly Cost
OVERALL TOTAL $0.00
ββββββββββββββββββββββββββββββββββ
40 cloud resources were detected:
β 0 were estimated
β 38 were free, rerun with --show-skipped to see details
β 2 are not supported yet, rerun with --show-skipped to see details
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββ
β Project β Monthly cost β
β£ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ«
β With Public & Private Subnets no/NAT β $0.00 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ»βββββββββββββββ
This is a good starter Public/Private network topology which will use a single NAT in the first availability zone for all subnets. If you are spreading your workload across multiple availability zones for fault tolerance note that in this configuration the NAT Gateway becomes a single point of failure for outbound traffic.
network = {
cidr = "10.10.0.0/16"
enable_nat = true
one_nat = true
enable_private = true
subnets = [
{
az = "us-east-1a"
public = "10.10.1.0/24"
private = "10.10.16.0/20"
},
{
az = "us-east-1b"
public = "10.10.2.0/24"
private = "10.10.32.0/20"
},
{
az = "us-east-1c"
public = "10.10.3.0/24"
private = "10.10.48.0/20"
},
{
az = "us-east-1d"
public = "10.10.4.0/24"
private = "10.10.64.0/20"
},
{
az = "us-east-1e"
public = "10.10.5.0/24"
private = "10.10.80.0/20"
},
{
az = "us-east-1f"
public = "10.10.6.0/24"
private = "10.10.96.0/20"
},
]
}
π¨Using a NAT Gateway costs about $32.85/month to exist. Additionally, NAT Gateway's charge $0.045/1 GB data processed. There is no charge between the NAT Gateway and resources in the same availability zone, however data transfers between the NAT Gateway and resources in different availability zones do incur standard EC2 data transfer charges.
This cost example assumes 50GB of processed data at the NAT and that 4/5ths of that data is being distributed to other availability zones.
Project: With Public & Private Subnets with one NAT
Module path: examples/complete
Name Monthly Qty Unit Monthly Cost
aws_data_transfer.my_region
ββ Intra-region data transfer 80 GB $0.80
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[0]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
OVERALL TOTAL $35.90
ββββββββββββββββββββββββββββββββββ
44 cloud resources were detected:
β 2 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
β 40 were free, rerun with --show-skipped to see details
β 2 are not supported yet, rerun with --show-skipped to see details
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββ
β Project β Monthly cost β
β£ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ«
β With Public & Private Subnets with one NAT β $36 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ»βββββββββββββββ
This is the more robust Public/Private topology that allows for failed regions to not take down NATing.
network = {
cidr = "10.10.0.0/16"
enable_nat = true
one_nat = false
enable_private = true
subnets = [
{
az = "us-east-1a"
public = "10.10.1.0/24"
private = "10.10.16.0/20"
},
{
az = "us-east-1b"
public = "10.10.2.0/24"
private = "10.10.32.0/20"
},
{
az = "us-east-1c"
public = "10.10.3.0/24"
private = "10.10.48.0/20"
},
{
az = "us-east-1d"
public = "10.10.4.0/24"
private = "10.10.64.0/20"
},
{
az = "us-east-1e"
public = "10.10.5.0/24"
private = "10.10.80.0/20"
},
{
az = "us-east-1f"
public = "10.10.6.0/24"
private = "10.10.96.0/20"
},
]
}
π¨Using a NAT Gateway costs about $32.85/month to exist. Additionally, NAT Gateway's charge $0.045/1 GB data processed. There is no charge between the NAT Gateway and resources in the same availability zone, however data transfers between the NAT Gateway and resources in different availability zones do incur standard EC2 data transfer charges.
This cost example assumes 50GB of processed data at the NAT without any need for inter-region data transfer.
Project: With Public & Private Subnets with NAT per AZ
Module path: examples/complete
Name Monthly Qty Unit Monthly Cost
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[0]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[1]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[2]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[3]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[4]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
module.aws_defaults.module.vpc_default.aws_nat_gateway.this[5]
ββ NAT gateway 730 hours $32.85
ββ Data processed 50 GB $2.25
OVERALL TOTAL $210.60
ββββββββββββββββββββββββββββββββββ
63 cloud resources were detected:
β 6 were estimated, all of which include usage-based costs, see https://infracost.io/usage-file
β 55 were free, rerun with --show-skipped to see details
β 2 are not supported yet, rerun with --show-skipped to see details
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ³βββββββββββββββ
β Project β Monthly cost β
β£ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ«
β With Public & Private Subnets with NAT per AZ β $211 β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ»βββββββββββββββ
Name | Version |
---|---|
terraform | >= 0.13 |
aws | ~> 5.0 |
Name | Version |
---|---|
aws | 5.31.0 |
Name | Source | Version |
---|---|---|
iam_account | terraform-aws-modules/iam/aws//modules/iam-account | 5.33.0 |
label_account_alias | bendoerr-terraform-modules/label/null | 0.4.1 |
label_monthly_total | bendoerr-terraform-modules/label/null | 0.4.1 |
label_network | bendoerr-terraform-modules/label/null | 0.4.1 |
vpc_default | terraform-aws-modules/vpc/aws | 5.4.0 |
Name | Type |
---|---|
aws_budgets_budget.monthly_total | resource |
aws_ebs_default_kms_key.default | resource |
aws_ebs_encryption_by_default.default | resource |
aws_ec2_serial_console_access.default | resource |
aws_ecs_account_setting_default.awsvpc_trunking | resource |
aws_ecs_account_setting_default.container_insights | resource |
aws_kms_alias.ebs | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
budget_alert_emails | n/a | set(string) |
n/a | yes |
budget_monthly_limit | n/a | string |
n/a | yes |
context | Shared Context from Ben's terraform-null-context | object({ |
n/a | yes |
iam_alias_postfix | n/a | string |
n/a | yes |
network | n/a | object({ |
{ |
no |
Name | Description |
---|---|
aws_budgets_budget_monthly_total_account | n/a |
aws_budgets_budget_monthly_total_name | n/a |
vpc_azs | n/a |
vpc_id | n/a |
vpc_private_subnet_ids | n/a |
vpc_public_subnet_ids | n/a |
See the open issues for a list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
- If you have suggestions for adding or removing projects, feel free to open an issue to discuss it, or directly create a pull request after you edit the README.md file with necessary changes.
- Please make sure you check your spelling and grammar.
- Create individual PR for each suggestion.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.
- Benjamin R. Doerr - Terraformer - Benjamin R. Doerr - Built Ben's Terraform Modules
Only the latest tagged version is supported.
See SECURITY.md.