From b54e0b209b93bb3860d57e0d1bbc737c2e861371 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Fri, 19 Dec 2025 22:48:19 +0900 Subject: [PATCH 01/27] =?UTF-8?q?feat:=20.gitignore=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..596ea8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/environment/prod/secret.tfvars +/environment/prod/.terraform +/environment/prod/.terraform.lock.hcl +/environment/prod/terraform.tfstate +/environment/prod/terraform.tfstate.backup +/environment/stage/secret.tfvars +/environment/stage/.terraform +/environment/stage/.terraform.lock.hcl +inseong_accessKeys.csv +solid-connection-server-2.pem +.DS_Store \ No newline at end of file From f142fa9013bea7f873b958b378fc44e19ff58b8c Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Fri, 19 Dec 2025 22:49:46 +0900 Subject: [PATCH 02/27] =?UTF-8?q?fix:=20stage=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=9D=98=20terraform=20state=20=EC=A0=95=EB=B3=B4=20ignore=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 596ea8e..b81cce9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ /environment/stage/secret.tfvars /environment/stage/.terraform /environment/stage/.terraform.lock.hcl +/environment/stage/terraform.tfstate +/environment/stage/terraform.tfstate.backup inseong_accessKeys.csv solid-connection-server-2.pem .DS_Store \ No newline at end of file From 649101fb9e8f38e88b1d6b224e1c9e85ff1c86b1 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Fri, 19 Dec 2025 22:51:07 +0900 Subject: [PATCH 03/27] =?UTF-8?q?docs:=20readme=20=EB=94=94=EB=A0=89?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20=EC=B5=9C=EC=8B=A0?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index 16ca9a9..d6aad9f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,34 @@ # solid-connection-infra solid-connection 서비스의 AWS, terraform 기반 IaC 레포지토리입니다. + + +## 디렉토리 구조 +``` +solid-connection-infra/ +├── modules/ +│ └── app_stack/ # [공통 모듈] API Server + RDS 정의 +│ ├── main.tf +│ ├── variables.tf +│ └── outputs.tf +└── environments/ + ├── prod/ # [Prod 환경] + │ ├── main.tf + │ ├── provider.tf + │ ├── variables.tf + │ └── secret.tfvars + ├── stage/ # [Stage 환경] + │ ├── main.tf + │ ├── provider.tf + │ ├── variables.tf + │ └── secret.tfvars + ├── load_test/ # [부하테스트 환경] + │ ├── main.tf + │ ├── provider.tf + │ ├── variables.tf + │ └── secret.tfvars + └── monitoring/ # [Monitoring 환경] (Grafana 단독) + ├── main.tf + ├── provider.tf + ├── variables.tf + └── secret.tfvars +``` \ No newline at end of file From 72cc1071804a525d84db7d16c32c3e4463499150 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:18:36 +0900 Subject: [PATCH 04/27] =?UTF-8?q?feat:=20=EC=9D=B8=EC=8A=A4=ED=84=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=ED=95=A0=20docker=5Fsetup=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/scripts/docker_setup.sh | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 modules/app_stack/scripts/docker_setup.sh diff --git a/modules/app_stack/scripts/docker_setup.sh b/modules/app_stack/scripts/docker_setup.sh new file mode 100644 index 0000000..e6c5b23 --- /dev/null +++ b/modules/app_stack/scripts/docker_setup.sh @@ -0,0 +1,36 @@ +wait_for_apt_lock() { + echo "Checking for apt locks..." + while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || \ + fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || \ + fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do + echo "Waiting for apt lock..." + sleep 5 + done + echo "Apt lock acquired." +} + +# 1. 필수 패키지 설치 +apt-get update +apt-get install -y ca-certificates curl gnupg lsb-release + +# 2. Docker 공식 GPG Key 추가 +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg +chmod a+r /etc/apt/keyrings/docker.gpg + +# 3. Docker Repository 설정 +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ + tee /etc/apt/sources.list.d/docker.list > /dev/null + +# 4. Docker Engine 설치 +apt-get update +apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + +# 5. ubuntu 유저에게 Docker 권한 부여 +usermod -aG docker ubuntu + +# 6. 서비스 시작 및 활성화 +systemctl enable docker +systemctl start docker \ No newline at end of file From 2f1e17f71dc721c82b84bd732f7bf6df33e80b29 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:18:59 +0900 Subject: [PATCH 05/27] =?UTF-8?q?feat:=20=EC=9D=B8=EC=8A=A4=ED=84=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EC=8B=A4=ED=96=89?= =?UTF-8?q?=ED=95=A0=20nginx=5Fsetup=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/scripts/docker_setup.sh | 2 +- modules/app_stack/scripts/nginx_setup.tftpl | 90 +++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 modules/app_stack/scripts/nginx_setup.tftpl diff --git a/modules/app_stack/scripts/docker_setup.sh b/modules/app_stack/scripts/docker_setup.sh index e6c5b23..1254eaa 100644 --- a/modules/app_stack/scripts/docker_setup.sh +++ b/modules/app_stack/scripts/docker_setup.sh @@ -33,4 +33,4 @@ usermod -aG docker ubuntu # 6. 서비스 시작 및 활성화 systemctl enable docker -systemctl start docker \ No newline at end of file +systemctl start docker diff --git a/modules/app_stack/scripts/nginx_setup.tftpl b/modules/app_stack/scripts/nginx_setup.tftpl new file mode 100644 index 0000000..bce1b2e --- /dev/null +++ b/modules/app_stack/scripts/nginx_setup.tftpl @@ -0,0 +1,90 @@ +set -e + +wait_for_apt_lock() { + echo "Checking for apt locks..." + while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || \ + fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || \ + fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do + echo "Waiting for apt lock..." + sleep 5 + done + echo "Apt lock acquired." +} + +# --- 변수 설정 --- +DOMAIN="${domain_name}" +EMAIL="${email}" +CONF_NAME="${conf_file_name}" + +echo "Start Nginx Setup for $DOMAIN with config file: $CONF_NAME" + +# 1. Nginx 및 Certbot 필수 패키지 설치 +apt-get update +apt-get install -y nginx python3 python3-venv libaugeas0 + +# 2. Certbot 설치 (pip 이용) +python3 -m venv /opt/certbot/ +/opt/certbot/bin/pip install --upgrade pip +/opt/certbot/bin/pip install certbot certbot-nginx +ln -s /opt/certbot/bin/certbot /usr/bin/certbot + +# 3. SSL 인증서 발급 (비대화형 모드) +systemctl stop nginx + +certbot certonly --standalone \ + --non-interactive \ + --agree-tos \ + --email "$EMAIL" \ + -d "$DOMAIN" + +echo "Certificate obtained successfully." + +# 4. Nginx 설정 파일 작성 +cat < /etc/nginx/sites-available/$CONF_NAME +server { + listen 80; + server_name $DOMAIN; + location / { + return 301 https://\$host\$request_uri; + } +} + +server { + listen 443 ssl; + server_name $DOMAIN; + + ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem; + + client_max_body_size 10M; + + ssl_protocols TLSv1.2 TLSv1.3; + ssl_prefer_server_ciphers on; + ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"; + ssl_session_cache shared:SSL:10m; + ssl_session_timeout 10m; + ssl_stapling on; + ssl_stapling_verify on; + + location / { + proxy_pass http://127.0.0.1:8080; + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + } +} +EOF + +# 5. 심볼릭 링크 연결 및 기본 설정 삭제 +ln -sf /etc/nginx/sites-available/$CONF_NAME /etc/nginx/sites-enabled/$CONF_NAME +rm -f /etc/nginx/sites-enabled/default + +# 6. 자동 갱신 크론탭 등록 +echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q" | tee -a /etc/crontab > /dev/null + +# 7. Nginx 재시작 +nginx -t +systemctl restart nginx + +echo "Nginx setup complete!" From 35111420dbf5c7899a95d599c5a1a3dc917bd105 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:21:21 +0900 Subject: [PATCH 06/27] =?UTF-8?q?feat:=20=EB=AA=A8=EB=93=88=EB=A1=9C?= =?UTF-8?q?=EC=8D=A8=20app=5Fstack(ec2=20+=20rds)=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/main.tf | 144 +++++++++++++++++++++++++++++++++ modules/app_stack/output.tf | 0 modules/app_stack/variables.tf | 89 ++++++++++++++++++++ 3 files changed, 233 insertions(+) create mode 100644 modules/app_stack/main.tf create mode 100644 modules/app_stack/output.tf create mode 100644 modules/app_stack/variables.tf diff --git a/modules/app_stack/main.tf b/modules/app_stack/main.tf new file mode 100644 index 0000000..ce54071 --- /dev/null +++ b/modules/app_stack/main.tf @@ -0,0 +1,144 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + cloudinit = { + source = "hashicorp/cloudinit" + version = "~> 2.3" + } + mysql = { + source = "petoju/mysql" + version = ">= 3.0" + } + } +} + +provider "mysql" { + endpoint = "127.0.0.1:3306" + username = var.db_username + password = var.db_password +} + +# 1. API Server용 보안 그룹 (SSH 연결 허용) +resource "aws_security_group" "api_sg" { + name = "sc-${var.env_name}-api-sg" + description = "Security Group for API Server" + vpc_id = var.vpc_id + + tags = { + Name = "solid-connection-server-${var.env_name}-sg" + } +} + +# 2. RDS용 보안 그룹 (API Server만 믿음) +resource "aws_security_group" "db_sg" { + name = "sc-${var.env_name}-db-sg" + description = "Security Group for RDS" + vpc_id = var.vpc_id + + tags = { + Name = "solid-connection-${var.env_name}-db-sg" + } +} + +# 3. CloudInit을 이용한 User Data 스크립트 구성 +data "cloudinit_config" "app_init" { + gzip = true # 압축하여 UserData 용량 제한(64KB) 극복 + base64_encode = true # EC2 UserData는 Base64 필수 + + # [Part 1] Docker 설치 스크립트 + part { + content_type = "text/x-shellscript" + content = file("${path.module}/scripts/docker_setup.sh") + filename = "1_docker_install.sh" + } + + # [Part 2] Nginx 설정 스크립트 + part { + content_type = "text/x-shellscript" + content = templatefile("${path.module}/scripts/nginx_setup.tftpl", { + domain_name = var.domain_name + email = var.cert_email + conf_file_name = var.nginx_conf_name + }) + filename = "2_nginx_setup.sh" + } +} + +# 4. API Server (EC2) +resource "aws_instance" "api_server" { + ami = var.ami_id + instance_type = var.instance_type + + vpc_security_group_ids = [aws_security_group.api_sg.id] + + key_name = var.key_name + associate_public_ip_address = true + + # User Data가 변경되면 인스턴스를 새로 만들 것인지 결정, true로 설정하면 스크립트 수정 시 기존 서버를 삭제하고 새 서버를 띄웁니다. + user_data_base64 = data.cloudinit_config.app_init.rendered + + tags = { + Name = "solid-connection-server-${var.env_name}" + } + + user_data_replace_on_change = false # true면 User Data 변경 시 인스턴스 교체 + + lifecycle { + ignore_changes = [ + user_data, + user_data_base64, + user_data_replace_on_change, + + ami, + key_name + ] + } +} + +# 5. RDS +resource "aws_db_instance" "default" { + identifier = var.rds_identifier + allocated_storage = 20 + engine = "mysql" + engine_version = var.db_engine_version + instance_class = var.db_instance_class + username = var.db_username + password = var.db_password + parameter_group_name = var.db_parameter_group_name + copy_tags_to_snapshot = true + skip_final_snapshot = true + vpc_security_group_ids = [aws_security_group.db_sg.id] + + storage_encrypted = true + kms_key_id = var.kms_key_arn + + tags = { + Name = var.rds_identifier + } +} + +# 6. MySQL 추가 유저 생성 +resource "mysql_user" "users" { + for_each = var.additional_db_users + + user = each.key + host = "%" + plaintext_password = each.value.password + + depends_on = [aws_db_instance.default] +} + +# 7. MySQL 권한 부여 +resource "mysql_grant" "user_grants" { + for_each = var.additional_db_users + + user = each.key + host = "%" + database = each.value.database + privileges = each.value.privileges + + depends_on = [mysql_user.users] +} \ No newline at end of file diff --git a/modules/app_stack/output.tf b/modules/app_stack/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/app_stack/variables.tf b/modules/app_stack/variables.tf new file mode 100644 index 0000000..f317807 --- /dev/null +++ b/modules/app_stack/variables.tf @@ -0,0 +1,89 @@ +variable "env_name" { + description = "환경 이름 (prod/stage)" +} + +variable "instance_type" { + description = "EC2 인스턴스 타입" +} + +variable "db_instance_class" { + description = "RDS 인스턴스 타입" +} + +# [DB 관련 추가 변수] +variable "db_username" { + description = "DB 마스터 사용자명" + type = string +} + +variable "db_password" { + description = "DB 마스터 비밀번호" + type = string + sensitive = true +} + +# 추가할 DB 유저 목록 +variable "additional_db_users" { + description = "추가 DB 유저 설정 (비번, 대상 DB, 권한 목록)" + type = map(object({ + password = string # 유저 비밀번호 + database = string # 권한을 줄 데이터베이스 이름 + privileges = list(string) # 권한 목록 + })) + default = {} +} + +variable "db_engine_version" { + description = "MySQL 엔진 버전 (예: 8.0.35, 8.4.0)" + type = string +} + +variable "db_parameter_group_name" { + description = "MySQL 엔진 파라미터 그룹" + type = string +} + +variable "rds_identifier" { + description = "RDS DB Identifier" + type = string +} + +variable "kms_key_arn" { + description = "RDS 스토리지 암호화를 위한 KMS Key ARN" + type = string +} + +variable "vpc_id" { + description = "배포할 VPC ID" +} + +variable "ami_id" { + description = "EC2 AMI ID" + type = string +} + +variable "allowed_ssh_cidrs" { + description = "SSH 접속을 허용할 IP 대역 리스트 (개발자 IP)" + type = list(string) +} + +variable "key_name" { + description = "AWS 콘솔에 등록된 기존 EC2 Key Pair 이름" + type = string +} + +# [Nginx 관련 추가 변수] +variable "domain_name" { + description = "Domain name for Nginx" + type = string +} + +variable "cert_email" { + description = "Email for Let's Encrypt" + type = string +} + +variable "nginx_conf_name" { + description = "Nginx config filename" + type = string +} From bb0e1b52d74fe15b8d80c6ed34ba150b64dfdd2a Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:31:08 +0900 Subject: [PATCH 07/27] =?UTF-8?q?feat:=20app=5Fstack=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=9C=20stage=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/stage/main.tf | 20 ++++++++++++++++++++ environment/stage/provider.tf | 9 +++++++++ environment/stage/variables.tf | 20 ++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 environment/stage/main.tf create mode 100644 environment/stage/provider.tf create mode 100644 environment/stage/variables.tf diff --git a/environment/stage/main.tf b/environment/stage/main.tf new file mode 100644 index 0000000..942dc1b --- /dev/null +++ b/environment/stage/main.tf @@ -0,0 +1,20 @@ +data "aws_vpc" "default" { + default = true +} + +module "stage_stack" { + source = "../../modules/app_stack" + + env_name = "stage" + vpc_id = data.aws_vpc.default.id + + # 키페어 및 접속 허용 + key_name = var.key_name + + # DB 계정 정보 + db_username = var.db_username + db_password = var.db_password + + # DB 엔진 및 암호화 설정 + kms_key_arn = var.kms_key_arn +} \ No newline at end of file diff --git a/environment/stage/provider.tf b/environment/stage/provider.tf new file mode 100644 index 0000000..f62636d --- /dev/null +++ b/environment/stage/provider.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "ap-northeast-2" + default_tags { + tags = { + Project = "solid-connection" + Env = "stage" + } + } +} \ No newline at end of file diff --git a/environment/stage/variables.tf b/environment/stage/variables.tf new file mode 100644 index 0000000..5db2137 --- /dev/null +++ b/environment/stage/variables.tf @@ -0,0 +1,20 @@ +variable "kms_key_arn" { + description = "Existing KMS Key ARN for stage DB Encryption" + type = string +} + +variable "db_username" { + description = "DB Username for stage" + type = string +} + +variable "db_password" { + description = "DB Password from secret" + type = string + sensitive = true +} + +variable "key_name" { + description = "Key pair name" + type = string +} \ No newline at end of file From 8732f88ef85104d20c7f5c39877aca32da5b8bf9 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:31:39 +0900 Subject: [PATCH 08/27] =?UTF-8?q?feat:=20app=5Fstack=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=9C=20prod=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/prod/main.tf | 20 ++++++++++++++++++++ environment/prod/provider.tf | 9 +++++++++ environment/prod/variables.tf | 20 ++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 environment/prod/main.tf create mode 100644 environment/prod/provider.tf create mode 100644 environment/prod/variables.tf diff --git a/environment/prod/main.tf b/environment/prod/main.tf new file mode 100644 index 0000000..549abe2 --- /dev/null +++ b/environment/prod/main.tf @@ -0,0 +1,20 @@ +data "aws_vpc" "default" { + default = true +} + +module "prod_stack" { + source = "../../modules/app_stack" + + env_name = "prod" + vpc_id = data.aws_vpc.default.id + + # 키페어 및 접속 허용 + key_name = var.key_name + + # DB 계정 정보 + db_username = var.db_username + db_password = var.db_password + + # DB 엔진 및 암호화 설정 + kms_key_arn = var.kms_key_arn +} \ No newline at end of file diff --git a/environment/prod/provider.tf b/environment/prod/provider.tf new file mode 100644 index 0000000..00eeaaa --- /dev/null +++ b/environment/prod/provider.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "ap-northeast-2" + default_tags { + tags = { + Project = "solid-connection" + Env = "prod" + } + } +} \ No newline at end of file diff --git a/environment/prod/variables.tf b/environment/prod/variables.tf new file mode 100644 index 0000000..63afdaa --- /dev/null +++ b/environment/prod/variables.tf @@ -0,0 +1,20 @@ +variable "kms_key_arn" { + description = "Existing KMS Key ARN for prod DB Encryption" + type = string +} + +variable "db_username" { + description = "DB Username for prod" + type = string +} + +variable "db_password" { + description = "DB Password from secret" + type = string + sensitive = true +} + +variable "key_name" { + description = "Key pair name" + type = string +} \ No newline at end of file From 5a652af0da515b9e8d6156387c50bac0b077ceb3 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Mon, 22 Dec 2025 13:32:44 +0900 Subject: [PATCH 09/27] =?UTF-8?q?chore:=20monitoring=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=20=EC=A0=95=EC=9D=98=EB=A5=BC=20=EC=9C=84=ED=95=9C=20.tf=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=93=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/monitoring/main.tf | 1 + environment/monitoring/provider.tf | 9 +++++++++ environment/monitoring/variables.tf | 1 + 3 files changed, 11 insertions(+) create mode 100644 environment/monitoring/main.tf create mode 100644 environment/monitoring/provider.tf create mode 100644 environment/monitoring/variables.tf diff --git a/environment/monitoring/main.tf b/environment/monitoring/main.tf new file mode 100644 index 0000000..2ea1690 --- /dev/null +++ b/environment/monitoring/main.tf @@ -0,0 +1 @@ +# TODO:: 모니터링용 EC2 인스턴스 및 보안 그룹 리소스 정의 필요 \ No newline at end of file diff --git a/environment/monitoring/provider.tf b/environment/monitoring/provider.tf new file mode 100644 index 0000000..c4a6bd4 --- /dev/null +++ b/environment/monitoring/provider.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "ap-northeast-2" + default_tags { + tags = { + Project = "solid-connection" + Env = "monitoring" + } + } +} \ No newline at end of file diff --git a/environment/monitoring/variables.tf b/environment/monitoring/variables.tf new file mode 100644 index 0000000..f6da737 --- /dev/null +++ b/environment/monitoring/variables.tf @@ -0,0 +1 @@ +# TODO:: 모니터링 인스턴스용 변수 정의 \ No newline at end of file From d872a076165a3cb56b0cd3a6f828435aa9347484 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:21:59 +0900 Subject: [PATCH 10/27] chore: add infra secrets --- .gitmodules | 3 +++ config/secrets | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 config/secrets diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..61a9ce8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "config/secrets"] + path = config/secrets + url = https://github.com/solid-connection/solid-connection-infra-secret.git diff --git a/config/secrets b/config/secrets new file mode 160000 index 0000000..db27de4 --- /dev/null +++ b/config/secrets @@ -0,0 +1 @@ +Subproject commit db27de4c33b4900b8dc7b24a5cc89e1cbfad5736 From db3f24b6c518b40ad15127985be48925b2f595b8 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:24:43 +0900 Subject: [PATCH 11/27] =?UTF-8?q?refactor:=20=EB=B3=B4=EC=95=88=EA=B7=B8?= =?UTF-8?q?=EB=A3=B9=20=EC=9D=B8=EB=B0=94=EC=9A=B4=EB=93=9C=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=ED=99=94=20&=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/main.tf | 41 +++++++++++++++++++++++++++++----- modules/app_stack/variables.tf | 33 ++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/modules/app_stack/main.tf b/modules/app_stack/main.tf index ce54071..210bccb 100644 --- a/modules/app_stack/main.tf +++ b/modules/app_stack/main.tf @@ -27,6 +27,25 @@ resource "aws_security_group" "api_sg" { description = "Security Group for API Server" vpc_id = var.vpc_id + dynamic "ingress" { + for_each = var.api_ingress_rules + content { + description = ingress.value.description + from_port = ingress.value.from_port + to_port = ingress.value.to_port + protocol = ingress.value.protocol + cidr_blocks = ingress.value.cidr_blocks + } + } + + # [Outbound] 모든 트래픽 허용 + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + tags = { Name = "solid-connection-server-${var.env_name}-sg" } @@ -38,6 +57,17 @@ resource "aws_security_group" "db_sg" { description = "Security Group for RDS" vpc_id = var.vpc_id + dynamic "ingress" { + for_each = var.db_ingress_rules + content { + description = ingress.value.description + from_port = ingress.value.from_port + to_port = ingress.value.to_port + protocol = ingress.value.protocol + security_groups = [aws_security_group.api_sg.id] + } + } + tags = { Name = "solid-connection-${var.env_name}-db-sg" } @@ -45,8 +75,8 @@ resource "aws_security_group" "db_sg" { # 3. CloudInit을 이용한 User Data 스크립트 구성 data "cloudinit_config" "app_init" { - gzip = true # 압축하여 UserData 용량 제한(64KB) 극복 - base64_encode = true # EC2 UserData는 Base64 필수 + gzip = true + base64_encode = true # [Part 1] Docker 설치 스크립트 part { @@ -77,14 +107,13 @@ resource "aws_instance" "api_server" { key_name = var.key_name associate_public_ip_address = true - # User Data가 변경되면 인스턴스를 새로 만들 것인지 결정, true로 설정하면 스크립트 수정 시 기존 서버를 삭제하고 새 서버를 띄웁니다. user_data_base64 = data.cloudinit_config.app_init.rendered tags = { Name = "solid-connection-server-${var.env_name}" } - user_data_replace_on_change = false # true면 User Data 변경 시 인스턴스 교체 + user_data_replace_on_change = false lifecycle { ignore_changes = [ @@ -137,8 +166,8 @@ resource "mysql_grant" "user_grants" { user = each.key host = "%" - database = each.value.database + database = each.value.database privileges = each.value.privileges depends_on = [mysql_user.users] -} \ No newline at end of file +} diff --git a/modules/app_stack/variables.tf b/modules/app_stack/variables.tf index f317807..3907622 100644 --- a/modules/app_stack/variables.tf +++ b/modules/app_stack/variables.tf @@ -1,5 +1,5 @@ variable "env_name" { - description = "환경 이름 (prod/stage)" + description = "환경 이름" } variable "instance_type" { @@ -10,6 +10,27 @@ variable "db_instance_class" { description = "RDS 인스턴스 타입" } +variable "api_ingress_rules" { + description = "List of ingress rules for API Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + description = string + })) +} + +variable "db_ingress_rules" { + description = "List of ingress rules for DB Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + description = string + })) +} + # [DB 관련 추가 변수] variable "db_username" { description = "DB 마스터 사용자명" @@ -26,15 +47,15 @@ variable "db_password" { variable "additional_db_users" { description = "추가 DB 유저 설정 (비번, 대상 DB, 권한 목록)" type = map(object({ - password = string # 유저 비밀번호 - database = string # 권한을 줄 데이터베이스 이름 - privileges = list(string) # 권한 목록 + password = string + database = string + privileges = list(string) })) default = {} } variable "db_engine_version" { - description = "MySQL 엔진 버전 (예: 8.0.35, 8.4.0)" + description = "MySQL 엔진 버전" type = string } @@ -63,7 +84,7 @@ variable "ami_id" { } variable "allowed_ssh_cidrs" { - description = "SSH 접속을 허용할 IP 대역 리스트 (개발자 IP)" + description = "SSH 접속을 허용할 IP 대역 리스트" type = list(string) } From 4af0ad7ae22ec789d3859710e9827357760676fc Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:25:03 +0900 Subject: [PATCH 12/27] =?UTF-8?q?docs:=20.gitignore=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index b81cce9..d78b2be 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,16 @@ -/environment/prod/secret.tfvars -/environment/prod/.terraform -/environment/prod/.terraform.lock.hcl -/environment/prod/terraform.tfstate -/environment/prod/terraform.tfstate.backup -/environment/stage/secret.tfvars -/environment/stage/.terraform -/environment/stage/.terraform.lock.hcl -/environment/stage/terraform.tfstate -/environment/stage/terraform.tfstate.backup -inseong_accessKeys.csv -solid-connection-server-2.pem -.DS_Store \ No newline at end of file +# --- Terraform (모든 하위 폴더 적용) --- +**/.terraform/ +*.tfstate +*.tfstate.backup +*.tfvars +.terraform.lock.hcl + +# --- Secrets (보안상 절대 커밋 금지) --- +*.pem +*.csv +*.json +*_accessKeys.csv + +# --- IDE & OS --- +.idea/ +.DS_Store From d956d5a6400e6059158efd39649ab72010333949 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:25:51 +0900 Subject: [PATCH 13/27] =?UTF-8?q?refactor:=20=EC=A4=91=EC=95=99=20?= =?UTF-8?q?=EC=A7=91=EC=A4=91=EB=90=9C=20=EC=8B=9C=ED=81=AC=EB=A6=BF?= =?UTF-8?q?=EC=9D=84=20=EA=B3=A0=EB=A0=A4=ED=95=9C=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20=EA=B5=AC=EC=A1=B0=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d6aad9f..7083af1 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ solid-connection 서비스의 AWS, terraform 기반 IaC 레포지토리입니다 ## 디렉토리 구조 ``` solid-connection-infra/ +├── config/ +│ └── secrets/ # 민감한 data 관리 +│ └── ... ├── modules/ │ └── app_stack/ # [공통 모듈] API Server + RDS 정의 │ ├── main.tf @@ -14,21 +17,17 @@ solid-connection-infra/ ├── prod/ # [Prod 환경] │ ├── main.tf │ ├── provider.tf - │ ├── variables.tf - │ └── secret.tfvars + │ ├── variables.tf ├── stage/ # [Stage 환경] │ ├── main.tf │ ├── provider.tf │ ├── variables.tf - │ └── secret.tfvars ├── load_test/ # [부하테스트 환경] │ ├── main.tf │ ├── provider.tf │ ├── variables.tf - │ └── secret.tfvars - └── monitoring/ # [Monitoring 환경] (Grafana 단독) + └── monitoring/ # [Monitoring 환경] ├── main.tf ├── provider.tf ├── variables.tf - └── secret.tfvars -``` \ No newline at end of file +``` From c04fb6d9fb035f44bec66be3801f09486ec7ecb8 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:26:44 +0900 Subject: [PATCH 14/27] =?UTF-8?q?feat:=20stage=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=8B=9C=ED=81=AC=EB=A6=BF=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20variable=EB=A1=9C=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/stage/main.tf | 33 ++++++++++-- environment/stage/provider.tf | 2 +- environment/stage/variables.tf | 92 +++++++++++++++++++++++++++++++--- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/environment/stage/main.tf b/environment/stage/main.tf index 942dc1b..4cba659 100644 --- a/environment/stage/main.tf +++ b/environment/stage/main.tf @@ -1,3 +1,4 @@ +# 기본 VPC 정보 조회 data "aws_vpc" "default" { default = true } @@ -8,13 +9,37 @@ module "stage_stack" { env_name = "stage" vpc_id = data.aws_vpc.default.id + ami_id = var.ami_id + # 키페어 및 접속 허용 key_name = var.key_name + allowed_ssh_cidrs = var.allowed_ssh_cidrs + + # 인스턴스 스펙 + instance_type = var.server_instance_type + db_instance_class = var.db_instance_class + + # 보안 그룹 규칙 + api_ingress_rules = var.api_ingress_rules + db_ingress_rules = var.db_ingress_rules + + # RDS 식별자 설정 + rds_identifier = var.rds_identifier # DB 계정 정보 - db_username = var.db_username - db_password = var.db_password + db_username = var.db_root_username + db_password = var.db_root_password # DB 엔진 및 암호화 설정 - kms_key_arn = var.kms_key_arn -} \ No newline at end of file + db_engine_version = var.db_engine_version # MySQL 버전 지정 + db_parameter_group_name = var.db_parameter_group_name # MySQL 파라미터 그룹 지정 + kms_key_arn = var.kms_key_arn # KMS ARN 변수 전달 + + # 추가 유저마다 다른 권한 부여 + additional_db_users = var.additional_db_users + + # Nginx 및 도메인 설정 + domain_name = var.domain_name + cert_email = var.cert_email + nginx_conf_name = var.nginx_conf_name +} diff --git a/environment/stage/provider.tf b/environment/stage/provider.tf index f62636d..87dc788 100644 --- a/environment/stage/provider.tf +++ b/environment/stage/provider.tf @@ -6,4 +6,4 @@ provider "aws" { Env = "stage" } } -} \ No newline at end of file +} diff --git a/environment/stage/variables.tf b/environment/stage/variables.tf index 5db2137..af74bdf 100644 --- a/environment/stage/variables.tf +++ b/environment/stage/variables.tf @@ -1,20 +1,100 @@ -variable "kms_key_arn" { - description = "Existing KMS Key ARN for stage DB Encryption" +variable "ami_id" { + description = "AMI ID for the stage environment" + type = string +} + +variable "server_instance_type" { + description = "Server instance type for the stage environment" + type = string +} + +variable "db_instance_class" { + description = "DB instance class for the stage environment" + type = string +} + +variable "api_ingress_rules" { + description = "List of ingress rules for API Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + description = string + })) +} + +variable "db_ingress_rules" { + description = "List of ingress rules for DB Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + description = string + })) +} + +variable "rds_identifier" { + description = "RDS identifier for the stage environment" + type = string +} + +variable "db_engine_version" { + description = "MySQL engine version for the stage environment" + type = string +} + +variable "db_parameter_group_name" { + description = "MySQL parameter group name for the stage environment" type = string } -variable "db_username" { +variable "db_root_username" { description = "DB Username for stage" type = string } -variable "db_password" { - description = "DB Password from secret" +variable "db_root_password" { + description = "DB Password for stage" type = string sensitive = true } +variable "additional_db_users" { + description = "추가 DB 유저 및 권한 목록" + type = map(object({ + password = string + database = string + privileges = list(string) + })) +} + variable "key_name" { description = "Key pair name" type = string -} \ No newline at end of file +} + +variable "allowed_ssh_cidrs" { + description = "Allowed SSH CIDR blocks" + type = list(string) +} + +variable "kms_key_arn" { + description = "Existing KMS Key ARN for stage DB Encryption" + type = string +} + +variable "domain_name" { + description = "Domain name for the stage environment" + type = string +} + +variable "cert_email" { + description = "email for Domain Name Certbot" + type = string +} + +variable "nginx_conf_name" { + description = "Nginx conf name for the stage environment" + type = string +} From 42f3cf111baf1a4bc8e8c63e9e260fff12b72e87 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:28:30 +0900 Subject: [PATCH 15/27] =?UTF-8?q?feat:=20prod=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=8B=9C=ED=81=AC=EB=A6=BF=20?= =?UTF-8?q?=EA=B0=92=EC=9D=84=20variable=EB=A1=9C=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/prod/main.tf | 33 +++++++++++-- environment/prod/provider.tf | 2 +- environment/prod/variables.tf | 92 ++++++++++++++++++++++++++++++++--- 3 files changed, 116 insertions(+), 11 deletions(-) diff --git a/environment/prod/main.tf b/environment/prod/main.tf index 549abe2..2139ab0 100644 --- a/environment/prod/main.tf +++ b/environment/prod/main.tf @@ -1,3 +1,4 @@ +# 기본 VPC 정보 조회 data "aws_vpc" "default" { default = true } @@ -8,13 +9,37 @@ module "prod_stack" { env_name = "prod" vpc_id = data.aws_vpc.default.id + ami_id = var.ami_id + # 키페어 및 접속 허용 key_name = var.key_name + allowed_ssh_cidrs = var.allowed_ssh_cidrs + + # 인스턴스 스펙 + instance_type = var.server_instance_type + db_instance_class = var.db_instance_class + + # 보안 그룹 규칙 + api_ingress_rules = var.api_ingress_rules + db_ingress_rules = var.db_ingress_rules + + # RDS 식별자 설정 + rds_identifier = var.rds_identifier # DB 계정 정보 - db_username = var.db_username - db_password = var.db_password + db_username = var.db_root_username + db_password = var.db_root_password # DB 엔진 및 암호화 설정 - kms_key_arn = var.kms_key_arn -} \ No newline at end of file + db_engine_version = var.db_engine_version # MySQL 버전 지정 + db_parameter_group_name = var.db_parameter_group_name # MySQL 파라미터 그룹 지정 + kms_key_arn = var.kms_key_arn # KMS ARN 변수 전달 + + # 추가 유저마다 다른 권한 부여 + additional_db_users = var.additional_db_users + + # Nginx 및 도메인 설정 + domain_name = var.domain_name + cert_email = var.cert_email + nginx_conf_name = var.nginx_conf_name +} diff --git a/environment/prod/provider.tf b/environment/prod/provider.tf index 00eeaaa..087653c 100644 --- a/environment/prod/provider.tf +++ b/environment/prod/provider.tf @@ -6,4 +6,4 @@ provider "aws" { Env = "prod" } } -} \ No newline at end of file +} diff --git a/environment/prod/variables.tf b/environment/prod/variables.tf index 63afdaa..baee5d4 100644 --- a/environment/prod/variables.tf +++ b/environment/prod/variables.tf @@ -1,20 +1,100 @@ -variable "kms_key_arn" { - description = "Existing KMS Key ARN for prod DB Encryption" +variable "ami_id" { + description = "AMI ID for the prod environment" + type = string +} + +variable "server_instance_type" { + description = "Server instance type for the prod environment" + type = string +} + +variable "db_instance_class" { + description = "DB instance class for the prod environment" + type = string +} + +variable "api_ingress_rules" { + description = "List of ingress rules for API Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + description = string + })) +} + +variable "db_ingress_rules" { + description = "List of ingress rules for DB Server" + type = list(object({ + from_port = number + to_port = number + protocol = string + description = string + })) +} + +variable "rds_identifier" { + description = "RDS identifier for the prod environment" + type = string +} + +variable "db_engine_version" { + description = "MySQL engine version for the prod environment" + type = string +} + +variable "db_parameter_group_name" { + description = "MySQL parameter group name for the prod environment" type = string } -variable "db_username" { +variable "db_root_username" { description = "DB Username for prod" type = string } -variable "db_password" { - description = "DB Password from secret" +variable "db_root_password" { + description = "DB Password for prod" type = string sensitive = true } +variable "additional_db_users" { + description = "추가 DB 유저 및 권한 목록" + type = map(object({ + password = string + database = string + privileges = list(string) + })) +} + variable "key_name" { description = "Key pair name" type = string -} \ No newline at end of file +} + +variable "allowed_ssh_cidrs" { + description = "Allowed SSH CIDR blocks" + type = list(string) +} + +variable "kms_key_arn" { + description = "Existing KMS Key ARN for prod DB Encryption" + type = string +} + +variable "domain_name" { + description = "Domain name for the prod environment" + type = string +} + +variable "cert_email" { + description = "email for Domain Name Certbot" + type = string +} + +variable "nginx_conf_name" { + description = "Nginx conf name for the prod environment" + type = string +} From c422d7fc69e999844324dd95ddbe79e87c0c1097 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:29:10 +0900 Subject: [PATCH 16/27] =?UTF-8?q?chore:=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=EC=A4=80=EC=88=98=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EB=A7=88?= =?UTF-8?q?=EC=A7=80=EB=A7=89=20=EC=A4=84=20=EA=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/monitoring/main.tf | 2 +- environment/monitoring/provider.tf | 2 +- environment/monitoring/variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/environment/monitoring/main.tf b/environment/monitoring/main.tf index 2ea1690..7e6ba38 100644 --- a/environment/monitoring/main.tf +++ b/environment/monitoring/main.tf @@ -1 +1 @@ -# TODO:: 모니터링용 EC2 인스턴스 및 보안 그룹 리소스 정의 필요 \ No newline at end of file +# TODO:: 모니터링용 EC2 인스턴스 및 보안 그룹 리소스 정의 필요 diff --git a/environment/monitoring/provider.tf b/environment/monitoring/provider.tf index c4a6bd4..3c04703 100644 --- a/environment/monitoring/provider.tf +++ b/environment/monitoring/provider.tf @@ -6,4 +6,4 @@ provider "aws" { Env = "monitoring" } } -} \ No newline at end of file +} diff --git a/environment/monitoring/variables.tf b/environment/monitoring/variables.tf index f6da737..fea9485 100644 --- a/environment/monitoring/variables.tf +++ b/environment/monitoring/variables.tf @@ -1 +1 @@ -# TODO:: 모니터링 인스턴스용 변수 정의 \ No newline at end of file +# TODO:: 모니터링 인스턴스용 변수 정의 From 34328ec7d01e0c6513d2758cacb2510b78896cdb Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 00:29:43 +0900 Subject: [PATCH 17/27] =?UTF-8?q?feat:=20=EB=B6=80=ED=95=98=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?=EC=9A=A9=EB=8F=84=EC=9D=98=20=ED=8C=8C=EC=9D=BC=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/load_test/main.tf | 1 + environment/load_test/provider.tf | 9 +++++++++ environment/load_test/variables.tf | 1 + 3 files changed, 11 insertions(+) create mode 100644 environment/load_test/main.tf create mode 100644 environment/load_test/provider.tf create mode 100644 environment/load_test/variables.tf diff --git a/environment/load_test/main.tf b/environment/load_test/main.tf new file mode 100644 index 0000000..995074f --- /dev/null +++ b/environment/load_test/main.tf @@ -0,0 +1 @@ +# TODO:: 부하 테스트용 EC2 인스턴스 및 보안 그룹 리소스 정의 필요 diff --git a/environment/load_test/provider.tf b/environment/load_test/provider.tf new file mode 100644 index 0000000..3c3f8d1 --- /dev/null +++ b/environment/load_test/provider.tf @@ -0,0 +1,9 @@ +provider "aws" { + region = "ap-northeast-2" + default_tags { + tags = { + Project = "solid-connection" + Env = "load_test" + } + } +} diff --git a/environment/load_test/variables.tf b/environment/load_test/variables.tf new file mode 100644 index 0000000..6f74e1f --- /dev/null +++ b/environment/load_test/variables.tf @@ -0,0 +1 @@ +# TODO:: 부하 테스트 인스턴스용 변수 정의 From fe6d034da647badf10ad4e7d590398c3e42633c8 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:17:26 +0900 Subject: [PATCH 18/27] =?UTF-8?q?refactor:=20=ED=99=95=EC=9E=A5=EC=9E=90?= =?UTF-8?q?=20=EC=9D=B8=EC=8B=9D=EC=9D=84=20=EC=9C=84=ED=95=9C=20nginx=5Fs?= =?UTF-8?q?etup=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app_stack/scripts/{nginx_setup.tftpl => nginx_setup.sh.tftpl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/app_stack/scripts/{nginx_setup.tftpl => nginx_setup.sh.tftpl} (100%) diff --git a/modules/app_stack/scripts/nginx_setup.tftpl b/modules/app_stack/scripts/nginx_setup.sh.tftpl similarity index 100% rename from modules/app_stack/scripts/nginx_setup.tftpl rename to modules/app_stack/scripts/nginx_setup.sh.tftpl From 266ee673c8f9f7a8c3e8155bf354a823295b8ef1 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:27:52 +0900 Subject: [PATCH 19/27] =?UTF-8?q?refactor:=20provider=20=EA=B5=AC=EB=AC=B8?= =?UTF-8?q?=EC=9D=84=20app=5Fstack/main=EC=97=90=EC=84=9C=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/main.tf | 25 +------------------------ modules/app_stack/provider.tf | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 modules/app_stack/provider.tf diff --git a/modules/app_stack/main.tf b/modules/app_stack/main.tf index 210bccb..10dde34 100644 --- a/modules/app_stack/main.tf +++ b/modules/app_stack/main.tf @@ -1,26 +1,3 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.0" - } - cloudinit = { - source = "hashicorp/cloudinit" - version = "~> 2.3" - } - mysql = { - source = "petoju/mysql" - version = ">= 3.0" - } - } -} - -provider "mysql" { - endpoint = "127.0.0.1:3306" - username = var.db_username - password = var.db_password -} - # 1. API Server용 보안 그룹 (SSH 연결 허용) resource "aws_security_group" "api_sg" { name = "sc-${var.env_name}-api-sg" @@ -88,7 +65,7 @@ data "cloudinit_config" "app_init" { # [Part 2] Nginx 설정 스크립트 part { content_type = "text/x-shellscript" - content = templatefile("${path.module}/scripts/nginx_setup.tftpl", { + content = templatefile("${path.module}/scripts/nginx_setup.sh.tftpl", { domain_name = var.domain_name email = var.cert_email conf_file_name = var.nginx_conf_name diff --git a/modules/app_stack/provider.tf b/modules/app_stack/provider.tf new file mode 100644 index 0000000..346cc47 --- /dev/null +++ b/modules/app_stack/provider.tf @@ -0,0 +1,23 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.0" + } + cloudinit = { + source = "hashicorp/cloudinit" + version = "~> 2.3" + } + mysql = { + source = "petoju/mysql" + version = ">= 3.0" + } + } +} + +# MySQL Provider 설정 (SSH 터널링을 통해 로컬호스트로 접속 가정) +provider "mysql" { + endpoint = "127.0.0.1:3306" + username = var.db_username + password = var.db_password +} \ No newline at end of file From 00fbed18b0fc52fb430843d962788dc1394a24a6 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:38:10 +0900 Subject: [PATCH 20/27] =?UTF-8?q?refactor:=20=EA=B8=B8=EC=96=B4=EC=A7=84?= =?UTF-8?q?=20main.tf=20=ED=8C=8C=EC=9D=BC=EC=9D=84=20=EA=B0=81=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=EB=B3=84=EB=A1=9C=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EB=8B=A8=EC=9C=84=20=EB=B6=84=EB=A6=AC=20feat:=20s?= =?UTF-8?q?3=20default,=20upload=20bucket=EC=9D=84=20=ED=85=8C=EB=9D=BC?= =?UTF-8?q?=ED=8F=BC=EC=9C=BC=EB=A1=9C=20=EA=B4=80=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/secrets | 2 +- modules/app_stack/ec2.tf | 53 ++++++++++ modules/app_stack/main.tf | 150 --------------------------- modules/app_stack/provider.tf | 2 +- modules/app_stack/rds.tf | 44 ++++++++ modules/app_stack/security_groups.tf | 51 +++++++++ 6 files changed, 150 insertions(+), 152 deletions(-) create mode 100644 modules/app_stack/ec2.tf delete mode 100644 modules/app_stack/main.tf create mode 100644 modules/app_stack/rds.tf create mode 100644 modules/app_stack/security_groups.tf diff --git a/config/secrets b/config/secrets index db27de4..c1cf69a 160000 --- a/config/secrets +++ b/config/secrets @@ -1 +1 @@ -Subproject commit db27de4c33b4900b8dc7b24a5cc89e1cbfad5736 +Subproject commit c1cf69a9de6f6b766750395875cd5bdcb16a0e96 diff --git a/modules/app_stack/ec2.tf b/modules/app_stack/ec2.tf new file mode 100644 index 0000000..704e676 --- /dev/null +++ b/modules/app_stack/ec2.tf @@ -0,0 +1,53 @@ +# 3. CloudInit을 이용한 User Data 스크립트 구성 +data "cloudinit_config" "app_init" { + gzip = true + base64_encode = true + + # [Part 1] Docker 설치 스크립트 + part { + content_type = "text/x-shellscript" + content = file("${path.module}/scripts/docker_setup.sh") + filename = "1_docker_install.sh" + } + + # [Part 2] Nginx 설정 스크립트 + part { + content_type = "text/x-shellscript" + content = templatefile("${path.module}/scripts/nginx_setup.sh.tftpl", { + domain_name = var.domain_name + email = var.cert_email + conf_file_name = var.nginx_conf_name + }) + filename = "2_nginx_setup.sh" + } +} + +# 4. API Server (EC2) +resource "aws_instance" "api_server" { + ami = var.ami_id + instance_type = var.instance_type + + vpc_security_group_ids = [aws_security_group.api_sg.id] + + key_name = var.key_name + associate_public_ip_address = true + + user_data_base64 = data.cloudinit_config.app_init.rendered + + tags = { + Name = "solid-connection-server-${var.env_name}" + } + + user_data_replace_on_change = false + + lifecycle { + ignore_changes = [ + user_data, + user_data_base64, + user_data_replace_on_change, + + ami, + key_name + ] + } +} diff --git a/modules/app_stack/main.tf b/modules/app_stack/main.tf deleted file mode 100644 index 10dde34..0000000 --- a/modules/app_stack/main.tf +++ /dev/null @@ -1,150 +0,0 @@ -# 1. API Server용 보안 그룹 (SSH 연결 허용) -resource "aws_security_group" "api_sg" { - name = "sc-${var.env_name}-api-sg" - description = "Security Group for API Server" - vpc_id = var.vpc_id - - dynamic "ingress" { - for_each = var.api_ingress_rules - content { - description = ingress.value.description - from_port = ingress.value.from_port - to_port = ingress.value.to_port - protocol = ingress.value.protocol - cidr_blocks = ingress.value.cidr_blocks - } - } - - # [Outbound] 모든 트래픽 허용 - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - tags = { - Name = "solid-connection-server-${var.env_name}-sg" - } -} - -# 2. RDS용 보안 그룹 (API Server만 믿음) -resource "aws_security_group" "db_sg" { - name = "sc-${var.env_name}-db-sg" - description = "Security Group for RDS" - vpc_id = var.vpc_id - - dynamic "ingress" { - for_each = var.db_ingress_rules - content { - description = ingress.value.description - from_port = ingress.value.from_port - to_port = ingress.value.to_port - protocol = ingress.value.protocol - security_groups = [aws_security_group.api_sg.id] - } - } - - tags = { - Name = "solid-connection-${var.env_name}-db-sg" - } -} - -# 3. CloudInit을 이용한 User Data 스크립트 구성 -data "cloudinit_config" "app_init" { - gzip = true - base64_encode = true - - # [Part 1] Docker 설치 스크립트 - part { - content_type = "text/x-shellscript" - content = file("${path.module}/scripts/docker_setup.sh") - filename = "1_docker_install.sh" - } - - # [Part 2] Nginx 설정 스크립트 - part { - content_type = "text/x-shellscript" - content = templatefile("${path.module}/scripts/nginx_setup.sh.tftpl", { - domain_name = var.domain_name - email = var.cert_email - conf_file_name = var.nginx_conf_name - }) - filename = "2_nginx_setup.sh" - } -} - -# 4. API Server (EC2) -resource "aws_instance" "api_server" { - ami = var.ami_id - instance_type = var.instance_type - - vpc_security_group_ids = [aws_security_group.api_sg.id] - - key_name = var.key_name - associate_public_ip_address = true - - user_data_base64 = data.cloudinit_config.app_init.rendered - - tags = { - Name = "solid-connection-server-${var.env_name}" - } - - user_data_replace_on_change = false - - lifecycle { - ignore_changes = [ - user_data, - user_data_base64, - user_data_replace_on_change, - - ami, - key_name - ] - } -} - -# 5. RDS -resource "aws_db_instance" "default" { - identifier = var.rds_identifier - allocated_storage = 20 - engine = "mysql" - engine_version = var.db_engine_version - instance_class = var.db_instance_class - username = var.db_username - password = var.db_password - parameter_group_name = var.db_parameter_group_name - copy_tags_to_snapshot = true - skip_final_snapshot = true - vpc_security_group_ids = [aws_security_group.db_sg.id] - - storage_encrypted = true - kms_key_id = var.kms_key_arn - - tags = { - Name = var.rds_identifier - } -} - -# 6. MySQL 추가 유저 생성 -resource "mysql_user" "users" { - for_each = var.additional_db_users - - user = each.key - host = "%" - plaintext_password = each.value.password - - depends_on = [aws_db_instance.default] -} - -# 7. MySQL 권한 부여 -resource "mysql_grant" "user_grants" { - for_each = var.additional_db_users - - user = each.key - host = "%" - database = each.value.database - privileges = each.value.privileges - - depends_on = [mysql_user.users] -} diff --git a/modules/app_stack/provider.tf b/modules/app_stack/provider.tf index 346cc47..b1a1d17 100644 --- a/modules/app_stack/provider.tf +++ b/modules/app_stack/provider.tf @@ -20,4 +20,4 @@ provider "mysql" { endpoint = "127.0.0.1:3306" username = var.db_username password = var.db_password -} \ No newline at end of file +} diff --git a/modules/app_stack/rds.tf b/modules/app_stack/rds.tf new file mode 100644 index 0000000..8f484c1 --- /dev/null +++ b/modules/app_stack/rds.tf @@ -0,0 +1,44 @@ +# 5. RDS +resource "aws_db_instance" "default" { + identifier = var.rds_identifier + allocated_storage = 20 + engine = "mysql" + engine_version = var.db_engine_version + instance_class = var.db_instance_class + username = var.db_username + password = var.db_password + parameter_group_name = var.db_parameter_group_name + copy_tags_to_snapshot = true + skip_final_snapshot = true + vpc_security_group_ids = [aws_security_group.db_sg.id] + + storage_encrypted = true + kms_key_id = var.kms_key_arn + + tags = { + Name = var.rds_identifier + } +} + +# 6. MySQL 추가 유저 생성 +resource "mysql_user" "users" { + for_each = var.additional_db_users + + user = each.key + host = "%" + plaintext_password = each.value.password + + depends_on = [aws_db_instance.default] +} + +# 7. MySQL 권한 부여 +resource "mysql_grant" "user_grants" { + for_each = var.additional_db_users + + user = each.key + host = "%" + database = each.value.database + privileges = each.value.privileges + + depends_on = [mysql_user.users] +} diff --git a/modules/app_stack/security_groups.tf b/modules/app_stack/security_groups.tf new file mode 100644 index 0000000..db984f2 --- /dev/null +++ b/modules/app_stack/security_groups.tf @@ -0,0 +1,51 @@ +# 1. API Server용 보안 그룹 (SSH 연결 허용) +resource "aws_security_group" "api_sg" { + name = "sc-${var.env_name}-api-sg" + description = "Security Group for API Server" + vpc_id = var.vpc_id + + dynamic "ingress" { + for_each = var.api_ingress_rules + content { + description = ingress.value.description + from_port = ingress.value.from_port + to_port = ingress.value.to_port + protocol = ingress.value.protocol + cidr_blocks = ingress.value.cidr_blocks + } + } + + # [Outbound] 모든 트래픽 허용 + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "solid-connection-server-${var.env_name}-sg" + } +} + +# 2. RDS용 보안 그룹 (API Server만 믿음) +resource "aws_security_group" "db_sg" { + name = "sc-${var.env_name}-db-sg" + description = "Security Group for RDS" + vpc_id = var.vpc_id + + dynamic "ingress" { + for_each = var.db_ingress_rules + content { + description = ingress.value.description + from_port = ingress.value.from_port + to_port = ingress.value.to_port + protocol = ingress.value.protocol + security_groups = [aws_security_group.api_sg.id] + } + } + + tags = { + Name = "solid-connection-${var.env_name}-db-sg" + } +} From 82ed57b86dff95d4547ee2d3f6dbf57e4786ff42 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:41:31 +0900 Subject: [PATCH 21/27] =?UTF-8?q?feat:=20s3=20default,=20upload=20bucket?= =?UTF-8?q?=EC=9D=84=20=ED=85=8C=EB=9D=BC=ED=8F=BC=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/prod/main.tf | 4 ++++ environment/prod/variables.tf | 10 ++++++++++ environment/stage/main.tf | 4 ++++ environment/stage/variables.tf | 10 ++++++++++ modules/app_stack/s3.tf | 18 ++++++++++++++++++ modules/app_stack/variables.tf | 11 +++++++++++ 6 files changed, 57 insertions(+) create mode 100644 modules/app_stack/s3.tf diff --git a/environment/prod/main.tf b/environment/prod/main.tf index 2139ab0..0125413 100644 --- a/environment/prod/main.tf +++ b/environment/prod/main.tf @@ -42,4 +42,8 @@ module "prod_stack" { domain_name = var.domain_name cert_email = var.cert_email nginx_conf_name = var.nginx_conf_name + + # S3 버킷 이름 전달 + s3_default_bucket_name = var.s3_default_bucket_name + s3_upload_bucket_name = var.s3_upload_bucket_name } diff --git a/environment/prod/variables.tf b/environment/prod/variables.tf index baee5d4..1d0ac49 100644 --- a/environment/prod/variables.tf +++ b/environment/prod/variables.tf @@ -98,3 +98,13 @@ variable "nginx_conf_name" { description = "Nginx conf name for the prod environment" type = string } + +variable "s3_default_bucket_name" { + description = "Name of the default S3 bucket" + type = string +} + +variable "s3_upload_bucket_name" { + description = "Name of the upload S3 bucket" + type = string +} diff --git a/environment/stage/main.tf b/environment/stage/main.tf index 4cba659..6988434 100644 --- a/environment/stage/main.tf +++ b/environment/stage/main.tf @@ -42,4 +42,8 @@ module "stage_stack" { domain_name = var.domain_name cert_email = var.cert_email nginx_conf_name = var.nginx_conf_name + + # S3 버킷 이름 전달 + s3_default_bucket_name = var.s3_default_bucket_name + s3_upload_bucket_name = var.s3_upload_bucket_name } diff --git a/environment/stage/variables.tf b/environment/stage/variables.tf index af74bdf..800714d 100644 --- a/environment/stage/variables.tf +++ b/environment/stage/variables.tf @@ -98,3 +98,13 @@ variable "nginx_conf_name" { description = "Nginx conf name for the stage environment" type = string } + +variable "s3_default_bucket_name" { + description = "Name of the default S3 bucket" + type = string +} + +variable "s3_upload_bucket_name" { + description = "Name of the upload S3 bucket" + type = string +} diff --git a/modules/app_stack/s3.tf b/modules/app_stack/s3.tf new file mode 100644 index 0000000..29838cd --- /dev/null +++ b/modules/app_stack/s3.tf @@ -0,0 +1,18 @@ +# 8. S3 Buckets +resource "aws_s3_bucket" "default" { + bucket = var.s3_default_bucket_name + + lifecycle { + prevent_destroy = true + ignore_changes = [tags_all] + } +} + +resource "aws_s3_bucket" "upload" { + bucket = var.s3_upload_bucket_name + + lifecycle { + prevent_destroy = true + ignore_changes = [tags_all] + } +} diff --git a/modules/app_stack/variables.tf b/modules/app_stack/variables.tf index 3907622..e939a84 100644 --- a/modules/app_stack/variables.tf +++ b/modules/app_stack/variables.tf @@ -108,3 +108,14 @@ variable "nginx_conf_name" { description = "Nginx config filename" type = string } + +# [S3 버킷 관련 변수] +variable "s3_default_bucket_name" { + description = "Name of the default S3 bucket" + type = string +} + +variable "s3_upload_bucket_name" { + description = "Name of the upload S3 bucket" + type = string +} \ No newline at end of file From 4812b4b0183b1c7d432902e3b8cf184ce5020ba7 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:42:54 +0900 Subject: [PATCH 22/27] =?UTF-8?q?chore:=20=EC=93=B0=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20app=5Fstack/variable=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/variables.tf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/app_stack/variables.tf b/modules/app_stack/variables.tf index e939a84..878b0fe 100644 --- a/modules/app_stack/variables.tf +++ b/modules/app_stack/variables.tf @@ -83,11 +83,6 @@ variable "ami_id" { type = string } -variable "allowed_ssh_cidrs" { - description = "SSH 접속을 허용할 IP 대역 리스트" - type = list(string) -} - variable "key_name" { description = "AWS 콘솔에 등록된 기존 EC2 Key Pair 이름" type = string @@ -118,4 +113,4 @@ variable "s3_default_bucket_name" { variable "s3_upload_bucket_name" { description = "Name of the upload S3 bucket" type = string -} \ No newline at end of file +} From 1861292a0fa9d4bc18905b13a4e947b74a4b855d Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:44:10 +0900 Subject: [PATCH 23/27] =?UTF-8?q?chore:=20prod/stage=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=93=B0=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=A0=84=EB=8B=AC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/prod/main.tf | 1 - environment/stage/main.tf | 1 - 2 files changed, 2 deletions(-) diff --git a/environment/prod/main.tf b/environment/prod/main.tf index 0125413..49adda0 100644 --- a/environment/prod/main.tf +++ b/environment/prod/main.tf @@ -13,7 +13,6 @@ module "prod_stack" { # 키페어 및 접속 허용 key_name = var.key_name - allowed_ssh_cidrs = var.allowed_ssh_cidrs # 인스턴스 스펙 instance_type = var.server_instance_type diff --git a/environment/stage/main.tf b/environment/stage/main.tf index 6988434..5fd2308 100644 --- a/environment/stage/main.tf +++ b/environment/stage/main.tf @@ -13,7 +13,6 @@ module "stage_stack" { # 키페어 및 접속 허용 key_name = var.key_name - allowed_ssh_cidrs = var.allowed_ssh_cidrs # 인스턴스 스펙 instance_type = var.server_instance_type From 765dc78059571fb001b9515f590b50b41614dce9 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:44:51 +0900 Subject: [PATCH 24/27] =?UTF-8?q?chore:=20prod/stage=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=93=B0=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?variable=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- environment/prod/variables.tf | 5 ----- environment/stage/variables.tf | 5 ----- 2 files changed, 10 deletions(-) diff --git a/environment/prod/variables.tf b/environment/prod/variables.tf index 1d0ac49..dfcf981 100644 --- a/environment/prod/variables.tf +++ b/environment/prod/variables.tf @@ -74,11 +74,6 @@ variable "key_name" { type = string } -variable "allowed_ssh_cidrs" { - description = "Allowed SSH CIDR blocks" - type = list(string) -} - variable "kms_key_arn" { description = "Existing KMS Key ARN for prod DB Encryption" type = string diff --git a/environment/stage/variables.tf b/environment/stage/variables.tf index 800714d..2e18f2a 100644 --- a/environment/stage/variables.tf +++ b/environment/stage/variables.tf @@ -74,11 +74,6 @@ variable "key_name" { type = string } -variable "allowed_ssh_cidrs" { - description = "Allowed SSH CIDR blocks" - type = list(string) -} - variable "kms_key_arn" { description = "Existing KMS Key ARN for stage DB Encryption" type = string From b06fe62d97f4b97aacba37f92bded8b23b1b6ce4 Mon Sep 17 00:00:00 2001 From: Hexeong <123macanic@naver.com> Date: Tue, 23 Dec 2025 14:49:43 +0900 Subject: [PATCH 25/27] =?UTF-8?q?chore:=20=ED=8F=B4=EB=8D=94=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?README.md=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7083af1..6d5ae6d 100644 --- a/README.md +++ b/README.md @@ -9,25 +9,28 @@ solid-connection-infra/ │ └── secrets/ # 민감한 data 관리 │ └── ... ├── modules/ -│ └── app_stack/ # [공통 모듈] API Server + RDS 정의 -│ ├── main.tf +│ └── app_stack/ # [Prod/Stage 환경의 공통 모듈] +│ ├── security_groups.tf +│ ├── ec2.tf +│ ├── rds.tf +│ ├── s3.tf │ ├── variables.tf │ └── outputs.tf └── environments/ ├── prod/ # [Prod 환경] │ ├── main.tf │ ├── provider.tf - │ ├── variables.tf + │ └── variables.tf ├── stage/ # [Stage 환경] │ ├── main.tf │ ├── provider.tf - │ ├── variables.tf + │ └── variables.tf ├── load_test/ # [부하테스트 환경] │ ├── main.tf │ ├── provider.tf - │ ├── variables.tf + │ └── variables.tf └── monitoring/ # [Monitoring 환경] ├── main.tf ├── provider.tf - ├── variables.tf + └── variables.tf ``` From 364d0ac5ad524f27f0ed4a93e007d54c96ae5322 Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 29 Dec 2025 16:32:16 +0900 Subject: [PATCH 26/27] =?UTF-8?q?feat:=20monitoring=20=EC=8B=9C=EC=8A=A4?= =?UTF-8?q?=ED=85=9C=20=EC=9D=B8=ED=94=84=EB=9D=BC=20=EA=B5=AC=EC=84=B1=20?= =?UTF-8?q?-=20monitoring=5Fstack=20=EC=B6=94=EA=B0=80=20-=20nginx=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20-=20secret=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/secrets | 2 +- environment/monitoring/main.tf | 30 +++++++- environment/monitoring/variables.tf | 52 ++++++++++++- modules/monitoring_stack/ec2.tf | 56 ++++++++++++++ modules/monitoring_stack/output.tf | 7 ++ .../scripts/nginx_setup.sh.tftpl | 77 +++++++++++++++++++ modules/monitoring_stack/security_groups.tf | 27 +++++++ modules/monitoring_stack/variables.tf | 56 ++++++++++++++ 8 files changed, 304 insertions(+), 3 deletions(-) create mode 100644 modules/monitoring_stack/ec2.tf create mode 100644 modules/monitoring_stack/output.tf create mode 100644 modules/monitoring_stack/scripts/nginx_setup.sh.tftpl create mode 100644 modules/monitoring_stack/security_groups.tf create mode 100644 modules/monitoring_stack/variables.tf diff --git a/config/secrets b/config/secrets index c1cf69a..03c90ed 160000 --- a/config/secrets +++ b/config/secrets @@ -1 +1 @@ -Subproject commit c1cf69a9de6f6b766750395875cd5bdcb16a0e96 +Subproject commit 03c90ed5b009df392bf7a3b086f2bdb3242f7adc diff --git a/environment/monitoring/main.tf b/environment/monitoring/main.tf index 7e6ba38..778cd4d 100644 --- a/environment/monitoring/main.tf +++ b/environment/monitoring/main.tf @@ -1 +1,29 @@ -# TODO:: 모니터링용 EC2 인스턴스 및 보안 그룹 리소스 정의 필요 +# 기본 VPC 정보 조회 +data "aws_vpc" "default" { + default = true +} + +module "monitoring_stack" { + # 기존 app_stack 모듈을 재사용하거나, 모니터링 전용 모듈이 있다면 경로 수정 + source = "../../modules/monitoring_stack" + + env_name = "monitoring" + vpc_id = data.aws_vpc.default.id + + ami_id = var.ami_id + + key_name = var.key_name + + instance_type = var.monitoring_instance_type + + private_ip = var.private_ip + + # Nginx 및 도메인 설정 + domain_name = var.domain_name + cert_email = var.cert_email + nginx_conf_name = var.nginx_conf_name + + + # Grafana(3000), Prometheus(9090), Loki(3100) 포트 개방 + monitoring_ingress_rules = var.monitoring_ingress_rules +} diff --git a/environment/monitoring/variables.tf b/environment/monitoring/variables.tf index fea9485..b1d78a6 100644 --- a/environment/monitoring/variables.tf +++ b/environment/monitoring/variables.tf @@ -1 +1,51 @@ -# TODO:: 모니터링 인스턴스용 변수 정의 +variable "ami_id" { + description = "AMI ID for the monitoring environment" + type = string +} + +variable "monitoring_instance_type" { + description = "Instance type for monitoring (e.g., t3.medium or larger recommended)" + type = string +} + +variable "key_name" { + description = "SSH Key pair name" + type = string +} + +variable "monitoring_ingress_rules" { + description = "Ingress rules for Grafana(3000), Prometheus(9090), Loki(3100)" + type = list(object({ + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + description = string + })) +} + +variable "private_ip" { + description = "Fixed private ip for alloy config" + type = string +} + +variable "ebs_volume_size" { + description = "Disk size for Prometheus TSDB (GB)" + type = number + default = 50 +} + +variable "domain_name" { + description = "Domain name for Grafana dashboard (e.g., monitor.example.com)" + type = string +} + +variable "cert_email" { + description = "email for Domain Name Certbot" + type = string +} + +variable "nginx_conf_name" { + description = "Nginx conf name for the prod environment" + type = string +} diff --git a/modules/monitoring_stack/ec2.tf b/modules/monitoring_stack/ec2.tf new file mode 100644 index 0000000..9de07dd --- /dev/null +++ b/modules/monitoring_stack/ec2.tf @@ -0,0 +1,56 @@ +data "cloudinit_config" "app_init" { + gzip = true + base64_encode = true + + # [Part 1] Docker 설치 스크립트 + part { + content_type = "text/x-shellscript" + content = file("${path.module}/../common/scripts/docker_setup.sh") + filename = "1_docker_install.sh" + } + + # [Part 2] Nginx 설정 스크립트 파일 생성 (실행 안 함, 파일만 생성) + part { + content_type = "text/cloud-config" + content = <>> [수동 실행] $DOMAIN 에 대한 Nginx 및 SSL 설정을 시작합니다." + +# 1. 패키지 설치 +sudo apt-get update +sudo apt-get install -y nginx python3 python3-venv libaugeas0 + +# 2. Certbot 설치 및 링크 +sudo python3 -m venv /opt/certbot/ +sudo /opt/certbot/bin/pip install --upgrade pip +sudo /opt/certbot/bin/pip install certbot certbot-nginx +sudo ln -sf /opt/certbot/bin/certbot /usr/bin/certbot + +# 3. SSL 인증서 발급 +sudo systemctl stop nginx +sudo certbot certonly --standalone \ + --non-interactive \ + --agree-tos \ + --email "$EMAIL" \ + -d "$DOMAIN" + +# 4. Nginx 설정 파일 작성 +sudo tee /etc/nginx/sites-available/$CONF_NAME > /dev/null </dev/null | grep -q "certbot renew"; then + (crontab -l 2>/dev/null; echo "0 0,12 * * * /usr/bin/certbot renew --quiet --post-hook 'systemctl reload nginx'") | crontab - +fi + +# 7. Nginx 재시작 +sudo nginx -t +sudo systemctl restart nginx + +echo "Nginx setup complete!" diff --git a/modules/monitoring_stack/security_groups.tf b/modules/monitoring_stack/security_groups.tf new file mode 100644 index 0000000..c3a42eb --- /dev/null +++ b/modules/monitoring_stack/security_groups.tf @@ -0,0 +1,27 @@ +resource "aws_security_group" "monitoring_sg" { + name = "sc-${var.env_name}-sg" + description = "Security group for Monitoring Stack (Grafana, Prometheus, Loki)" + vpc_id = var.vpc_id + + dynamic "ingress" { + for_each = var.monitoring_ingress_rules + content { + from_port = ingress.value.from_port + to_port = ingress.value.to_port + protocol = ingress.value.protocol + cidr_blocks = ingress.value.cidr_blocks + description = ingress.value.description + } + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } + + tags = { + Name = "${var.env_name}-sg" + } +} diff --git a/modules/monitoring_stack/variables.tf b/modules/monitoring_stack/variables.tf new file mode 100644 index 0000000..7534c61 --- /dev/null +++ b/modules/monitoring_stack/variables.tf @@ -0,0 +1,56 @@ +variable "env_name" { + description = "환경 이름" + type = string +} + +variable "vpc_id" { + description = "배포할 VPC ID" + type = string +} + +variable "ami_id" { + description = "EC2 AMI ID" + type = string +} + +variable "key_name" { + description = "EC2 Key Pair 이름" + type = string +} + +variable "instance_type" { + description = "EC2 인스턴스 타입" + type = string +} + +variable "private_ip" { + description = "alloy 설정을 위한 private ip 고정" + type = string +} + +variable "monitoring_ingress_rules" { + description = "모니터링 도구(Grafana, Prometheus, Loki)를 위한 보안 규칙" + type = list(object({ + from_port = number + to_port = number + protocol = string + cidr_blocks = list(string) + description = string + })) +} + +# [Nginx 관련 추가 변수] +variable "domain_name" { + description = "Domain name for Nginx" + type = string +} + +variable "cert_email" { + description = "Email for Let's Encrypt" + type = string +} + +variable "nginx_conf_name" { + description = "Nginx config filename" + type = string +} From 0153c2878dc5c7cedb21540d926af888c87c823e Mon Sep 17 00:00:00 2001 From: Yeonri Date: Mon, 29 Dec 2025 16:34:15 +0900 Subject: [PATCH 27/27] =?UTF-8?q?feat:=20docker=5Fsetup.sh=20=EA=B3=B5?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/app_stack/ec2.tf | 2 +- modules/{app_stack => common}/scripts/docker_setup.sh | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename modules/{app_stack => common}/scripts/docker_setup.sh (100%) diff --git a/modules/app_stack/ec2.tf b/modules/app_stack/ec2.tf index 704e676..fd0c315 100644 --- a/modules/app_stack/ec2.tf +++ b/modules/app_stack/ec2.tf @@ -6,7 +6,7 @@ data "cloudinit_config" "app_init" { # [Part 1] Docker 설치 스크립트 part { content_type = "text/x-shellscript" - content = file("${path.module}/scripts/docker_setup.sh") + content = file("${path.module}/../common/scripts/docker_setup.sh") filename = "1_docker_install.sh" } diff --git a/modules/app_stack/scripts/docker_setup.sh b/modules/common/scripts/docker_setup.sh similarity index 100% rename from modules/app_stack/scripts/docker_setup.sh rename to modules/common/scripts/docker_setup.sh