Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b54e0b2
feat: .gitignore 파일 추가
Hexeong Dec 19, 2025
f142fa9
fix: stage 환경의 terraform state 정보 ignore 처리
Hexeong Dec 19, 2025
649101f
docs: readme 디렉토리 구조 최신화
Hexeong Dec 19, 2025
72cc107
feat: 인스턴스 생성시 실행할 docker_setup 스크립트 작성
Hexeong Dec 22, 2025
2f1e17f
feat: 인스턴스 생성시 실행할 nginx_setup 스크립트 작성
Hexeong Dec 22, 2025
3511142
feat: 모듈로써 app_stack(ec2 + rds) 구현
Hexeong Dec 22, 2025
bb0e1b5
feat: app_stack 모듈을 사용한 stage 환경 구축
Hexeong Dec 22, 2025
8732f88
feat: app_stack 모듈을 사용한 prod 환경 구축
Hexeong Dec 22, 2025
5a652af
chore: monitoring 환경 정의를 위한 .tf 파일들 생성
Hexeong Dec 22, 2025
d872a07
chore: add infra secrets
Hexeong Dec 22, 2025
db3f24b
refactor: 보안그룹 인바운드 변수화 & 불필요한 주석 제거
Hexeong Dec 22, 2025
4af0ad7
docs: .gitignore 파일 수정
Hexeong Dec 22, 2025
d956d5a
refactor: 중앙 집중된 시크릿을 고려한 전체 폴더 구조 개선
Hexeong Dec 22, 2025
c04fb6d
feat: stage 환경에 대한 시크릿 값을 variable로 연결
Hexeong Dec 22, 2025
42f3cf1
feat: prod 환경에 대한 시크릿 값을 variable로 연결
Hexeong Dec 22, 2025
c422d7f
chore: 컨벤션 준수를 위한 마지막 줄 개행
Hexeong Dec 22, 2025
34328ec
feat: 부하테스트 환경 정의 용도의 파일 생성
Hexeong Dec 22, 2025
fe6d034
refactor: 확장자 인식을 위한 nginx_setup 스크립트 이름 변경
Hexeong Dec 23, 2025
266ee67
refactor: provider 구문을 app_stack/main에서 분리
Hexeong Dec 23, 2025
00fbed1
refactor: 길어진 main.tf 파일을 각 리소스별로 파일 단위 분리
Hexeong Dec 23, 2025
82ed57b
feat: s3 default, upload bucket을 테라폼으로 관리하도록 상태 추가
Hexeong Dec 23, 2025
4812b4b
chore: 쓰지 않는 app_stack/variable 제거
Hexeong Dec 23, 2025
1861292
chore: prod/stage 환경에서 쓰지 않는 변수 전달 제거
Hexeong Dec 23, 2025
765dc78
chore: prod/stage 환경에서 쓰지 않는 variable 제거
Hexeong Dec 23, 2025
b06fe62
chore: 폴더 구조 변경에 따른 README.md 수정
Hexeong Dec 23, 2025
4db146e
Merge remote-tracking branch 'origin/main'
lsy1307 Dec 27, 2025
7045993
Merge remote-tracking branch 'origin/main'
lsy1307 Dec 27, 2025
364d0ac
feat: monitoring 시스템 인프라 구성
lsy1307 Dec 29, 2025
0153c28
feat: docker_setup.sh 공용으로 사용하도록 설정
lsy1307 Dec 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/secrets
30 changes: 29 additions & 1 deletion environment/monitoring/main.tf
Original file line number Diff line number Diff line change
@@ -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
}
52 changes: 51 additions & 1 deletion environment/monitoring/variables.tf
Original file line number Diff line number Diff line change
@@ -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
}
Comment on lines +32 to +36
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's explore the repository structure
echo "=== Repository structure ==="
git ls-files | head -20

echo -e "\n=== Check if modules/monitoring_stack exists ==="
find . -type d -name "monitoring_stack" 2>/dev/null

echo -e "\n=== List files in monitoring_stack directory ==="
find . -path "*/monitoring_stack/*" -type f 2>/dev/null | head -20

Repository: solid-connection/solid-connection-infra

Length of output: 1014


🏁 Script executed:

#!/bin/bash
# Search for ebs_volume_size usage across the entire repository
echo "=== Searching for ebs_volume_size usage ==="
rg -n "ebs_volume_size" --type tf

echo -e "\n=== Also search in all files (not just .tf) ==="
rg -n "ebs_volume_size"

Repository: solid-connection/solid-connection-infra

Length of output: 311


🏁 Script executed:

#!/bin/bash
# Check the specific ec2.tf file in monitoring_stack
echo "=== Looking for ec2.tf files ==="
fd "ec2.tf" 

echo -e "\n=== Content of monitoring_stack ec2.tf (if exists) ==="
if find . -path "*/monitoring_stack/ec2.tf" -type f 2>/dev/null | grep -q "ec2.tf"; then
  cat "$(find . -path '*/monitoring_stack/ec2.tf' -type f 2>/dev/null | head -1)"
fi

Repository: solid-connection/solid-connection-infra

Length of output: 1494


미사용 변수 제거 필요

ebs_volume_size 변수가 정의되어 있지만 코드베이스 어디에서도 사용되지 않습니다. modules/monitoring_stack/ec2.tfaws_instance.monitoring_server 리소스에서 이 변수가 참조되지 않고 있으며 ebs_block_device 블록도 없습니다. 변수를 제거하거나, 향후 사용할 계획이 있다면 EC2 리소스에 EBS 볼륨 구성을 추가하세요.

🤖 Prompt for AI Agents
In environment/monitoring/variables.tf around lines 32 to 36, the variable
`ebs_volume_size` is defined but unused; either remove this variable definition
to avoid dead configuration, or wire it into modules/monitoring_stack/ec2.tf by
adding an `ebs_block_device` (or `root_block_device` modification) on
`aws_instance.monitoring_server` that references var.ebs_volume_size and
updating any module input variables accordingly so the EC2 resource actually
uses the defined size.


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
}
2 changes: 1 addition & 1 deletion modules/app_stack/ec2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}

Expand Down
56 changes: 56 additions & 0 deletions modules/monitoring_stack/ec2.tf
Original file line number Diff line number Diff line change
@@ -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 = <<EOF
write_files:
- path: /home/ubuntu/setup_nginx.sh
owner: ubuntu:ubuntu
permissions: '0755'
content: |
${indent(6, templatefile("${path.module}/scripts/nginx_setup.sh.tftpl", {
domain_name = var.domain_name
email = var.cert_email
conf_file_name = var.nginx_conf_name
}))}
EOF
}
}

resource "aws_instance" "monitoring_server" {
ami = var.ami_id
instance_type = var.instance_type
key_name = var.key_name

associate_public_ip_address = true

vpc_security_group_ids = [aws_security_group.monitoring_sg.id]

user_data_base64 = data.cloudinit_config.app_init.rendered

user_data_replace_on_change = false

private_ip = var.private_ip

tags = {
Name = "solid-connection-monitoring"
}

lifecycle {
ignore_changes = [
user_data,
user_data_base64,
ami
]
}
}
7 changes: 7 additions & 0 deletions modules/monitoring_stack/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "monitoring_instance_public_ip" {
value = aws_instance.monitoring_server.public_ip
}

output "monitoring_sg_id" {
value = aws_security_group.monitoring_sg.id
}
77 changes: 77 additions & 0 deletions modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/bin/bash
set -e

# --- 변수 설정 (Terraform에서 주입) ---
DOMAIN="${domain_name}"
EMAIL="${email}"
CONF_NAME="${conf_file_name}"

echo ">>> [수동 실행] $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 <<EOF
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;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers HIGH:!aNULL:!MD5;

location / {
proxy_pass http://127.0.0.1:3000;
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;

proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
}
}
EOF

# 5. 설정 활성화
sudo ln -sf /etc/nginx/sites-available/$CONF_NAME /etc/nginx/sites-enabled/$CONF_NAME
sudo rm -f /etc/nginx/sites-enabled/default

# 6. 자동 갱신 크론탭 등록
if ! crontab -l 2>/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!"
27 changes: 27 additions & 0 deletions modules/monitoring_stack/security_groups.tf
Original file line number Diff line number Diff line change
@@ -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"
}
}
56 changes: 56 additions & 0 deletions modules/monitoring_stack/variables.tf
Original file line number Diff line number Diff line change
@@ -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
}