HTTPS 무료 인증서 자동화 — Let's Encrypt + certbot 완전 정복
인증서 만료로 서비스가 먹통 된 경험
2023년 3월 금요일 오후 4시. 모니터링 알림: 서비스 응답 없음. 원인은 5분 만에 찾았다. HTTPS 인증서가 만료되었다. 하루 전 메일로 갱신 알림이 왔었지만 담당자가 휴가 중이었고, 아무도 처리하지 않았다. 결국 1시간간 서비스가 완전히 다운되었다. 그때부터 나는 "절대 자동화한다"고 다짐했다.
지난 2년, Let's Encrypt와 certbot으로 구축한 자동화 시스템을 설명한다. Ubuntu 기준이지만 대부분의 Linux 배포판에서 동일하다.
Certbot 설치 — 5분이면 끝
먼저 설치: sudo apt-get update && sudo apt-get install certbot python3-certbot-nginx. 설치 후 인증서 발급: sudo certbot --nginx -d example.com -d www.example.com. 이 한 명령이 여러 작업을 자동으로 처리한다. Let's Encrypt에서 인증서를 발급받고, Nginx 설정을 자동 수정하며, HTTP를 HTTPS로 리다이렉트하고, 인증서를 /etc/letsencrypt/live/example.com/에 저장한다. Nginx 설정은 자동으로 SSL 설정과 리다이렉트를 추가한다.
자동 갱신 설정
인증서는 90일 유효하다. 자동 갱신은 필수다. 먼저 sudo certbot renew --dry-run으로 테스트한다. Systemd timer를 사용해서 매일 정해진 시간에 갱신을 시도하도록 설정한다. /etc/systemd/system/certbot.timer에서 OnCalendar=0 0,12 * * *로 매일 0시와 12시에 실행되도록 한다. 부팅 후 1시간 뒤에도 실행하고, 서버 부하 분산을 위해 최대 1시간 지연을 설정한다. 활성화: sudo systemctl enable certbot.timer && sudo systemctl start certbot.timer.
와일드카드 인증서 — DNS 챌린지
와일드카드(*.example.com)는 HTTP 검증으로 불가능하다. DNS 챌린지를 사용해야 한다. 명령: sudo certbot certonly --manual --preferred-challenges dns -d example.com -d *.example.com. DNS 레코드를 수동으로 추가해야 하는데, Route53 같은 서비스를 사용하면 자동화할 수 있다: sudo apt-get install python3-certbot-dns-route53 후 sudo certbot certonly --dns-route53 -d example.com -d *.example.com.
모니터링 — 실패를 알아야 한다
갱신이 실패해도 모르면 안 된다. Bash 스크립트로 인증서 만료 날짜를 확인하고, 7일 이내면 Slack으로 경고를 보낸다. 명령: openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem으로 만료일을 확인할 수 있다. 이 스크립트를 cron에 등록해서 매일 아침 9시에 실행하면, 문제가 생기면 즉시 알 수 있다.
트러블슈팅
"Too many requests" 에러가 나면 --staging 플래그로 테스트한다. DNS 챌린지가 작동 안 하면 dig _acme-challenge.example.com TXT로 DNS 레코드가 정말 추가되었는지 확인한다. Nginx 재로드 실패는 renewer_post_hooks에 systemctl reload nginx를 설정해서 해결한다.
결론
이제는 인증서 갱신을 자동으로 체크하고, 실패하면 Slack으로 알리며, 갱신 성공하면 Nginx가 자동으로 재로드된다. 인증서가 만료될 수 없다. Let's Encrypt는 무료고 자동화도 어렵지 않다. 2024년에 인증서 만료로 다운되는 건 순전히 게으름이다.