diff options
Diffstat (limited to 'infra')
-rw-r--r-- | infra/.terraform.lock.hcl | 67 | ||||
-rw-r--r-- | infra/data.tf | 11 | ||||
-rw-r--r-- | infra/keypair.tf | 4 | ||||
-rw-r--r-- | infra/main.tf | 46 | ||||
-rw-r--r-- | infra/output.tf | 29 | ||||
-rw-r--r-- | infra/rds.tf | 58 | ||||
-rw-r--r-- | infra/sg.tf | 38 | ||||
-rw-r--r-- | infra/variables.tf | 58 | ||||
-rw-r--r-- | infra/versions.tf | 17 | ||||
-rw-r--r-- | infra/vpc.tf | 29 |
10 files changed, 357 insertions, 0 deletions
diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl new file mode 100644 index 0000000..0f121c1 --- /dev/null +++ b/infra/.terraform.lock.hcl | |||
@@ -0,0 +1,67 @@ | |||
1 | # This file is maintained automatically by "terraform init". | ||
2 | # Manual edits may be lost in future updates. | ||
3 | |||
4 | provider "registry.terraform.io/cloudflare/cloudflare" { | ||
5 | version = "3.33.1" | ||
6 | constraints = "~> 3.29" | ||
7 | hashes = [ | ||
8 | "h1:yL+jBzX+P/VabdTwZ1V1+UjI1EH+S1UQtm3U+rZ4XtU=", | ||
9 | "zh:0387f5891f349fb0ef3b68cbbd212c4c1fabb921324cba4dfeda08ad3d91f338", | ||
10 | "zh:3c016161cb8de9fbf1cf7d0d6099fb9c1c0d1e7bcae36a6084285f7fa4726176", | ||
11 | "zh:43ea39ca52688c350fccc0207ae49a88835f8c56bbc437999acc7feb04d365fd", | ||
12 | "zh:6d184850613b26956634ea5a34c7a0dec775747ef400f83dad54ba48d060218e", | ||
13 | "zh:73236e553775b59af1987f6857c68a7c274aea85c21da9e0e8ad6e67ab5318a7", | ||
14 | "zh:753e07cbda96d020d5a1fe09beb322e8efeb2d11450c71d956f1ee03d923410c", | ||
15 | "zh:7e35d6437fd3add22ebecfe457bfe2f46a2ae58358e59f7ccdb22c13a49fce07", | ||
16 | "zh:878d479802ff633e5cc13da6a3b9eb41e572e1320b3ce45662390c8e97167c80", | ||
17 | "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", | ||
18 | "zh:950a7489e0394470fd0589121d1a0602c57164c854229fedb3319b717d9c2e23", | ||
19 | "zh:a2c3a4b14d4686042e8418860cd59a5f9876c56a755ca9530757307b9b9195cf", | ||
20 | "zh:a4dc55555cb79488a8dff002acf4e98061099721571e290b467872f7c30a897f", | ||
21 | "zh:b6148bbc97d375f185a2ab05243a4d45da82f0c67033a461179f8090bb8bfbd4", | ||
22 | "zh:c0d720c316f580a382d9bc2d00a78217b62fbd28e186dc814bc8d75482540ec2", | ||
23 | "zh:dd42c50c4fb93ec390871234f5a52e21aebf91765365c728f3f237c4db4f4748", | ||
24 | ] | ||
25 | } | ||
26 | |||
27 | provider "registry.terraform.io/hashicorp/aws" { | ||
28 | version = "4.52.0" | ||
29 | constraints = ">= 3.73.0, ~> 4.46" | ||
30 | hashes = [ | ||
31 | "h1:Ofm8syFCBU8MFOiU+zg+vnTWkSdozpmvaA9xukNvcBg=", | ||
32 | "zh:00c865de3a0e7643f4e2e5c8d4ba91eee94a46d41090eb134baca6b58c107172", | ||
33 | "zh:1430682e26eba25d8ace19fa780361187f474153e455545235b4fe30637fdcc2", | ||
34 | "zh:1b9a4e5c889bd2022bd59fb924dc78e189f1b7a4fd718fcacda0f0a4cb74d6eb", | ||
35 | "zh:2485260141608f1d386d0f68934092bbf68a27d96f0d83c73222d0382aee02f5", | ||
36 | "zh:2fe67ee94e2df7dabee7e474356f8e907e7c8011533f9d71df8702d59f9060b2", | ||
37 | "zh:37babd1b7ff96ff1f42aa56d7575cacabda6f9f460ff651d70662bfd90076341", | ||
38 | "zh:54aa8d39f22ecab6613169f49d37d2ccfaf417e59dd7a8c8fc6bf92600c3384f", | ||
39 | "zh:5bf4a84b962a8d2da8f4ccf2a7de56fb6c7a1f566e8393b563977fc7872a8740", | ||
40 | "zh:8cb4a51f209a3cc497e53f09188c15c6675697587fe2ea14a6c7fff10c8c8476", | ||
41 | "zh:91f6bdcbb1e36471140982e9048b7ced437d3290b2cc21079e5429cc84fed2fd", | ||
42 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", | ||
43 | "zh:9f8c01c3f677bc64ddefa41e59c6fc98860c11875d7f148af55969d3e3847f77", | ||
44 | "zh:b6b4fc0bd6f3c0adcd9531da3ccf8c25787ccd6ccc568f13ebbff1336d71a9e1", | ||
45 | "zh:d52a428bd92cc319088685ecac63b9f7d12d4cd6725604edb20d0c4f37a9936e", | ||
46 | "zh:e20252a851a0d38548a3c01a006bfc59ee1fc84217bf9eb95b22724769601b2b", | ||
47 | ] | ||
48 | } | ||
49 | |||
50 | provider "registry.terraform.io/hashicorp/random" { | ||
51 | version = "3.4.3" | ||
52 | hashes = [ | ||
53 | "h1:xZGZf18JjMS06pFa4NErzANI98qi59SEcBsOcS2P2yQ=", | ||
54 | "zh:41c53ba47085d8261590990f8633c8906696fa0a3c4b384ff6a7ecbf84339752", | ||
55 | "zh:59d98081c4475f2ad77d881c4412c5129c56214892f490adf11c7e7a5a47de9b", | ||
56 | "zh:686ad1ee40b812b9e016317e7f34c0d63ef837e084dea4a1f578f64a6314ad53", | ||
57 | "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", | ||
58 | "zh:84103eae7251384c0d995f5a257c72b0096605048f757b749b7b62107a5dccb3", | ||
59 | "zh:8ee974b110adb78c7cd18aae82b2729e5124d8f115d484215fd5199451053de5", | ||
60 | "zh:9dd4561e3c847e45de603f17fa0c01ae14cae8c4b7b4e6423c9ef3904b308dda", | ||
61 | "zh:bb07bb3c2c0296beba0beec629ebc6474c70732387477a65966483b5efabdbc6", | ||
62 | "zh:e891339e96c9e5a888727b45b2e1bb3fcbdfe0fd7c5b4396e4695459b38c8cb1", | ||
63 | "zh:ea4739860c24dfeaac6c100b2a2e357106a89d18751f7693f3c31ecf6a996f8d", | ||
64 | "zh:f0c76ac303fd0ab59146c39bc121c5d7d86f878e9a69294e29444d4c653786f8", | ||
65 | "zh:f143a9a5af42b38fed328a161279906759ff39ac428ebcfe55606e05e1518b93", | ||
66 | ] | ||
67 | } | ||
diff --git a/infra/data.tf b/infra/data.tf new file mode 100644 index 0000000..2102273 --- /dev/null +++ b/infra/data.tf | |||
@@ -0,0 +1,11 @@ | |||
1 | data "aws_ami" "debian" { | ||
2 | most_recent = true | ||
3 | owners = ["136693071363"] | ||
4 | |||
5 | filter { | ||
6 | name = "name" | ||
7 | values = ["debian-11-amd64-*"] | ||
8 | } | ||
9 | } | ||
10 | |||
11 | data "aws_availability_zones" "available" {} | ||
diff --git a/infra/keypair.tf b/infra/keypair.tf new file mode 100644 index 0000000..a73a0af --- /dev/null +++ b/infra/keypair.tf | |||
@@ -0,0 +1,4 @@ | |||
1 | resource "aws_key_pair" "framework" { | ||
2 | key_name = "framework" | ||
3 | public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILS2i5/x9r+cv2j2/SUZ2x2fgQeGnJP1I7PUHC0UdWN6 framework" | ||
4 | } | ||
diff --git a/infra/main.tf b/infra/main.tf new file mode 100644 index 0000000..77b8571 --- /dev/null +++ b/infra/main.tf | |||
@@ -0,0 +1,46 @@ | |||
1 | locals { | ||
2 | name = var.name | ||
3 | } | ||
4 | |||
5 | data "aws_subnet" "ec2" { | ||
6 | filter { | ||
7 | name = "availability-zone" | ||
8 | values = [aws_db_instance.mastodon.availability_zone] | ||
9 | } | ||
10 | filter { | ||
11 | name = "subnet-id" | ||
12 | values = module.vpc.public_subnets | ||
13 | } | ||
14 | } | ||
15 | |||
16 | resource "aws_instance" "mastodon" { | ||
17 | ami = data.aws_ami.debian.id | ||
18 | instance_type = var.ec2_instance_type | ||
19 | |||
20 | subnet_id = data.aws_subnet.ec2.id | ||
21 | key_name = "framework" | ||
22 | |||
23 | vpc_security_group_ids = [aws_security_group.backend.id] | ||
24 | |||
25 | root_block_device { | ||
26 | volume_type = "gp3" | ||
27 | // how to resize partition and file system after resizing ebs volume | ||
28 | // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html | ||
29 | volume_size = "30" | ||
30 | tags = { | ||
31 | Name = "${local.name}-root" | ||
32 | } | ||
33 | } | ||
34 | |||
35 | tags = { | ||
36 | Name = local.name | ||
37 | } | ||
38 | |||
39 | lifecycle { | ||
40 | ignore_changes = [ami] | ||
41 | } | ||
42 | } | ||
43 | |||
44 | resource "aws_eip" "mastodon" { | ||
45 | instance = aws_instance.mastodon.id | ||
46 | } | ||
diff --git a/infra/output.tf b/infra/output.tf new file mode 100644 index 0000000..d0d90fa --- /dev/null +++ b/infra/output.tf | |||
@@ -0,0 +1,29 @@ | |||
1 | output "rds_hostname" { | ||
2 | description = "RDS instance hostname" | ||
3 | value = aws_db_instance.mastodon.address | ||
4 | } | ||
5 | |||
6 | output "rds_port" { | ||
7 | description = "RDS instance port" | ||
8 | value = aws_db_instance.mastodon.port | ||
9 | } | ||
10 | |||
11 | output "rds_username" { | ||
12 | description = "RDS instance username" | ||
13 | value = aws_db_instance.mastodon.username | ||
14 | } | ||
15 | |||
16 | output "rds_password" { | ||
17 | description = "RDS instance password" | ||
18 | value = random_password.rds_password.result | ||
19 | sensitive = true | ||
20 | } | ||
21 | |||
22 | output "instance" { | ||
23 | description = "The main EC2 instance." | ||
24 | value = { | ||
25 | arn = aws_instance.mastodon.arn | ||
26 | public_ip = aws_eip.mastodon.public_ip | ||
27 | private_ip = aws_instance.mastodon.private_ip | ||
28 | } | ||
29 | } | ||
diff --git a/infra/rds.tf b/infra/rds.tf new file mode 100644 index 0000000..d9ba204 --- /dev/null +++ b/infra/rds.tf | |||
@@ -0,0 +1,58 @@ | |||
1 | resource "aws_db_parameter_group" "mastodon" { | ||
2 | name = var.name | ||
3 | family = var.rds_parameter_group | ||
4 | } | ||
5 | |||
6 | resource "aws_db_instance" "mastodon" { | ||
7 | identifier = var.name | ||
8 | instance_class = var.rds_instance_class | ||
9 | allocated_storage = var.rds_storage_size | ||
10 | engine = var.rds_engine | ||
11 | engine_version = var.rds_engine_version | ||
12 | username = var.rds_username | ||
13 | password = random_password.rds_password.result | ||
14 | port = var.rds_port | ||
15 | db_subnet_group_name = aws_db_subnet_group.mastodon.name | ||
16 | vpc_security_group_ids = [aws_security_group.rds.id] | ||
17 | parameter_group_name = aws_db_parameter_group.mastodon.name | ||
18 | publicly_accessible = true | ||
19 | skip_final_snapshot = true | ||
20 | |||
21 | backup_retention_period = 7 | ||
22 | performance_insights_enabled = true | ||
23 | } | ||
24 | |||
25 | resource "random_password" "rds_password" { | ||
26 | length = 16 | ||
27 | special = false | ||
28 | } | ||
29 | |||
30 | resource "aws_ssm_parameter" "rds_host" { | ||
31 | name = "/${var.name}/rds/host" | ||
32 | type = "String" | ||
33 | value = aws_db_instance.mastodon.address | ||
34 | } | ||
35 | |||
36 | resource "aws_ssm_parameter" "rds_port" { | ||
37 | name = "/${var.name}/rds/port" | ||
38 | type = "String" | ||
39 | value = aws_db_instance.mastodon.port | ||
40 | } | ||
41 | |||
42 | resource "aws_ssm_parameter" "mastodon_db_name" { | ||
43 | name = "/${local.name}/rds/name" | ||
44 | type = "String" | ||
45 | value = aws_db_instance.mastodon.db_name | ||
46 | } | ||
47 | |||
48 | resource "aws_ssm_parameter" "mastodon_db_user" { | ||
49 | name = "/${local.name}/rds/username" | ||
50 | type = "String" | ||
51 | value = aws_db_instance.mastodon.username | ||
52 | } | ||
53 | |||
54 | resource "aws_ssm_parameter" "mastodon_db_password" { | ||
55 | name = "/${local.name}/rds/password" | ||
56 | type = "SecureString" | ||
57 | value = random_password.rds_password.result | ||
58 | } | ||
diff --git a/infra/sg.tf b/infra/sg.tf new file mode 100644 index 0000000..48d5406 --- /dev/null +++ b/infra/sg.tf | |||
@@ -0,0 +1,38 @@ | |||
1 | # EC 2 | ||
2 | resource "aws_security_group" "backend" { | ||
3 | name = local.name | ||
4 | vpc_id = module.vpc.vpc_id | ||
5 | } | ||
6 | |||
7 | resource "aws_security_group_rule" "backend_ingress_ssh" { | ||
8 | security_group_id = aws_security_group.backend.id | ||
9 | type = "ingress" | ||
10 | protocol = "tcp" | ||
11 | from_port = 22 | ||
12 | to_port = 22 | ||
13 | cidr_blocks = ["0.0.0.0/0"] | ||
14 | } | ||
15 | |||
16 | resource "aws_security_group_rule" "backend_egress_all" { | ||
17 | security_group_id = aws_security_group.backend.id | ||
18 | type = "egress" | ||
19 | protocol = "all" | ||
20 | from_port = 0 | ||
21 | to_port = 0 | ||
22 | cidr_blocks = ["0.0.0.0/0"] | ||
23 | } | ||
24 | |||
25 | # RDS | ||
26 | resource "aws_security_group" "rds" { | ||
27 | name = "${local.name}-db" | ||
28 | vpc_id = module.vpc.vpc_id | ||
29 | } | ||
30 | |||
31 | resource "aws_security_group_rule" "rds_ingress_backend" { | ||
32 | security_group_id = aws_security_group.rds.id | ||
33 | type = "ingress" | ||
34 | protocol = "tcp" | ||
35 | from_port = var.rds_port | ||
36 | to_port = var.rds_port | ||
37 | source_security_group_id = aws_security_group.backend.id | ||
38 | } | ||
diff --git a/infra/variables.tf b/infra/variables.tf new file mode 100644 index 0000000..66c6e5c --- /dev/null +++ b/infra/variables.tf | |||
@@ -0,0 +1,58 @@ | |||
1 | provider "aws" { | ||
2 | region = var.region | ||
3 | } | ||
4 | |||
5 | variable "name" { | ||
6 | description = "Name of the service. It will be used to name EC2, and RDS instances." | ||
7 | default = "mastodon" | ||
8 | } | ||
9 | |||
10 | variable "region" { | ||
11 | default = "us-west-2" | ||
12 | description = "AWS region" | ||
13 | } | ||
14 | |||
15 | # RDS | ||
16 | variable "rds_instance_class" { | ||
17 | default = "db.t3.micro" | ||
18 | } | ||
19 | |||
20 | variable "rds_storage_size" { | ||
21 | default = 20 | ||
22 | } | ||
23 | |||
24 | variable "rds_username" { | ||
25 | default = "mastodon" | ||
26 | } | ||
27 | |||
28 | variable "rds_engine" { | ||
29 | default = "postgres" | ||
30 | } | ||
31 | |||
32 | variable "rds_engine_version" { | ||
33 | default = "13.7" | ||
34 | } | ||
35 | |||
36 | variable "rds_parameter_group" { | ||
37 | default = "default.postgres13" | ||
38 | } | ||
39 | |||
40 | variable "rds_port" { | ||
41 | default = 33060 | ||
42 | } | ||
43 | |||
44 | # EC 2 | ||
45 | variable "ec2_instance_type" { | ||
46 | default = "t3a.medium" | ||
47 | } | ||
48 | |||
49 | variable "site_domain" { | ||
50 | type = string | ||
51 | default = "m.jinwei.me" | ||
52 | } | ||
53 | |||
54 | variable "cloudflare_account_id" { | ||
55 | description = "The Cloudflare UUID for the Account the Zone lives in." | ||
56 | type = string | ||
57 | sensitive = true | ||
58 | } | ||
diff --git a/infra/versions.tf b/infra/versions.tf new file mode 100644 index 0000000..62b3386 --- /dev/null +++ b/infra/versions.tf | |||
@@ -0,0 +1,17 @@ | |||
1 | terraform { | ||
2 | required_providers { | ||
3 | aws = { | ||
4 | source = "hashicorp/aws" | ||
5 | version = "~> 4.46" | ||
6 | } | ||
7 | cloudflare = { | ||
8 | source = "cloudflare/cloudflare" | ||
9 | version = "~> 3.29" | ||
10 | } | ||
11 | } | ||
12 | } | ||
13 | |||
14 | provider "aws" { | ||
15 | alias = "us-east-1" | ||
16 | region = "us-east-1" | ||
17 | } | ||
diff --git a/infra/vpc.tf b/infra/vpc.tf new file mode 100644 index 0000000..6941a06 --- /dev/null +++ b/infra/vpc.tf | |||
@@ -0,0 +1,29 @@ | |||
1 | locals { | ||
2 | cidr_block = "10.32.0.0/16" | ||
3 | subnets = cidrsubnets(local.cidr_block, 4, 4, 4, 4, 4, 4) | ||
4 | subnet_groups = chunklist(local.subnets, 3) | ||
5 | } | ||
6 | |||
7 | module "vpc" { | ||
8 | source = "terraform-aws-modules/vpc/aws" | ||
9 | version = "3.18.1" | ||
10 | |||
11 | name = local.name | ||
12 | cidr = local.cidr_block | ||
13 | azs = data.aws_availability_zones.available.names | ||
14 | private_subnets = local.subnet_groups[0] | ||
15 | public_subnets = local.subnet_groups[1] | ||
16 | enable_dns_hostnames = true | ||
17 | enable_dns_support = true | ||
18 | enable_nat_gateway = false | ||
19 | single_nat_gateway = true | ||
20 | } | ||
21 | |||
22 | resource "aws_db_subnet_group" "mastodon" { | ||
23 | name = var.name | ||
24 | subnet_ids = module.vpc.public_subnets | ||
25 | |||
26 | tags = { | ||
27 | Name = var.name | ||
28 | } | ||
29 | } | ||