← 전체 글로 돌아가기

서버 운영

Certbot로 HTTPS 인증서를 발급할 때 자주 막히는 지점들

Nginx와 certbot을 쓰다 보면 비슷한 곳에서 반복해서 막힌다. 내가 겪은 실패 패턴과 각각의 확인 방법을 정리했다.

certbot을 처음 쓸 때는 명령 한 줄이면 끝날 것 같지만, 실제로는 DNS, Nginx 설정, 방화벽 중 하나라도 어긋나면 바로 실패한다. 비슷한 실수를 두세 번 반복하고 나서 확인 순서를 고정하게 됐다.

가장 흔한 실패: DNS가 아직 안 잡혔을 때

Let's Encrypt는 도메인 소유 확인을 위해 HTTP-01 챌린지를 쓴다. 이때 도메인이 실제 서버 IP를 가리키지 않으면 인증이 실패한다. 도메인을 새로 연결했거나 레코드를 바꿨다면 propagation이 완전히 끝난 뒤에 certbot을 돌려야 한다.

# 내 서버 IP와 도메인이 일치하는지 먼저 확인
dig +short example.com
curl -s https://api64.ipify.org

두 값이 다르면 아직 DNS가 덜 퍼진 것이다. 급하게 certbot을 재실행해봤자 rate limit만 소모된다.

Nginx가 80번 포트를 이미 쓰고 있을 때

HTTP-01 방식은 certbot이 80번 포트를 잠깐 점유하거나, 아니면 Nginx에 .well-known/acme-challenge 경로를 열어줘야 한다. --nginx 플러그인을 쓴다면 Nginx 설정을 자동으로 건드리는데, 기존 설정에 문법 오류가 있으면 실패한다.

sudo nginx -t

이 명령이 먼저 통과해야 certbot도 잘 된다. nginx -t가 실패하면 certbot을 돌리기 전에 설정을 고쳐야 한다.

방화벽에서 80/443이 열려 있는지

ufw나 iptables로 막혀 있으면 챌린지 요청 자체가 도달하지 못한다.

sudo ufw status
sudo ss -lntp | grep -E ':(80|443)'

포트가 열려 있고 Nginx가 리스닝 중인지 같이 확인한다.

인증서 발급 후 자동 갱신 확인

certbot은 /etc/cron.d/certbot 또는 systemd timer로 갱신을 걸어두는데, 실제로 돌아가는지 한 번은 확인해두는 게 좋다.

sudo certbot renew --dry-run

--dry-run은 실제 발급 없이 갱신 과정 전체를 시뮬레이션한다. 여기서 에러가 없으면 자동 갱신도 잘 된다.

발급 후 적용 확인

인증서가 발급됐어도 Nginx가 reload되지 않으면 브라우저는 여전히 옛날 인증서를 본다.

sudo nginx -t && sudo systemctl reload nginx
curl -I https://example.com 2>&1 | grep -E 'HTTP|expire'

브라우저 주소창의 자물쇠보다 curl -I로 응답 코드와 헤더를 직접 보는 쪽이 더 정확하다. OS 인증서 캐시 때문에 브라우저가 틀린 정보를 보여줄 때가 있다.