서버 운영
HTTPS 인증서가 만료되거나 유효하지 않을 때
운영 중 HTTPS 인증서 에러가 발생했을 때, 원인을 빠르게 파악하고 대응하는 순서를 정리했다.
어느 날 갑자기 사용자들이 "사이트가 안 열려요"라고 신고했다. 브라우저에서는 "인증서가 유효하지 않습니다"라고 뜬다. 심각한 상황이다.
HTTPS 인증서는 갱신 기한, DNS 설정, 서버 설정 등이 맞물려 있어서, 하나만 틀려도 사용자들이 전부 못 접근한다.
먼저 확인할 신호들
Curl로 직접 테스트해본다.
dig example.com
# DNS 응답이 올바른가?
curl -I https://example.com
# HTTP 상태 코드가 뭔가? 에러 메시지가 나오는가?
curl -v https://example.com 2>&1 | grep certificate
# 인증서 에러의 구체적인 내용은?
에러 메시지가 "인증서 만료", "호스트명 불일치", "자체 서명 인증서" 등 구체적으로 나온다.
Nginx 설정 확인
sudo nginx -t
# Nginx 설정이 유효한가?
sudo nginx -T
# 전체 설정을 더 자세히 본다
SSL 인증서 경로, 키 파일 경로가 정확한지 확인한다.
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
경로가 실제로 존재하는가? 파일이 읽을 수 있는 권한이 있는가?
인증서 만료일 확인
# 인증서의 유효 기간 확인
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep -A 2 "Validity"
# 또는
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
현재 날짜보다 before, after 범위를 확인한다. 만료일이 지났다면 즉시 갱신해야 한다.
DNS 설정과 호스트명 불일치
인증서의 CN(Common Name)이나 SAN(Subject Alternative Name)이 실제 도메인과 일치하는가?
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep -A 1 "Subject:"
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -text -noout | grep "DNS:"
예를 들어 인증서가 example.com만 있는데 www.example.com으로 접속하면 에러가 난다.
Let's Encrypt 자동 갱신
Let's Encrypt 인증서는 보통 90일마다 갱신해야 한다. 자동 갱신이 설정돼 있는가?
# Certbot 갱신 테스트
sudo certbot renew --dry-run
# Systemd timer 확인
sudo systemctl list-timers certbot
# 또는 Cron job
sudo crontab -l | grep certbot
갱신 후 Nginx를 reload해야 새 인증서가 적용된다.
즉시 대응
만료된 인증서는 바로 갱신해야 한다.
# 수동 갱신
sudo certbot renew --force-renewal
# Nginx reload (재시작이 아니라 reload)
sudo systemctl reload nginx
Browser 캐시 때문에 사용자들이 여전히 에러를 볼 수 있으니, 사용자들에게 브라우저 캐시를 비우라고 안내한다.
마지막으로, HTTPS 문제는 사용자들을 즉시 차단하므로 가장 심각하다. 특히 Let's Encrypt 갱신은 자동화되어야 하고, 갱신 실패 시 알림이 와야 한다. 미리 모니터링을 설정해두면, 만료 며칠 전에 미리 알 수 있다.