Skip to content

fix: nginx 인증서 자동 갱신 안정화#55

Merged
Hexeong merged 5 commits into
mainfrom
fix/54-certificate-auto-renew-stabilization
Jul 14, 2026
Merged

fix: nginx 인증서 자동 갱신 안정화#55
Hexeong merged 5 commits into
mainfrom
fix/54-certificate-auto-renew-stabilization

Conversation

@Hexeong

@Hexeong Hexeong commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

관련 이슈

작업 내용

  • Monitoring Nginx 인증서 발급/갱신 방식을 standalone에서 webroot 방식으로 변경했습니다.

    • certbot이 80번 포트를 직접 점유하지 않고, nginx가 /.well-known/acme-challenge/ 요청을 처리합니다.
    • 인증서 발급/갱신 과정에서 monitoring EC2 또는 nginx를 중지하지 않도록 변경했습니다.
    • 자동 갱신 cron을 /etc/cron.d/certbot-$CONF_NAME 파일로 관리하도록 변경해 중복 등록을 방지했습니다.
  • Monitoring EC2에 nginx 설정 변경 반영 경로를 추가했습니다.

    • nginx_setup.sh.tftpl 렌더링 결과의 hash를 terraform_data.update_nginx 트리거로 사용합니다.
    • hash 변경 시 SSM RunCommand로 기존 monitoring EC2에서 nginx setup script를 재실행합니다.
    • monitoring EC2에 SSM 전용 instance profile을 주입할 수 있도록 ec2_iam_instance_profile 변수를 추가했습니다.
  • Prod/Stage 공용 app_stack Nginx 인증서 갱신도 동일하게 안정화했습니다.

    • certbot --standalonesystemctl stop nginx 흐름을 제거했습니다.
    • 기존 인증서가 있으면 443 설정을 유지한 상태로 nginx reload 후 webroot certbot을 실행합니다.
    • 인증서가 없는 최초 구성 시에는 HTTP challenge용 bootstrap config를 먼저 적용합니다.
    • null_resource.update_nginx의 기존 script hash 기반 재실행 구조는 유지했습니다.
  • Monitoring secrets submodule을 갱신했습니다.

    • monitoring 환경에서 전용 SSM instance profile을 사용하도록 tfvars를 갱신했습니다.

특이 사항

  • 이번 변경은 EC2 destroy/recreate를 유발하지 않습니다.
  • nginx 설정 반영은 정상 경로에서 reload로 수행되며, reload 실패 시에만 restart fallback을 사용합니다.
  • Prod/Stage는 기존처럼 nginx_setup.sh.tftpl 내용이 바뀌면 script hash 변경으로 null_resource.update_nginx가 재실행됩니다.
  • Monitoring은 이번 PR부터 terraform_data.update_nginx를 통해 동일한 hash 기반 재실행 구조를 갖습니다.

검증 결과:

  • bash -n modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
  • bash -n modules/app_stack/scripts/nginx_setup.sh.tftpl
  • terraform validate for environment/monitoring
  • terraform validate for environment/stage
  • terraform validate for environment/prod
  • Monitoring plan: EC2 instance profile in-place update + terraform_data.update_nginx 생성
  • Stage plan: null_resource.update_nginx script hash replacement only
  • Prod plan: SSH tunnel 연결 후 full refresh plan 성공, null_resource.update_nginx script hash replacement only

리뷰 요구사항 (선택)

  • webroot 방식으로 전환한 nginx challenge location이 HTTP redirect/default server 차단 로직과 충돌하지 않는지 확인해주세요.
  • Monitoring 전용 SSM instance profile을 사용하는 방향이 prod/stage app instance profile과 권한 경계를 분리하는 방식으로 적절한지 확인해주세요.
  • Prod/Stage에서 인증서가 이미 있는 경우 443 설정을 유지하고, 인증서가 없는 경우 bootstrap HTTP config를 사용하는 분기 흐름이 적절한지 확인해주세요.

Summary by CodeRabbit

  • 새 기능
    • 모니터링 서버에 SSM RunCommand 실행용 인스턴스 프로필을 선택적으로 연결할 수 있게 됐습니다.
    • Nginx/인증서 설정을 SSM 기반 원격 적용으로 자동화했습니다.
    • 인증서 발급/갱신 방식을 웹루트 기반으로 전환해 자동 갱신 시에도 웹 구성을 안정적으로 유지합니다.
  • 버그 수정
    • Nginx 적용을 검증 후 일관된 로드/리로드 흐름으로 정리해 서비스 중단 위험을 낮췄습니다.
    • 갱신 스케줄 및 갱신 훅 설정이 개선되어 갱신 작업 안정성이 향상됐습니다.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e16eba18-6ec9-419d-b673-3b64a947d62a

📥 Commits

Reviewing files that changed from the base of the PR and between 7b05728 and f5aaa43.

📒 Files selected for processing (3)
  • config/secrets
  • modules/app_stack/scripts/nginx_setup.sh.tftpl
  • modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
🚧 Files skipped from review as they are similar to previous changes (2)
  • config/secrets
  • modules/app_stack/scripts/nginx_setup.sh.tftpl

📝 Walkthrough

Walkthrough

monitoring_stack 및 app_stack의 nginx 설정이 standalone Certbot에서 webroot 기반 HTTP-01 challenge 방식으로 전환되었다. monitoring_stack에는 IAM instance profile과 SSM RunCommand 기반 nginx 설정 재실행 경로가 추가되었으며, 관련 변수와 모듈 배선 및 secrets 서브프로젝트 참조가 갱신되었다.

Changes

Nginx SSL 갱신 및 SSM 재실행

Layer / File(s) Summary
monitoring_stack nginx webroot 흐름
modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
HTTP-01 challenge용 webroot 설정, webroot 기반 인증서 발급·갱신, cron.d 자동 갱신과 nginx reload hook을 추가했다.
app_stack nginx 함수화 및 webroot 전환
modules/app_stack/scripts/nginx_setup.sh.tftpl
nginx 설정 생성과 reload를 함수화하고, 인증서 미존재 시 challenge 설정을 적용한 뒤 인증서 발급 후 full 설정을 재적용하도록 변경했다.
EC2 및 SSM 재실행 경로
modules/monitoring_stack/ec2.tf
nginx 스크립트를 locals로 렌더링하고 EC2 IAM 프로파일과 SSM RunCommand 기반 설정 재실행 및 상태 폴링을 추가했다.
변수·모듈 배선 및 서브프로젝트 참조
modules/monitoring_stack/variables.tf, environment/monitoring/variables.tf, environment/monitoring/main.tf, config/secrets
IAM instance profile 변수를 선언·전달하고 secrets 서브프로젝트 커밋 참조를 갱신했다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Terraform
  participant SSM as AWS SSM
  participant EC2 as monitoring_server
  participant Nginx
  participant Certbot

  Terraform->>SSM: SSM 에이전트 온라인 대기
  Terraform->>SSM: send-command(setup_nginx.sh)
  SSM->>EC2: nginx 설정 스크립트 실행
  EC2->>Nginx: challenge 설정 작성 및 reload
  EC2->>Certbot: certonly --webroot 인증서 발급
  EC2->>Nginx: full 설정 작성 및 reload
  Terraform->>SSM: 실행 상태 폴링
  SSM-->>Terraform: Success 또는 실패 상태
  Certbot->>Nginx: renew deploy-hook reload
Loading

Possibly related PRs

Suggested labels: 인프라

Suggested reviewers: gyuhyeok99, sukangpunch, wibaek, whqtker, lsy1307

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Monitoring 외에 app_stack/prod-stage 및 config/secrets 갱신이 포함되어 있어 #54 범위를 벗어납니다. Monitoring 관련 변경과 분리해 별도 PR로 제출하거나, linked issue에 prod/stage와 secrets 갱신 범위를 명시해 주세요.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 nginx 인증서 자동 갱신 안정화라는 핵심 변경을 정확히 요약합니다.
Description check ✅ Passed 필수 섹션이 모두 포함되어 있고 작업 내용과 주의사항이 구체적으로 적혀 있습니다.
Linked Issues check ✅ Passed Monitoring에서 webroot 전환, nginx reload, cron 관리, SSM 재적용 경로 추가로 #54 요구사항을 충족합니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/54-certificate-auto-renew-stabilization

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.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Terraform Plan: monitoring

Plan: 1 to add, 1 to change, 0 to destroy.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Terraform Plan: global

No changes. Your infrastructure matches the configuration.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Terraform Plan: stage

Plan: 1 to add, 0 to change, 1 to destroy.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown

Terraform Plan: prod

Plan: 1 to add, 0 to change, 1 to destroy.

전체 plan 결과는 보안을 위해 댓글에 포함되지 않습니다. 워크플로우 실행 아티팩트를 확인하세요.

@Hexeong Hexeong marked this pull request as ready for review July 8, 2026 05:54
@Hexeong Hexeong self-assigned this Jul 8, 2026
@Hexeong Hexeong added the bug Something isn't working label Jul 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b05728b97

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread modules/app_stack/scripts/nginx_setup.sh.tftpl Outdated
Comment thread modules/monitoring_stack/scripts/nginx_setup.sh.tftpl Outdated

@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: 1

🧹 Nitpick comments (2)
modules/monitoring_stack/scripts/nginx_setup.sh.tftpl (1)

22-45: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

인증서가 있으면 80 전용 설정으로 먼저 덮어쓰지 마세요
modules/monitoring_stack/scripts/nginx_setup.sh.tftpl:22-45에서 매번 80 전용 설정으로 reload한 뒤 full 설정을 다시 쓰고 있어서, 기존 인증서가 있는 재실행에서도 443 서버 블록이 잠깐 사라집니다. 인증서가 이미 있으면 처음부터 full 설정을 적용하고, challenge location만 추가하는 분기로 바꾸는 편이 좋습니다.

🤖 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 `@modules/monitoring_stack/scripts/nginx_setup.sh.tftpl` around lines 22 - 45,
The nginx setup flow in the script template is overwriting the existing config
with an HTTP-only server block before restoring the full TLS config, which can
temporarily drop the 443 block on reruns. Update the branching around the nginx
config generation so the existing-cert path writes the full server configuration
from the start, and only adds the ACME challenge location needed for certbot;
keep the no-cert path on the current 80-only bootstrap. Use the nginx config
generation and reload logic in the script template to locate the change.
modules/app_stack/scripts/nginx_setup.sh.tftpl (1)

154-180: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

중복된 full 설정 작성/심볼릭 링크 처리.

인증서가 이미 존재하는 경로(154-162행)에서 write_full_nginx_conf + 심볼릭 링크 + default 제거를 수행한 뒤, 176-180행에서 동일 작업이 다시 반복됩니다. challenge→full 전환이 필요한 최초 발급 경로를 제외하면 중복이므로, 발급이 실제로 필요한 경우에만 재작성하도록 정리하면 흐름이 단순해집니다.

🤖 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 `@modules/app_stack/scripts/nginx_setup.sh.tftpl` around lines 154 - 180, The
nginx setup flow is duplicating the full config write and site symlink/default
cleanup in the certificate-present branch and again after certbot runs. Refactor
the logic around write_full_nginx_conf, write_http_challenge_conf, the ln -sf
/etc/nginx/sites-available/$CONF_NAME step, and reload_nginx so the full
configuration and symlink cleanup happen only once after a successful
issuance/renewal, while the challenge config remains only for the initial
HTTP-01 path.
🤖 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 `@modules/monitoring_stack/scripts/nginx_setup.sh.tftpl`:
- Around line 102-108: Split the cron file name used in the certbot setup from
CONF_NAME, since the current /etc/cron.d/certbot-$CONF_NAME naming can inherit
dots from nginx_conf_name and be ignored by cron. Update the
nginx_setup.sh.tftpl block that writes the cron entry so the /etc/cron.d
filename is a fixed or sanitized value, while keeping CONF_NAME only for the
rest of the setup logic. Use the certbot renewal cron stanza as the location to
make this change.

---

Nitpick comments:
In `@modules/app_stack/scripts/nginx_setup.sh.tftpl`:
- Around line 154-180: The nginx setup flow is duplicating the full config write
and site symlink/default cleanup in the certificate-present branch and again
after certbot runs. Refactor the logic around write_full_nginx_conf,
write_http_challenge_conf, the ln -sf /etc/nginx/sites-available/$CONF_NAME
step, and reload_nginx so the full configuration and symlink cleanup happen only
once after a successful issuance/renewal, while the challenge config remains
only for the initial HTTP-01 path.

In `@modules/monitoring_stack/scripts/nginx_setup.sh.tftpl`:
- Around line 22-45: The nginx setup flow in the script template is overwriting
the existing config with an HTTP-only server block before restoring the full TLS
config, which can temporarily drop the 443 block on reruns. Update the branching
around the nginx config generation so the existing-cert path writes the full
server configuration from the start, and only adds the ACME challenge location
needed for certbot; keep the no-cert path on the current 80-only bootstrap. Use
the nginx config generation and reload logic in the script template to locate
the change.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 60bcfba8-8100-433c-8ed4-208cdfeb15f6

📥 Commits

Reviewing files that changed from the base of the PR and between fc79ded and 7b05728.

📒 Files selected for processing (7)
  • config/secrets
  • environment/monitoring/main.tf
  • environment/monitoring/variables.tf
  • modules/app_stack/scripts/nginx_setup.sh.tftpl
  • modules/monitoring_stack/ec2.tf
  • modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
  • modules/monitoring_stack/variables.tf

Comment thread modules/monitoring_stack/scripts/nginx_setup.sh.tftpl
@wibaek

wibaek commented Jul 8, 2026

Copy link
Copy Markdown
Member

👍 Caddy 사용도 고려해볼 수 있을 것 같네요

@Hexeong

Hexeong commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

👍 Caddy 사용도 고려해볼 수 있을 것 같네요

찾아본 결과, Caddy가 현재 nginx의 역할을 대체할 수 있다는 점 확인했습니다! 이번 PR이 반영되고 동일한 문제가 발생한다면 해당 작업 진행해보는 방향으로 하겠습니다!

@lsy1307 lsy1307 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

전체 nginx/webroot 전환 흐름은 괜찮아 보입니다. 기존 인증서가 있으면 full nginx config를 유지한 상태에서 challenge location만 포함하고, 인증서가 없을 때만 HTTP challenge bootstrap config를 쓰는 분기도 적절해 보입니다.

다만 config/secrets submodule 포인터 변경에 monitoring.tfvars뿐 아니라 prod.tfvars 변경도 함께 포함되어 있습니다. prod plan 결과가 null_resource.update_nginx 교체만 나온다고 적어주셔서 실제 영향은 없어 보이지만, PR 설명에는 monitoring secrets 갱신만 언급되어 있어 prod tfvars 변경도 의도된 최신화인지 한 줄 남겨주면 더 명확할 것 같습니다.

@Hexeong

Hexeong commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

전체 nginx/webroot 전환 흐름은 괜찮아 보입니다. 기존 인증서가 있으면 full nginx config를 유지한 상태에서 challenge location만 포함하고, 인증서가 없을 때만 HTTP challenge bootstrap config를 쓰는 분기도 적절해 보입니다.

다만 config/secrets submodule 포인터 변경에 monitoring.tfvars뿐 아니라 prod.tfvars 변경도 함께 포함되어 있습니다. prod plan 결과가 null_resource.update_nginx 교체만 나온다고 적어주셔서 실제 영향은 없어 보이지만, PR 설명에는 monitoring secrets 갱신만 언급되어 있어 prod tfvars 변경도 의도된 최신화인지 한 줄 남겨주면 더 명확할 것 같습니다.

해당 내용은 다른 PR이 머지됨과 함께 서브 모듈 포인터 충돌을 해결하고자 반영된 내용입니다. 포인터를 최신화하는 과정에서 반영되었기에 해당 PR의 작업내용은 아니지만, nginx 설정이 반영되는 과정에 있어 문제가 없게 최신화를 진행했습니다.

@lsy1307 lsy1307 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

meow

@Hexeong Hexeong merged commit 5f40744 into main Jul 14, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: nginx SSL 인증서 자동 갱신 안정화

3 participants