#!/usr/bin/env bash # 인증서 자동 발급(0.8.18~) — root 로 실행(보통 -tls.timer 가 15분마다 부름): bash deploy/tls-when-ready.sh # # 새 서버에 설치할 때 DNS(MAIL_HOST → 이 서버)가 아직 바뀌지 않았으면 Let's Encrypt HTTP-01 검증이 실패하므로 setup.sh 는 # 80 포트만 여는 임시 nginx 설정으로 끝납니다. 이 스크립트는 MAIL_HOST 의 A 레코드가 이 서버의 IP 와 같아지는 순간을 기다렸다가 # certbot 으로 인증서를 받고 setup.sh 를 다시 실행해 443 설정·인증서 사본·메일 포트 TLS 를 켠 뒤 타이머를 멈춥니다. # 이미 인증서가 있으면 아무 일도 하지 않고 타이머만 끕니다(갱신은 certbot 의 자체 타이머가 합니다). set -euo pipefail [ "$(id -u)" = 0 ] || { echo 'root 로 실행하세요' >&2; exit 1; } . "$(dirname "$0")/lib.sh" load_site "${1:?site.env 경로}" TIMER="$APP_NAME-tls.timer" stop_timer() { systemctl disable --now "$TIMER" >/dev/null 2>&1 || true; } if [ -d "/etc/letsencrypt/live/$MAIL_HOST" ]; then echo "이미 인증서가 있습니다: $MAIL_HOST"; stop_timer; exit 0; fi # DNS 확인: 권위 DNS 가 아니라 이 서버의 해석기 기준입니다(certbot 검증 서버가 보는 값과 보통 같습니다). RESOLVED="$(getent ahostsv4 "$MAIL_HOST" 2>/dev/null | awk '{print $1}' | sort -u || true)" MINE="$(ip -4 -o addr show scope global | awk '{print $4}' | cut -d/ -f1 | sort -u)" MATCH=""; for a in $RESOLVED; do for b in $MINE; do [ "$a" = "$b" ] && MATCH="$a"; done; done if [ -z "$MATCH" ]; then echo "$MAIL_HOST 가 아직 이 서버를 가리키지 않습니다 (DNS: ${RESOLVED:-없음} / 서버: $MINE) — 다음에 다시 확인"; exit 0; fi echo "DNS 확인됨($MAIL_HOST → $MATCH). 인증서를 발급합니다" mkdir -p "$ACME_WEBROOT" # 등록된 certbot 계정이 없으면 이메일 없이 등록합니다(만료 안내 메일을 받으려면 나중에 certbot register/update_account 로 바꾸세요). ACCOUNT_FLAG=""; ls /etc/letsencrypt/accounts/*/directory/*/regr.json >/dev/null 2>&1 || ACCOUNT_FLAG="--register-unsafely-without-email" certbot certonly --webroot -w "$ACME_WEBROOT" -d "$MAIL_HOST" --non-interactive --agree-tos --keep-until-expiring $ACCOUNT_FLAG echo "발급 완료. setup.sh 를 다시 실행해 443 설정과 메일 포트 TLS 를 켭니다" SITE="$SITE" bash "$APP_DIR/repo/deploy/setup.sh" stop_timer echo "✔ TLS 준비 완료: https://$MAIL_HOST/"