Skip to content

[FEATURE] 테라폼 기반 배포 구현 - #203

Merged
gdbs1107 merged 6 commits into
developfrom
feat/#202/terraform
Jun 8, 2026
Merged

[FEATURE] 테라폼 기반 배포 구현#203
gdbs1107 merged 6 commits into
developfrom
feat/#202/terraform

Conversation

@gdbs1107

@gdbs1107 gdbs1107 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

📣 Related Issue



📝 Summary

  • 테라폼 기반 배포 구현

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 클라우드 인프라 자동화 및 배포 자동화 추가
    • 실시간 모니터링 및 알림 시스템 추가
    • 애플리케이션 성능 메트릭 수집 및 대시보드 기능
  • Chores

    • 인프라 구성 파일 및 배포 스크립트 추가
    • 웹 서버 설정 및 리버스 프록시 구성 추가

@gdbs1107 gdbs1107 self-assigned this Jun 8, 2026
@gdbs1107 gdbs1107 added ✨ feat ✨ 기능 추가 ⚙️ chore ⚙️ 빌드/배포/유지보수 작업 labels Jun 8, 2026
@gdbs1107 gdbs1107 linked an issue Jun 8, 2026 that may be closed by this pull request
1 task
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@gdbs1107, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 20 minutes and 40 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f951ad0c-86a2-4f02-ae88-b65723615171

📥 Commits

Reviewing files that changed from the base of the PR and between 48926a7 and c82ad00.

📒 Files selected for processing (7)
  • deploy/ec2/install_caddy.sh
  • deploy/ec2/install_prod_monitoring_lite.sh
  • infra/terraform/main.tf
  • infra/terraform/outputs.tf
  • infra/terraform/scripts/deploy_ec2_app.sh
  • infra/terraform/terraform.tfvars.example
  • infra/terraform/variables.tf

Walkthrough

이 PR은 AWS Terraform 기반의 IaC 인프라 관리 파이프라인을 구축합니다. VPC, EC2, RDS PostgreSQL, S3, ECR을 정의하고, EC2 사용자 데이터로 Docker/Nginx/AWS CLI를 자동 설치합니다. Nginx는 HTTP/HTTPS/내부 모드 템플릿으로 요청 ID 추적 및 JSON 로깅을 제공하고, Caddy는 선택적 리버스 프록시로 제공됩니다. 배포 자동화 스크립트는 Docker 이미지 빌드·푸시 후 원격 EC2에서 인프라 설치 및 블루-그린 배포를 실행합니다. Prometheus, Alertmanager, Grafana로 구성한 경량 모니터링 스택은 SSD API 및 호스트 메트릭을 수집하고 Discord 웹훅으로 알림을 전달합니다.

Changes

Terraform 기반 AWS 인프라 및 배포 파이프라인

Layer / File(s) Summary
Terraform 기초 설정
infra/terraform/versions.tf, infra/terraform/providers.tf, infra/terraform/variables.tf, infra/terraform/terraform.tfvars.example
Terraform 1.5.0 이상 필수, AWS 프로바이더 5.55 이상과 random 3.6 이상 제약. AWS 리전, 프로젝트/환경 식별자, VPC CIDR, SSH 접근 CIDR, 인스턴스 클래스, RDS 설정, 민감한 값들(DB 비밀번호, JWT 시크릿, Discord 웹훅, Sentry DSN) 정의. 예시 tfvars 파일 제공.
네트워킹 및 보안 그룹
infra/terraform/main.tf (lines 40-102, 103-173)
VPC, 인터넷 게이트웨이, 공개 서브넷 2개(서로 다른 AZ), 공개 라우팅 테이블 구성. 앱 보안 그룹에 SSH/HTTP/HTTPS 인바운드, DB 보안 그룹에 앱 SG에서만 PostgreSQL 5432 포트 허용.
IAM 및 EC2 키 페어
infra/terraform/main.tf (lines 174-231)
EC2용 IAM 역할(AssumeRole), ECR 읽기 전용 정책, S3 List/Get/Put/Delete 정책 첨부. 인스턴스 프로파일 생성. SSH 공개키 기반 EC2 키 페어 생성.
컴퓨팅 및 스토리지 리소스
infra/terraform/main.tf (lines 232-323)
ECR 리포지토리 생성(스캔 온 푸시 활성화). S3 자산 버킷 생성(공개 접근 차단). RDS PostgreSQL 인스턴스(다중 AZ 비활성화, 백업/암호화 설정). Ubuntu 24.04 기반 EC2 인스턴스(Elastic IP 할당).
EC2 사용자 데이터 초기화
infra/terraform/templates/ec2_user_data.sh.tftpl
부팅 시 Docker, docker-compose-v2, Nginx, AWS CLI v2, jq, curl 자동 설치. Docker/Nginx 서비스 활성화. Ubuntu 사용자를 docker 그룹에 추가. 10GB 스왑 파일 생성 및 영구 마운트.
Terraform 출력 및 배포 문서
infra/terraform/outputs.tf, infra/terraform/README.md
EC2 공개 IP, DNS, SSH 명령, ECR 저장소 URL, S3 버킷명, RDS 연결정보 노출. Terraform 부트스트랩 가이드 및 수동 배포 단계 문서화.
배포 자동화 스크립트
infra/terraform/scripts/deploy_ec2_app.sh
Terraform 출력에서 EC2 IP/ECR URL 읽기. Docker 이미지를 amd64로 빌드 및 ECR 푸시. SSH로 EC2 대기 및 접속. 배포 스크립트/설정 파일 업로드. 원격에서 install_infra.sh 실행 후 blue_green_deploy.sh로 블루-그린 배포 수행.
Nginx 사이트 템플릿 (3가지 모드)
deploy/ec2/nginx/site.http.conf.template, deploy/ec2/nginx/site.https.conf.template, deploy/ec2/nginx/site.internal.conf.template
HTTP/HTTPS/내부 모드 템플릿. 요청 ID를 $http_x_request_id에서 추출하여 로그 및 프록시 헤더에 일관되게 사용. ssd_json 형식의 JSON 액세스 로그(타임스탐프, 요청 ID, 클라이언트 IP, HTTP 메서드/URI, 상태, 응답시간 등 포함). /grafana 경로를 로컬 Grafana(3001)로, / 경로를 ssd_backend로 프록시. HTTPS 모드는 SSL 인증서 및 HTTP→HTTPS 리다이렉트 포함.
Caddy 리버스 프록시
deploy/ec2/caddy/Caddyfile.template, deploy/ec2/install_caddy.sh
Caddyfile 템플릿: zstd/gzip 인코딩 활성화, 127.0.0.1:8088로 리버스 프록시. install_caddy.sh: Cloudsmith 저장소에서 Caddy 설치. NGINX_INTERNAL_ONLY 조건에 따라 install_infra.sh 실행 후 템플릿 렌더링 및 caddy 서비스 활성화.
Nginx 설정 및 Caddy 통합
deploy/ec2/install_infra.sh
NGINX_ENABLE_SSL, NGINX_INTERNAL_ONLY 플래그 추가. site.https.conf.template(기본), site.internal.conf.template(내부 전용), site.http.conf.template(그외) 중 선택 렌더링. 기본 활성화 사이트 심볼릭 링크 제거.
모니터링 스택 설정
deploy/ec2/install_prod_monitoring_lite.sh, deploy/ec2/monitoring-lite/docker-compose.monitoring-lite.yml, deploy/ec2/monitoring-lite/prometheus/prometheus.yml, deploy/ec2/monitoring-lite/alertmanager/alertmanager.yml, deploy/ec2/monitoring-lite/prometheus/rules/ssd-alerts.yml, deploy/ec2/monitoring-lite/alertmanager/templates/discord.tmpl
경량 모니터링 설치 스크립트: 디렉터리 생성, 시크릿 처리, Discord 웹훅 파일/Grafana 환경 변수 생성. Docker Compose: Prometheus(15초 스크래핑), Alertmanager, Grafana(3001 포트), Node Exporter 서비스. Prometheus 구성: ssd-api(HTTPS) 및 node-exporter 메트릭 수집, alertmanager 연동. Alertmanager 구성: 모든 알림을 Discord receiver로 라우팅. 알림 규칙: SSD API 수집 가용성, CPU 80% 초과, 디스크 85% 초과, JVM 힙 80% 초과. Discord 템플릿: 알림 제목 및 메시지 형식화(서비스, 심각도, 설명 포함).
기타 모니터링 설정
deploy/ec2/monitoring/prometheus/prometheus.yml
기존 Prometheus 구성의 ssd-api 및 blackbox-http 잡 스킴을 http에서 https로 변경.
구성 파일 및 초기화
.gitignore, infra/terraform/.terraform.lock.hcl
.gitignore: Terraform 관련 파일(.terraform/, *.tfstate, terraform.tfvars, *.auto.tfvars, override 파일, plan 파일 등) 무시 패턴 추가. .terraform.lock.hcl: aws 5.100.0, random 3.9.0 공급자 잠금 정보 기록.

🎯 4 (Complex) | ⏱️ ~75 minutes

🐰 테라폼의 구름 위에서,
AWS 인프라 춤을 춘다네,
EC2, RDS, VPC 위로 솟아,
프로메테우스가 지켜보니,
완벽한 배포의 교향곡! ☁️✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 '[FEATURE] 테라폼 기반 배포 구현'은 변경 사항의 핵심 내용을 명확하게 반영합니다. Terraform 인프라 구성, 배포 스크립트, 모니터링 스택 등의 주요 변경이 일관되게 Terraform 기반 배포 구현으로 요약됩니다.
Linked Issues check ✅ Passed PR은 연결된 이슈 #202의 요구사항인 'Terraform을 활용한 IaC 기반 인프라 관리 파이프라인 구축'을 완벽하게 충족합니다. Terraform 모듈(main.tf, variables.tf, outputs.tf), EC2 배포 스크립트, 인프라 설정 파일들이 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed PR의 모든 변경 사항은 Terraform 기반 배포 구현과 직접 관련이 있습니다. .gitignore 추가, nginx/caddy 설정, 모니터링 스택(prometheus, alertmanager, grafana), EC2 배포 스크립트 모두 인프라 관리 파이프라인의 필수 구성 요소입니다.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#202/terraform

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gdbs1107

gdbs1107 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor Author

📝 Code Coverage

Overall Project NaN% NaN% 🍏

There is no coverage information present for the Files changed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Nitpick comments (1)
deploy/ec2/nginx/site.http.conf.template (1)

1-18: ⚡ Quick win

세 nginx 템플릿 간 공통 설정 중복을 제거하는 것을 권장합니다.

Lines 1-18의 요청 ID 매핑 및 JSON 로그 포맷 정의가 site.http.conf.template, site.https.conf.template, site.internal.conf.template 세 파일에서 동일하게 반복됩니다. 이는 유지보수 시 세 곳을 모두 수정해야 하며 불일치 위험이 있습니다.

♻️ 제안하는 리팩터링

1단계: 공통 설정을 별도 파일로 분리

deploy/ec2/nginx/ssd-common.conf 파일 생성:

map $http_x_request_id $ssd_request_id {
    "~^(?:[A-Fa-f0-9]{32}|[A-Fa-f0-9-]{36})$" $http_x_request_id;
    default $request_id;
}

log_format ssd_json escape=json
    '{"timestamp":"$time_iso8601",'
    '"requestId":"$ssd_request_id",'
    '"remoteAddr":"$remote_addr",'
    '"method":"$request_method",'
    '"uri":"$request_uri",'
    '"status":$status,'
    '"bodyBytesSent":$body_bytes_sent,'
    '"requestTime":$request_time,'
    '"upstreamStatus":"$upstream_status",'
    '"upstreamResponseTime":"$upstream_response_time",'
    '"httpReferer":"$http_referer",'
    '"userAgent":"$http_user_agent"}';

2단계: 각 템플릿에서 include로 참조

+include /etc/nginx/conf.d/ssd-common.conf;
+
-map $http_x_request_id $ssd_request_id {
-    "~^(?:[A-Fa-f0-9]{32}|[A-Fa-f0-9-]{36})$" $http_x_request_id;
-    default $request_id;
-}
-
-log_format ssd_json escape=json
-    '{"timestamp":"$time_iso8601",'
-    ...
-    '"userAgent":"$http_user_agent"}';
-
 server {

3단계: install_infra.sh에서 공통 설정 파일 설치 추가

copy_if_changed "${SCRIPT_DIR}/nginx/ssd-common.conf" "/etc/nginx/conf.d/ssd-common.conf" 644
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/ec2/nginx/site.http.conf.template` around lines 1 - 18, Extract the
duplicated mapping and log_format block (the map $http_x_request_id
$ssd_request_id and log_format ssd_json definitions) into a new shared file
(e.g., deploy/ec2/nginx/ssd-common.conf), replace the repeated blocks in
site.http.conf.template, site.https.conf.template and
site.internal.conf.template with an include of that shared file, and update the
installation script (install_infra.sh) to copy the new ssd-common.conf into
/etc/nginx/conf.d (use the existing copy_if_changed pattern) so all three
templates use the single source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deploy/ec2/install_caddy.sh`:
- Around line 18-24: 설정 파일 경로
APP_CONFIG_SOURCE="/opt/ssd/config/application-dev.yml"가 하드코딩되어 있지만 존재 여부를 확인하지
않고 install_infra.sh를 호출하고 있어 오류가 발생할 수 있습니다; install_caddy.sh에서 SCRIPT_DIR/ 설치
호출 전에 해당 파일이 실제로 존재하는지(test -f "$APP_CONFIG_SOURCE") 검사하고, 파일이 없을 경우 적절한 error
message를 출력(processLogger 대신 echo/stderr)하고 비정상 종료(exit 1) 하도록 변경하세요; 검사 코드는
APP_CONFIG_SOURCE 변수와 기존 install_infra.sh 호출 블록 바로 위(현재 if [[
"${NGINX_INTERNAL_ONLY}" == "true" ]] 내부)에서 수행하면 됩니다.

In `@deploy/ec2/install_prod_monitoring_lite.sh`:
- Around line 23-31: The current block that extracts webhook_url from
APP_CONFIG_FILE and writes to DISCORD_WEBHOOK_FILE must validate the extracted
value and fail fast if empty: after computing webhook_url (the variable in this
code block), check that it is non-empty (and not just whitespace); if empty,
emit an error message to stderr or logs and exit with a non-zero status instead
of writing an empty file and continuing; only write to DISCORD_WEBHOOK_FILE and
chmod it when webhook_url contains a valid value.
- Around line 17-20: 현재 스크립트만으로는 monitoring-lite만 복사되어 Compose가 바인드 마운트하는
../monitoring/grafana 경로와 불일치해 Grafana 컨테이너가 실패할 수 있으니, MONITORING_SOURCE_DIR에서
공용 Grafana 자산(예: ../monitoring/grafana/*)도 tmp_dir로 함께 복사하도록 설치 흐름을 확장하고 기존
tmp_dir → MONITORING_DIR 복사와 chown 처리(변수: MONITORING_SOURCE_DIR, tmp_dir,
MONITORING_DIR, DEPLOY_USER)를 동일하게 적용하며 기존 .env 및
alertmanager/secrets/discord_webhook_url 삭제 로직을 유지해 주세요.

In `@deploy/ec2/nginx/site.https.conf.template`:
- Around line 56-60: The HTTPS nginx template (site.https.conf.template) assumes
/etc/letsencrypt/live/__SERVER_NAME__/fullchain.pem and privkey.pem exist before
nginx starts; ensure the deployment workflow provisions/renews certificates
prior to running nginx -t or systemd start. Fix by adding certificate
provisioning to the startup flow — either delegate TLS to install_caddy.sh and
use nginx only internally, or add certbot install/obtain/renew steps into
install_infra.sh (or the CI/CD job) and perform cert existence checks and nginx
-t after provisioning; update the bootstrap/start script to wait for/validate
the files referenced by ssl_certificate and ssl_certificate_key before launching
nginx.

In `@infra/terraform/main.tf`:
- Around line 257-260: The RDS subnet group aws_db_subnet_group.main is
currently using public subnets aws_subnet.public_a and aws_subnet.public_c
(which have map_public_ip_on_launch = true); update subnet_ids to reference the
dedicated private subnet resources (e.g., aws_subnet.private_a.id and
aws_subnet.private_c.id or whatever private subnet identifiers exist) so the DB
is placed in private subnets instead of public ones; ensure any variable/local
name (local.name_prefix) remains unchanged and run terraform fmt/validate after
updating aws_db_subnet_group.main.
- Around line 290-307: Add IMDSv2 enforcement and explicit root volume
encryption to the aws_instance.app resource: add a metadata_options block with
http_tokens = "required" (and optionally http_put_response_hop_limit) to force
IMDSv2, and set encrypted = true inside the root_block_device (and optionally
kms_key_id if a specific CMK is required) so the root volume does not rely on
account/region defaults; update the template for resource aws_instance.app,
referencing metadata_options and the existing root_block_device stanza.
- Around line 232-241: Locate the aws_ecr_repository resource named "app"
(resource "aws_ecr_repository" "app") and change the image_tag_mutability
attribute from "MUTABLE" to "IMMUTABLE" so tags cannot be overwritten; update
any related documentation or variable defaults (var.ecr_repository_name usage
can remain) and run terraform plan/apply to apply the change.

In `@infra/terraform/outputs.tf`:
- Around line 41-45: Remove the Terraform output block named "db_password" (the
output "db_password" that returns local.resolved_db_password) or replace it with
a secure secret-store export instead; update any automation that expects this
output to instead read the password from the chosen secret manager, and
remove/rename references to the db_password output in deployment scripts or CI
so nothing consumes terraform output -raw/-json for credentials. Ensure any
replacement uses a secret backend (e.g., AWS Secrets Manager / SSM Parameter
Store) and that the code paths which previously referenced
local.resolved_db_password are updated to fetch from that secret store.

In `@infra/terraform/scripts/deploy_ec2_app.sh`:
- Around line 72-87: The heredoc in deploy_ec2_app.sh currently uses an unquoted
EOF so the local shell expands variables before sending the script; update the
SSH heredoc to use a quoted delimiter (e.g. 'EOF') to prevent client-side
expansion and instead pass required values explicitly into the remote
environment (for example export or inline env for the remote commands that call
/home/${SSH_USER}/ec2/install_infra.sh and
/home/${SSH_USER}/ec2/blue_green_deploy.sh). Ensure the environment variables
referenced inside the heredoc—APP_CONFIG_SOURCE, NGINX_ENABLE_SSL,
NGINX_SERVER_NAME, AWS_REGION, ECR_URL, IMAGE_TAG, SPRING_PROFILE,
APP_GRAFANA_BASE_URL, HEALTH_PATH—are set on the remote side (via sudo -E,
export, or by prefixing the remote command) so the scripts install_infra.sh and
blue_green_deploy.sh receive them and no client-side expansion happens.

In `@infra/terraform/variables.tf`:
- Around line 86-105: Remove the hardcoded secret defaults for the variables
jwt_secret, discord_webhook_url, and sentry_dsn: delete the default = "..."
lines and keep sensitive = true so these vars must be supplied externally (via
terraform.tfvars, environment variables, or a secret manager); optionally add a
brief description or validation block if desired to enforce non-empty values
(refer to variables jwt_secret, discord_webhook_url, sentry_dsn to locate the
declarations).

---

Nitpick comments:
In `@deploy/ec2/nginx/site.http.conf.template`:
- Around line 1-18: Extract the duplicated mapping and log_format block (the map
$http_x_request_id $ssd_request_id and log_format ssd_json definitions) into a
new shared file (e.g., deploy/ec2/nginx/ssd-common.conf), replace the repeated
blocks in site.http.conf.template, site.https.conf.template and
site.internal.conf.template with an include of that shared file, and update the
installation script (install_infra.sh) to copy the new ssd-common.conf into
/etc/nginx/conf.d (use the existing copy_if_changed pattern) so all three
templates use the single source of truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 92a26415-77e6-44b0-9566-a991dc07d199

📥 Commits

Reviewing files that changed from the base of the PR and between 1ece0e0 and 48926a7.

📒 Files selected for processing (25)
  • .gitignore
  • deploy/ec2/caddy/Caddyfile.template
  • deploy/ec2/install_caddy.sh
  • deploy/ec2/install_infra.sh
  • deploy/ec2/install_prod_monitoring_lite.sh
  • deploy/ec2/monitoring-lite/alertmanager/alertmanager.yml
  • deploy/ec2/monitoring-lite/alertmanager/secrets/.gitkeep
  • deploy/ec2/monitoring-lite/alertmanager/templates/discord.tmpl
  • deploy/ec2/monitoring-lite/docker-compose.monitoring-lite.yml
  • deploy/ec2/monitoring-lite/prometheus/prometheus.yml
  • deploy/ec2/monitoring-lite/prometheus/rules/ssd-alerts.yml
  • deploy/ec2/monitoring/prometheus/prometheus.yml
  • deploy/ec2/nginx/site.http.conf.template
  • deploy/ec2/nginx/site.https.conf.template
  • deploy/ec2/nginx/site.internal.conf.template
  • infra/terraform/.terraform.lock.hcl
  • infra/terraform/README.md
  • infra/terraform/main.tf
  • infra/terraform/outputs.tf
  • infra/terraform/providers.tf
  • infra/terraform/scripts/deploy_ec2_app.sh
  • infra/terraform/templates/ec2_user_data.sh.tftpl
  • infra/terraform/terraform.tfvars.example
  • infra/terraform/variables.tf
  • infra/terraform/versions.tf

Comment thread deploy/ec2/install_caddy.sh
Comment thread deploy/ec2/install_prod_monitoring_lite.sh
Comment thread deploy/ec2/install_prod_monitoring_lite.sh
Comment on lines +56 to +60
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/__SERVER_NAME__/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/__SERVER_NAME__/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

❓ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# 인증서 발급/관리 관련 코드 검색

echo "=== Searching for certbot/letsencrypt setup ==="
rg -n -C3 'certbot|letsencrypt|acme' --type=sh

echo ""
echo "=== Searching for SSL certificate provisioning ==="
rg -n -C3 'ssl_certificate|fullchain\.pem|privkey\.pem' --type=sh

Repository: capstone-ssd/ssd-server

Length of output: 1949


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Confirm target template exists and show relevant lines ==="
ls -la deploy/ec2/nginx/site.https.conf.template 2>/dev/null || true
nl -ba deploy/ec2/nginx/site.https.conf.template | sed -n '40,90p' || true

echo
echo "=== Search for certbot/letsencrypt/acme setup (all relevant script types) ==="
rg -n --hidden --no-ignore \
  -S 'certbot|letsencrypt|acme' \
  deploy . --glob '!.git/*' --type-add 'sh:*.sh' --type sh 2>/dev/null || true

echo
echo "=== Search for certificate file references ==="
rg -n --hidden --no-ignore \
  -S 'ssl_certificate|fullchain\.pem|privkey\.pem|ssl_dhparam' \
  . --glob '!.git/*' 2>/dev/null || true

echo
echo "=== Locate install scripts mentioned in the review comment ==="
fd -a --hidden --no-ignore --type f 'install_caddy.sh|install_infra.sh' . 2>/dev/null || true

echo
echo "=== Show those scripts if found ==="
for f in $(fd -a --hidden --no-ignore --type f 'install_caddy.sh|install_infra.sh' . 2>/dev/null || true); do
  echo "----- $f -----"
  nl -ba "$f" | sed -n '1,220p'
  echo
done

Repository: capstone-ssd/ssd-server

Length of output: 1968


🏁 Script executed:

#!/bin/bash
echo "=== Searching for certbot/letsencrypt/acme setup ==="
rg -n -C3 'certbot|letsencrypt|acme' . --glob '!.git/*'

echo ""
echo "=== Searching for SSL certificate provisioning ==="
rg -n -C3 'ssl_certificate|fullchain\.pem|privkey\.pem' . --glob '!.git/*'

Repository: capstone-ssd/ssd-server

Length of output: 1968


HTTPS 템플릿 전제(인증서 사전 존재) 보장 여부를 확인하세요.

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/__SERVER_NAME__/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/__SERVER_NAME__/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

위 설정은 fullchain.pem/privkey.pemnginx 기동 전에 해당 경로에 존재해야 합니다. 배포 스크립트(또는 워크플로우)에서 인증서 발급/갱신 로직이 nginx 시작 이전에 수행되도록 되어 있는지 확인해주세요. 그렇지 않으면 nginx 검증(nginx -t)/기동이 실패할 수 있습니다.

인증서 프로비저닝 책임이 레포에 없다면 아래 중 하나로 구조를 정리해야 합니다:

  1. Caddy 사용 (권장): install_caddy.sh로 자동 HTTPS를 위임하고 nginx는 내부 전용으로 사용
  2. Certbot 추가: install_infra.sh 또는 별도 스크립트에서 certbot 설치 + 발급/갱신 로직 추가
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/ec2/nginx/site.https.conf.template` around lines 56 - 60, The HTTPS
nginx template (site.https.conf.template) assumes
/etc/letsencrypt/live/__SERVER_NAME__/fullchain.pem and privkey.pem exist before
nginx starts; ensure the deployment workflow provisions/renews certificates
prior to running nginx -t or systemd start. Fix by adding certificate
provisioning to the startup flow — either delegate TLS to install_caddy.sh and
use nginx only internally, or add certbot install/obtain/renew steps into
install_infra.sh (or the CI/CD job) and perform cert existence checks and nginx
-t after provisioning; update the bootstrap/start script to wait for/validate
the files referenced by ssl_certificate and ssl_certificate_key before launching
nginx.

Comment thread infra/terraform/main.tf
Comment thread infra/terraform/main.tf
Comment thread infra/terraform/main.tf
Comment thread infra/terraform/outputs.tf Outdated
Comment thread infra/terraform/scripts/deploy_ec2_app.sh Outdated
Comment thread infra/terraform/variables.tf
@gdbs1107
gdbs1107 merged commit 8c41293 into develop Jun 8, 2026
2 checks passed
@gdbs1107
gdbs1107 deleted the feat/#202/terraform branch June 8, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚙️ chore ⚙️ 빌드/배포/유지보수 작업 ✨ feat ✨ 기능 추가 💪🏼 재연

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 테라폼을 활용한 인프라 관리 파이프라인 구축

1 participant