1
0

initial commit

This commit is contained in:
xpk
2026-02-13 15:44:24 +08:00
parent 66be8224f4
commit 09ce4c881a
570 changed files with 61807 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
<!-- This readme file is generated with terraform-docs -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 1.3.0 |
| aws | ~> 5.35.0 |
## Providers
| Name | Version |
|------|---------|
| aws | ~> 5.35.0 |
| random | n/a |
| tls | n/a |
## Modules
No modules.
## Resources
| Name | Type |
|------|------|
| [aws_ebs_volume.data-volumes](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ebs_volume) | resource |
| [aws_eip.ec2-eip](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource |
| [aws_instance.ec2-instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource |
| [aws_key_pair.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource |
| [aws_secretsmanager_secret.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret) | resource |
| [aws_secretsmanager_secret_version.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret_version) | resource |
| [aws_volume_attachment.data-volume-attachments](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/volume_attachment) | resource |
| [random_id.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |
| [tls_private_key.this](https://registry.terraform.io/providers/hashicorp/tls/latest/docs/resources/private_key) | resource |
| [aws_default_tags.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/default_tags) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| UseRsaKeyForWindows | Set true to use RSA key for Windows instances | `bool` | `false` | no |
| additional-tags | Additional tags to be assigned on top of provider default tags. Useful for setting backup tags. | `map(string)` | n/a | yes |
| ami-id | Image id of EC2 instance | `string` | n/a | yes |
| asso-eip | Whether to associate Elastic IP | `bool` | n/a | yes |
| asso-public-ip | Whether to associate ephemeral public IP | `bool` | n/a | yes |
| create-ssh-key | Set true to create ssh key and store on secret manager | `bool` | `false` | no |
| data-volumes | Attach additional data volumes | <pre>map(object({<br> size = number<br> type = string<br> }))</pre> | n/a | yes |
| delete-on-termination | Whether to delete volumes on termination | `bool` | `true` | no |
| disable\_secure\_idmsv2 | If set to true, the insecure IDMSv1 will be used. | `bool` | `false` | no |
| ebs-encrypted | Whether to enable EBS encryption | `bool` | `true` | no |
| enable-detail-monitoring | Set true to enable detail monitoring | `bool` | `false` | no |
| enable-termination-protection | Whether to enable prevent accidential deletion of instance | `bool` | `false` | no |
| get\_password\_data | Get password data for windows instance, save in secretsmanager | `bool` | `false` | no |
| instance-name | Name of ec2 instance | `string` | n/a | yes |
| instance-profile | Ec2 instance profile name | `string` | `""` | no |
| instance-type | Instance type | `string` | n/a | yes |
| key-name | Instance ssh key name | `string` | `""` | no |
| kms-key-id | Disk encryption KMS key id | `string` | n/a | yes |
| private-ip | Specify private IP to be used on this instance | `string` | `null` | no |
| root-volume-size | Size of root volume | `number` | n/a | yes |
| root-volume-type | Root volume type | `string` | `"gp3"` | no |
| security-groups | List of security groups for Ec2 instance | `list(string)` | n/a | yes |
| spot-max-price | Max hourly price for spot instance. If greater than zero, spot instance will be used. | `number` | `0` | no |
| subnet-id | Id of subnet to deploy Ec2 instance to | `string` | n/a | yes |
| user-data | Ec2 user-data | `string` | `""` | no |
## Outputs
| Name | Description |
|------|-------------|
| ec2-id-ip | Ec2 instance id and private ip |
| elastic-ip | Ec2 instance EIP |
| instance-id | Ec2 instance id |
| private-ip | Ec2 instance private IP |
| public-ip | Ec2 instance ephemeral public IP |
| ssh-key-name | Ec2 instance ssh key name |
| ssh-key-secret-arn | Secretsmanager arn for ec2 instance ssh key |
---
## Authorship
This module was developed by xpk.
+135
View File
@@ -0,0 +1,135 @@
resource "aws_instance" "ec2-instance" {
ami = var.ami-id
instance_type = var.instance-type
associate_public_ip_address = var.asso-public-ip
// availability_zone = var.az
iam_instance_profile = var.instance-profile
key_name = var.create-ssh-key ? aws_key_pair.this[0].key_name : var.key-name
private_ip = var.private-ip
enable_primary_ipv6 = var.use-ipv6
root_block_device {
encrypted = var.ebs-encrypted
volume_size = var.root-volume-size
volume_type = var.root-volume-type
kms_key_id = var.kms-key-id
delete_on_termination = var.delete-on-termination
# terraform volume_tags is the only way to create volume and tag them in the same operation
# so do not use tagging in root_block_device
}
ebs_optimized = true
subnet_id = var.subnet-id
vpc_security_group_ids = var.security-groups
get_password_data = var.get_password_data
# IMDSv2 requirement
dynamic "metadata_options" {
for_each = var.disable_secure_idmsv2 == false ? { set_idmsv2 : true } : {}
content {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 2
}
}
# spot instance option
dynamic "instance_market_options" {
for_each = var.spot-max-price > 0 ? { use_spot : true } : {}
content {
market_type = "spot"
dynamic "spot_options" {
for_each = { use_spot : true }
content {
max_price = var.spot-max-price
}
}
}
}
disable_api_termination = var.enable-termination-protection
user_data = var.user-data
monitoring = var.enable-detail-monitoring
tags = merge(var.additional-tags, { "Name" : var.instance-name })
volume_tags = merge({ "Name" : "${var.instance-name}-root" }, data.aws_default_tags.this.tags)
# do not redeploy instance when a new ami is released
# do not update volume_tags after initial deployment
lifecycle {
ignore_changes = [ami, volume_tags]
}
}
resource "aws_ebs_volume" "data-volumes" {
for_each = var.data-volumes
availability_zone = aws_instance.ec2-instance.availability_zone
size = each.value["size"]
type = each.value["type"]
iops = try(each.value["iops"], null)
kms_key_id = aws_instance.ec2-instance.root_block_device[0].kms_key_id
encrypted = aws_instance.ec2-instance.root_block_device[0].encrypted
tags = merge(
{ Name : "${var.instance-name}-${each.key}" },
data.aws_default_tags.this.tags
)
}
locals {
a_to_z = split(",", "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z")
}
resource "aws_volume_attachment" "data-volume-attachments" {
count = length(aws_ebs_volume.data-volumes)
volume_id = [for v in aws_ebs_volume.data-volumes : v.id][count.index]
instance_id = aws_instance.ec2-instance.id
device_name = "/dev/xvda${element(local.a_to_z, count.index)}"
}
resource "aws_eip" "ec2-eip" {
count = var.asso-eip ? 1 : 0
instance = aws_instance.ec2-instance.id
domain = "vpc"
}
resource "tls_private_key" "this" {
count = var.create-ssh-key ? 1 : 0
algorithm = var.UseRsaKeyForWindows ? "RSA" : "ED25519"
rsa_bits = var.UseRsaKeyForWindows ? 3072 : null
ecdsa_curve = var.UseRsaKeyForWindows ? null : "P384"
}
resource "aws_key_pair" "this" {
count = var.create-ssh-key ? 1 : 0
key_name = "${var.instance-name}-sshkey"
public_key = tls_private_key.this[0].public_key_openssh
}
resource "random_id" "this" {
byte_length = 2
}
resource "aws_secretsmanager_secret" "this" {
count = var.create-ssh-key ? 1 : 0
name = "${var.instance-name}-sshkey-${random_id.this.dec}"
description = "Private key for ${aws_instance.ec2-instance.id}"
}
resource "aws_secretsmanager_secret_version" "this" {
count = var.create-ssh-key ? 1 : 0
secret_id = aws_secretsmanager_secret.this[0].id
secret_string = jsonencode({
"PrivateKey" = tls_private_key.this[0].private_key_openssh
"WindowsAdminPassword" = var.get_password_data ? rsadecrypt(aws_instance.ec2-instance.password_data, tls_private_key.this[0].private_key_openssh) : ""
})
}
data "aws_default_tags" "this" {
lifecycle {
postcondition {
condition = length(self.tags) >= 1
error_message = "Validation failed: Provider default_tags not set."
}
}
}
+37
View File
@@ -0,0 +1,37 @@
output "ec2-id-ip" {
description = "Ec2 instance id and private ip"
value = {
instance-id = aws_instance.ec2-instance.id
private-ip = aws_instance.ec2-instance.private_ip
}
}
output "instance-id" {
description = "Ec2 instance id"
value = aws_instance.ec2-instance.id
}
output "private-ip" {
description = "Ec2 instance private IP"
value = aws_instance.ec2-instance.private_ip
}
output "ssh-key-name" {
description = "Ec2 instance ssh key name"
value = var.create-ssh-key ? aws_key_pair.this[0].key_name : var.key-name
}
output "ssh-key-secret-arn" {
description = "Secretsmanager arn for ec2 instance ssh key"
value = var.create-ssh-key ? aws_secretsmanager_secret.this[0].arn : null
}
output "elastic-ip" {
description = "Ec2 instance EIP"
value = var.asso-eip ? aws_eip.ec2-eip[0].public_ip : null
}
output "public-ip" {
description = "Ec2 instance ephemeral public IP"
value = var.asso-public-ip ? aws_instance.ec2-instance.public_ip : null
}
+122
View File
@@ -0,0 +1,122 @@
variable "instance-type" {
type = string
description = "Instance type"
}
variable "ami-id" {
type = string
description = "Image id of EC2 instance"
}
variable "asso-public-ip" {
type = bool
description = "Whether to associate ephemeral public IP"
}
variable "instance-profile" {
type = string
default = ""
description = "Ec2 instance profile name"
}
variable "key-name" {
type = string
description = "Instance ssh key name"
default = ""
}
variable "ebs-encrypted" {
type = bool
default = true
description = "Whether to enable EBS encryption"
}
variable "root-volume-size" {
type = number
description = "Size of root volume"
}
variable "root-volume-type" {
type = string
default = "gp3"
description = "Root volume type"
}
variable "kms-key-id" {
type = string
description = "Disk encryption KMS key id"
}
variable "delete-on-termination" {
type = bool
default = true
description = "Whether to delete volumes on termination"
}
variable "subnet-id" {
type = string
description = "Id of subnet to deploy Ec2 instance to"
}
variable "security-groups" {
type = list(string)
description = "List of security groups for Ec2 instance"
}
variable "instance-name" {
type = string
description = "Name of ec2 instance"
}
variable "asso-eip" {
type = bool
description = "Whether to associate Elastic IP"
}
variable "data-volumes" {
type = map(object({
size = number
type = string
}))
description = "Attach additional data volumes"
}
variable "private-ip" {
type = string
default = null
description = "Specify private IP to be used on this instance"
}
variable "additional-tags" {
type = map(string)
description = "Additional tags to be assigned on top of provider default tags. Useful for setting backup tags."
}
variable "disable_secure_idmsv2" {
type = bool
default = false
description = "If set to true, the insecure IDMSv1 will be used."
}
variable "enable-termination-protection" {
type = bool
default = false
description = "Whether to enable prevent accidential deletion of instance"
}
variable "user-data" {
type = string
default = ""
description = "Ec2 user-data"
}
variable "enable-detail-monitoring" {
type = bool
default = false
description = "Set true to enable detail monitoring"
}
variable "spot-max-price" {
type = number
description = "Max hourly price for spot instance. If greater than zero, spot instance will be used."
default = 0
}
variable "create-ssh-key" {
type = bool
default = false
description = "Set true to create ssh key and store on secret manager"
}
variable "UseRsaKeyForWindows" {
type = bool
default = false
description = "Set true to use RSA key for Windows instances"
}
variable "get_password_data" {
type = bool
default = false
description = "Get password data for windows instance, save in secretsmanager"
}
variable use-ipv6 {
type = bool
default = false
description = "Enable primary IPv6 address"
}