Ubuntu 24.04 Certbot 설치 및 Nginx 인증서 적용 방법
Ubuntu 24.04에서 apt 또는 snap을 사용하여 Certbot을 설치하고 Nginx 인증서를 발급받는 방법을 설명합니다. apt와 snap 설치 시 주의사항, HTTP-01 챌린지 실패 원인인 포트 80 개방 문제 및 갱신 타임아웃 해결법을 상세히 안내합니다.
Certbot 설치: apt 또는 snap
Ubuntu 24.04 환경에서 sudo apt install certbot python3-certbot-nginx을 사용하면 실제 공개적으로 신뢰받는 Let's Encrypt 인증서를 발급할 수 있는 Certbot이 설치됩니다. Certbot 공식 문서에서는 snap 사용을 권장합니다. 두 방식의 차이는 미미합니다. snap은 업스트림 릴리스를 추적하고, 아카이브 패키지는 LTS 버전에 포함된 버전을 유지하며 보안 패치만 적용받습니다.
둘 중 하나만 선택하십시오. Certbot을 두 번 설치하면 동일한 /etc/letsencrypt 트리를 대상으로 갱신 타이머가 두 개 작동하게 되며, 잊고 있던 타이머가 문제를 일으킬 수 있습니다.
apt 설치 경로:
sudo apt update
sudo apt install certbot python3-certbot-nginx이 명령은 /usr/bin/certbot, nginx 플러그인, certbot.service + certbot.timer 쌍, 그리고 systemd 환경에서 아무 동작도 하지 않는 /etc/cron.d/certbot 항목을 설치합니다.
snap 설치 경로:
sudo apt remove certbot python3-certbot-nginx
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotsnap은 자체 타이머인 snap.certbot.renew.timer을 포함합니다. snap을 설치하기 전에 apt 패키지를 삭제하십시오.
두 설치 방식 모두 갱신 시점(아래 갱신 섹션 참조)을 제외하면 이후 동작은 동일합니다. Certbot 2.x는 기본적으로 ECDSA (P-256) 키를 사용합니다. ECDSA를 지원하지 않는 클라이언트를 위해서만 --key-type rsa 플래그를 전달하십시오. 모든 상태 정보는 /etc/letsencrypt 아래에 저장됩니다. archive/에는 실제 키와 인증서 파일이 저장되고, live/은 현재 사용 중인 파일로 심볼릭 링크됩니다. renewal/에는 인증서별 설정 파일이, accounts/에는 ACME 계정 키가 저장됩니다.
HTTP-01의 실제 동작 방식과 포트 80이 필수적인 이유
HTTP-01 챌린지는 콜백 방식입니다. 사용자가 Let's Encrypt에 example.com에 대한 인증서를 요청하면, Let's Encrypt는 공개 DNS에서 해당 도메인 이름을 확인하고, 발견된 주소의 포트 80으로 연결을 시도하여 http://example.com/.well-known/acme-challenge/<token>을 요청합니다. 이때 서버는 Certbot이 디스크에 기록한 토큰 내용을 그대로 응답해야 합니다. 이것이 전체 메커니즘의 전부입니다. 이 과정에서 발생하는 세 가지 결과가 대부분의 인증 실패 원인이 됩니다.
- 포트 80은 공용 인터넷에서 접근 가능해야 합니다. 단순히 사용자의 노트북에서 접근 가능한 것만으로는 부족합니다.
ufw규칙, 클라우드 제공업체의 보안 그룹, 또는 443 포트만 개방된 VPS 콘솔 방화벽은 인증서 발급은 물론 향후 모든 갱신 과정을 차단합니다. - DNS는 이미 해당 서버를 가리키고 있어야 합니다. 검증 서버는 외부에서 독자적으로 조회를 수행합니다. 사용자의
/etc/hosts항목이나 브라우저 캐시는 검증 서버에 아무런 영향을 주지 못합니다. - AAAA 레코드를 게시하면 IPv6가 우선 시도됩니다. Let's Encrypt는 IPv6 연결이 시간 초과될 때만 IPv4로 재시도합니다. 거부된 IPv6 연결은 재시도하지 않으며, 연결은 허용하지만 다른 내용을 응답하는 잘못된 AAAA 레코드는 즉각적인 실패를 유발합니다.
리다이렉트는 허용됩니다. 검증 과정은 HTTP 리다이렉트를 따라 HTTPS로 이동하며, 이때 목적지의 인증서가 없거나 만료되었거나 자체 서명된 것인지는 신경 쓰지 않습니다. 하지만 검증 서버는 반드시 포트 80에서 시작해야 합니다. Certbot은 TLS-ALPN-01 구현을 포함하고 있지 않으므로, "그냥 443 포트를 사용하면 되지 않느냐"는 해결책이 될 수 없습니다.
인증 방식 선택: --nginx, --webroot, --standalone
--nginx은 Nginx가 이미 실행 중이고 해당 도메인을 서비스하고 있을 때 사용하는 기본 권장 방식입니다. Certbot이 설정을 분석하여 임시 챌린지 경로를 삽입하고 Nginx를 리로드한 뒤, 검증을 마치고 TLS 지시어를 서버 블록에 작성합니다. 서비스 중단은 발생하지 않습니다.
sudo certbot --nginx -d example.com -d www.example.com초기 설정 단계에서 스크립트로 실행할 경우:
sudo certbot --nginx \
-d example.com -d www.example.com \
--agree-tos -m ops@example.com --no-eff-email \
--redirect --non-interactive--webroot는 Certbot이 Nginx 설정을 직접 수정하지 않기를 원할 때 적합합니다. 템플릿으로 설정을 생성하거나, git으로 관리하거나, Ansible로 배포하는 환경에 적합합니다. Certbot은 챌린지 파일만 이미 서비스 중인 디렉터리에 생성합니다.
sudo certbot certonly --webroot -w /var/www/example.com \
-d example.com -d www.example.com \
--deploy-hook "systemctl reload nginx"--standalone은 80번 포트를 사용하는 서비스가 없을 때 적합합니다. 메일 서버, 443번 포트만 사용하는 API, Nginx 설치 전 실행되는 초기화 스크립트 등이 이에 해당합니다. Certbot이 잠시 동안 직접 80번 포트를 점유합니다. 만약 Nginx가 실행 중이라면 이 방식은 실패하므로, 실행 전후로 Nginx를 중단해야 합니다.
sudo certbot certonly --standalone -d mail.example.com \
--pre-hook "systemctl stop nginx" \
--post-hook "systemctl start nginx"이러한 훅(hook)은 인증서 갱신 설정에 기록되므로, 갱신 시에도 동일한 중단/시작 과정이 자동으로 수행됩니다.
인증서 존재 여부와 관계없이 작동하는 서버 블록
닭과 달걀의 문제: nginx는 존재하지 않는 파일을 가리키는 ssl_certificate 설정이 있으면 시작을 거부하고, Certbot은 nginx가 내려가 있으면 검증을 수행할 수 없습니다. 먼저 80번 포트로 사이트를 띄우십시오.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location ^~ /.well-known/acme-challenge/ {
root /var/www/example.com;
default_type "text/plain";
try_files $uri =404;
}
location / {
try_files $uri $uri/ =404;
}
}sudo nginx -t && sudo systemctl reload nginx를 실행하고 외부에서 curl -I http://example.com/ 응답이 오는지 확인한 뒤 인증서를 발급받으십시오. 그 후:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/example.com;
default_type "text/plain";
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}더 긴 ACME 접두사가 이미 location /보다 우선하므로, return 301은 챌린지 요청을 볼 일이 없습니다. ^~ 수정자는 다른 곳에서 제 역할을 합니다. 해당 접두사가 일치하면 nginx는 정규 표현식 위치를 완전히 건너뛰므로, 나중에 추가된 location ~ /\. { deny all; } 같은 규칙이 챌린지를 차단할 수 없습니다. 이 위치를 80번 포트에 유지하면 사이트의 나머지 부분이 HTTPS 전용으로 전환된 후에도 갱신이 계속 작동합니다.
위의 두 블록은 모두 디스크에서 파일을 제공합니다. 만약 nginx가 애플리케이션의 앞단에 있다면, location /은 proxy_pass 블록이 되며 리버스 프록시 서버 블록, 줄 단위 설명에서 해당 애플리케이션에 필요한 헤더를 다룹니다. 이때 ACME 위치와 TLS 지시어는 그대로 유지됩니다.
HTTP/2 구문은 nginx 버전에 따라 다릅니다. Ubuntu 24.04는 nginx 1.24를 제공하며, 이는 listen 443 ssl http2;과 같이 인라인으로 작성해야 합니다. 별도의 http2 on; 지시어를 사용하면 시작에 실패합니다. Debian 13은 nginx 1.26을 제공하며, 이는 http2 on;를 사용해야 하고 인라인 방식은 더 이상 사용되지 않는다는 경고만 표시합니다. 먼저 nginx -v을 확인하십시오.
nginx가 archive/이 아닌 live/을 가리키도록 설정하십시오. live/ 심볼릭 링크는 갱신될 때마다 대상이 변경됩니다. archive/ 내부의 하드 경로를 사용하면 만료된 인증서에 고정될 위험이 있습니다.
와일드카드 인증서에는 DNS-01이 필요하며, DNS-01에는 플러그인이 필요합니다
와일드카드 인증서(*.example.com)는 HTTP-01 방식으로 검증할 수 없습니다. 파일을 가져올 단일 호스트 이름이 존재하지 않기 때문입니다. 유일한 방법은 DNS-01입니다. 특정 _acme-challenge.example.com TXT 레코드를 게시하여 도메인 제어권을 증명해야 합니다. Certbot이 이를 자동으로 수행하려면 DNS 공급자의 API 자격 증명이 필요하며, 이를 위해 공급자 플러그인이 존재합니다. 와일드카드 인증서 전체 가이드에서 TXT 레코드의 작동 원리와 수동 모드에서의 갱신 주의 사항을 다루며, 아래에는 Cloudflare를 사용하는 간략한 버전을 설명합니다.
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflareapt 경로에서는 대신 sudo apt install python3-certbot-dns-cloudflare을 사용합니다. 자격 증명은 root 계정만 읽을 수 있는 파일에 저장하십시오.
# /root/.secrets/cloudflare.ini
# then: sudo chmod 600 /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_scoped_token_here토큰의 범위를 해당 영역에 대한 DNS 편집 권한으로 제한하십시오. 이는 DNS에 대한 암호화 키이므로, 그에 걸맞게 취급해야 합니다.
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'셸에서 와일드카드를 해석하지 못하도록 따옴표로 묶으십시오. DNS-01은 HTTP-01이 해결할 수 없는 문제도 해결합니다. 공개 포트 80이 없는 호스트, 내부 서비스, VPS 기반의 자체 호스팅 WireGuard VPN을 통해서만 접근 가능한 장비, 사설 인터페이스의 관리자 패널 등에 대한 인증서 발급이 가능합니다.
갱신: 90일 주기, 타이머, 배포 훅
Let's Encrypt 인증서의 유효 기간은 90일입니다. apt 패키지(Certbot 2.9.0)는 만료까지 30일 미만으로 남았을 때 갱신을 수행합니다. snap은 최신 Certbot 버전을 추적하며, 버전 4.1부터는 ACME Renewal Info(ARI)를 통해 Let's Encrypt가 제안하는 갱신 시점을 확인하여 더 일찍 갱신할 수 있습니다. Let's Encrypt 인증서의 경우 일반적으로 전체 수명의 3분의 2 지점이 이에 해당합니다. 어느 경우든 약 30일의 여유 기간이 주어지므로, 갱신 실패 시 서비스 중단 없이 문제를 해결할 수 있습니다. 내년부터는 갱신 주기가 더 짧아질 예정입니다. Let's Encrypt의 기본 프로필은 2027년 2월 10일부터 64일 인증서로, 2028년 2월 16일부터는 45일 인증서로 변경됩니다. Let's Encrypt는 더 이상 만료 알림 이메일을 발송하지 않으며 아무도 대신 챙겨주지 않으므로, 이제 모니터링은 전적으로 사용자의 책임입니다.
설치 시 생성된 타이머를 확인하십시오:
systemctl list-timers 'certbot*' 'snap.certbot*'
sudo certbot certificatescertbot renew은 /etc/letsencrypt/renewal/에 있는 모든 설정을 순회하며, 아직 갱신 시기가 되지 않은 항목은 건너뛰고 나머지 인증서를 저장된 옵션에 따라 갱신합니다. 이 옵션들은 certbot reconfigure으로 변경하지 않는 한 최초 실행 시 사용한 플래그를 그대로 따릅니다. 따라서 최초 실행 시 기록되는 설정이 중요한 이유입니다.
디스크의 파일을 갱신하는 것만으로는 아무런 변화가 없습니다. nginx는 재시작 명령을 받기 전까지 메모리에 로드된 이전 인증서를 계속 사용합니다. 배포 훅을 한 번 설정하십시오:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh >/dev/null <<'EOF'
#!/bin/sh
set -e
nginx -t && systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shrenewal-hooks/deploy/에 위치한 실행 가능한 모든 파일은 갱신 성공 후 자동으로 실행됩니다. --deploy-hook 플래그는 특정 인증서에 대해 동일한 작업을 수행하며, 해당 갱신 설정에 renew_hook = ...을 저장합니다. certbot --nginx은 자동으로 리로드를 수행하지만, --webroot 및 --standalone 설정은 그렇지 않습니다. 훅이 누락되면 certbot certificates은 인증서가 정상적으로 갱신되었다고 보고하지만, 실제 사이트에서는 만료된 인증서가 제공되는 상황이 발생합니다. 시작 시 인증서를 읽는 다른 모든 서비스도 동일한 훅이 필요합니다. Docker, TLS 및 백업을 사용하는 Nextcloud VPS 설치와 같이 컨테이너화된 애플리케이션 역시 이곳에 자체적인 재시작 또는 리로드 단계를 연결해야 합니다.
실제 갱신 테스트
sudo certbot renew --dry-run이 명령은 Let's Encrypt의 스테이징 환경을 대상으로 전체 챌린지를 수행합니다. 운영 환경과 동일한 코드 경로, 방화벽, DNS 설정을 사용하며, 운영 환경의 속도 제한(rate limit)에 영향을 주지 않습니다(스테이징 환경은 별도의 훨씬 관대한 제한을 적용합니다). 또한 인증서를 디스크에 저장하지 않습니다. 오늘 테스트를 통과하면, 서버 환경에 변화가 없다는 가정하에 60일 뒤의 자동 갱신도 정상적으로 수행됩니다.
드라이 런(dry run)은 reload 훅이 정상적으로 실행되는지까지는 보장하지 않으며, 이 동작은 Certbot 버전에 따라 다를 수 있습니다. 따라서 훅 부분은 수동으로 테스트해야 합니다. 훅 스크립트를 직접 실행하여 systemctl reload nginx이 성공하는지 확인하고, sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf를 통해 결과를 검증하십시오.
실제로 마주하게 될 오류들
Could not bind to IPv4 or IPv6., --standalone는 nginx가 이미 80번 포트를 점유하고 있을 때 발생합니다. --nginx 또는 --webroot을 사용하거나, 실행 중에 nginx를 중단하십시오. sudo ss -lntp | grep ':80' 명령으로 포트를 점유 중인 프로세스를 확인하십시오.
Timeout during connect (likely firewall problem), Let's Encrypt가 80번 포트에 접근할 수 없는 경우입니다. 외부에서 내부로 순차적으로 확인하십시오: sudo ufw status (sudo ufw allow 'Nginx Full'로 개방), 그다음 VPS 제공업체의 방화벽, 마지막으로 DNS를 확인하십시오. 서버 외부의 환경에서 curl -sSv http://example.com/.well-known/acme-challenge/test 명령으로 테스트하십시오. 오래된 AAAA 레코드가 남아 있어도 동일한 메시지가 발생할 수 있습니다.
unauthorized :: Invalid response from http://example.com/.well-known/acme-challenge/xyz: 404, 80번 포트는 접근 가능하지만 토큰이 제공되지 않는 경우입니다. 요청이 다른 서버 블록으로 전달되었거나(어떤 블록이 default_server을 소유하는지 확인), -w에 전달된 디렉터리가 nginx가 실제로 서비스하는 디렉터리가 아닐 수 있습니다. /var/www/example.com/.well-known/acme-challenge/test에 파일을 생성하고 외부에서 가져오기를 시도하십시오. 만약 404 오류가 발생한다면, 인증서 문제가 아닙니다.
DNS problem: NXDOMAIN looking up A for example.com, 도메인 이름이 공개적으로 해석되지 않는 경우입니다. 새로 생성된 레코드가 전파되지 않았거나, 도메인 등록 기관에서 서비스하지 않는 영역의 레코드일 수 있습니다.
too many certificates (5) already issued ..., 속도 제한(rate limit) 오류로, 디버깅을 반복할 때 자주 발생합니다. 메시지에 제한 항목이 명시되며 retry after 시간으로 종료됩니다. Let's Encrypt는 동일한 도메인 이름 세트에 대해 주당 5개까지만 인증서 발급을 허용하며, 이에 대한 예외 처리는 불가능하므로 시간이 지나야 해결됩니다. 별도로 등록된 도메인당 주당 50개의 신규 인증서를 허용합니다. 이 제한은 요청을 통해 상향 조정할 수 있으며, 기존 인증서와 정확히 동일한 이름 세트에 대한 요청은 갱신으로 간주되어 제한에서 제외됩니다. 또한 ARI를 통해 조정된 갱신은 모든 제한에서 제외됩니다. --dry-run를 사용하여 스테이징 환경에서 디버깅하십시오.
nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": No such file or directory, nginx가 발급되지 않았거나 certbot delete로 삭제된 인증서를 사용하도록 설정된 경우입니다. TLS 서버 블록을 주석 처리하고, nginx를 시작한 뒤, 인증서를 발급받고, 다시 블록을 복구하십시오.
open() "/etc/letsencrypt/options-ssl-nginx.conf" failed, 해당 파일은 nginx 플러그인 패키지와 함께 제공됩니다. python3-certbot-nginx가 없는 certonly 환경이라면, 플러그인을 추가하거나 include 라인을 직접 작성한 ssl_protocols 및 ssl_ciphers 설정으로 교체하십시오.
대규모 환경에서의 관리
하나의 인증서에 최대 100개의 도메인을 포함할 수 있으며, 하나의 certbot --nginx -d a.example.com -d b.example.com ...을 사용하는 것이 매력적으로 보일 수 있습니다. 하지만 오래된 DNS 레코드 하나가 검증에 실패하면 해당 인증서에 포함된 모든 도메인의 서비스가 중단될 수 있습니다. 사이트별로 인증서를 분리하면 각 서비스가 독립적으로 동작하므로, 여러 서비스를 운영하는 서버에서는 이 방식이 권장됩니다. 사이트 개수가 늘어나면 ACME를 지원하는 프록시를 도입하는 것이 효율적입니다. Docker Compose로 여러 애플리케이션을 운영하는 Traefik 리버스 프록시는 인증서 발급과 갱신을 자동으로 처리하므로 Certbot을 직접 사용할 필요가 없습니다. 어떤 프록시를 선택할지는 운영자의 결정에 달려 있으며, Nginx, Caddy, Traefik 비교는 프록시가 인증서 관리와 애플리케이션별 설정을 얼마나 대신 처리해 줄지에 따라 결정됩니다.
/etc/letsencrypt 전체를 심볼릭 링크가 유지되도록 sudo tar -czf letsencrypt-$(date +%F).tar.gz -C /etc letsencrypt으로 백업하십시오. 이 디렉터리 트리에는 동일하게 재생성할 수 없는 ACME 계정 키인 accounts/이 포함되어 있습니다. 새로운 VPS로 이전하는 과정은 간단합니다. -a를 사용하여 디렉터리 트리를 rsync로 복사하고, Certbot을 설치한 뒤, DNS를 변경하고, 전환하기 전에 certbot renew --dry-run을 실행하면 됩니다.
서버를 재구축하거나 새로운 LTS 버전으로 이전하면 갱신 타이머는 자동으로 따라오지 않습니다. 마이그레이션, 스냅샷 복원, 배포판 업그레이드 후에는 반드시 systemctl list-timers 'certbot*'를 실행하고 --dry-run를 한 번 수행해야 합니다. 이를 건너뛰면 89일 후 새벽 3시에 인증서가 만료되어 사이트가 중단되는 상황이 발생할 수 있습니다.
위에서 설명한 HTTP-01 방식은 공인 IP를 보유하고 포트 80이 외부로 열려 있는 VPS와 같은 제어 가능한 환경을 가정합니다. 반면 DNS-01 방식은 이러한 조건이 필요하지 않습니다. 기본적인 작동 원리는 두 방식 모두 동일합니다.
동일한 인증서 발급 절차를 Nginx 대신 Apache에 적용할 수 있으며, 공인 인증서를 사용할 수 없는 내부 서비스의 경우 Ubuntu에서 자체 서명 인증서를 생성하여 사용할 수 있습니다.
FAQ
HTTPS만 서비스하는 경우에도 80번 포트를 열어야 합니까?
네, HTTP-01 챌린지를 위해 필요합니다. Let's Encrypt는 항상 80번 포트에서 검증 요청을 시작합니다. Certbot은 TLS-ALPN-01 구현을 제공하지 않으므로, 443번 포트만 개방된 방화벽은 최초 발급과 이후의 모든 자동 갱신을 차단합니다. 80번 포트에서 HTTPS로 리다이렉트하는 것은 괜찮으며, 검증 과정은 이를 따라갑니다. 80번 포트를 완전히 생략하는 유일한 방법은 DNS-01을 사용하는 것입니다. 제공자 플러그인을 사용하거나 Certbot의 --manual --preferred-challenges dns을 통해 직접 TXT 레코드를 추가할 수 있으나, --manual-auth-hook 스크립트를 제공하지 않으면 갱신이 자동화되지 않습니다.
Ubuntu 24.04의 nginx 환경에서 Certbot을 apt와 snap 중 무엇으로 설치해야 합니까?
apt를 사용하십시오. sudo apt install certbot python3-certbot-nginx은 Ubuntu 24.04에서 Certbot 2.9.0 버전을 제공합니다. 이 버전은 본 가이드의 모든 내용을 수행하기에 충분하며, unattended-upgrades를 통해 보안 패치를 받을 수 있고 snapd를 요구하지 않습니다. 최신 릴리스가 즉시 필요하거나 snap으로만 배포되는 DNS 플러그인이 필요한 경우에만 snap을 선택하십시오. 어떤 방식을 선택하든 하나만 사용해야 합니다. 두 가지를 모두 설치하면 동일한 /etc/letsencrypt 트리를 가리키는 두 개의 갱신 타이머가 생성되며, 관리하지 않는 쪽에서 문제가 발생하게 됩니다.
Certbot으로 nginx용 와일드카드 인증서를 발급할 수 있습니까?
DNS-01을 통해서만 가능합니다. *.example.com과 같은 와일드카드는 챌린지 파일을 가져올 단일 호스트 이름이 없으므로 --nginx, --webroot, --standalone 방식은 모두 사용할 수 없습니다. DNS 제공자용 플러그인을 설치하고, root 계정만 읽을 수 있는 자격 증명 파일에 제한된 권한의 API 토큰을 넣은 뒤 certbot certonly --dns-cloudflare -d example.com -d '*.example.com'를 실행하십시오. 이때 셸이 와일드카드를 확장하지 않도록 따옴표로 묶어야 합니다.
갱신에 성공했는데도 nginx가 왜 여전히 이전 인증서를 제공합니까?
nginx는 인증서를 메모리에 유지하며, 디스크의 파일이 변경되어도 리로드하기 전까지는 이를 인식하지 못합니다. certbot --nginx은 자동으로 리로드하지만, --webroot이나 --standalone 실행 시에는 리로드되지 않습니다. 따라서 갱신은 성공했더라도 브라우저에서는 여전히 만료되어가는 인증서가 보일 수 있습니다. nginx -t && systemctl reload nginx을 실행하는 스크립트를 /etc/letsencrypt/renewal-hooks/deploy/에 배치하면, 갱신이 성공할 때마다 자동으로 실행됩니다.
certbot renew --dry-run은 갱신이 정상적으로 작동할 것임을 보장합니까?
대체로 그렇습니다. 이 명령은 실제 운영 환경의 속도 제한에 영향을 주지 않고 디스크에 인증서를 저장하지 않으면서, 실제와 동일한 방화벽, DNS, 코드 경로를 사용하여 스테이징 환경에서 검증을 수행합니다. 따라서 통과했다면 네트워크 설정은 정상입니다. 다만 배포 훅(deploy hook)이 정상적으로 작동하는지까지 확실하게 보장하지는 않습니다. 훅 스크립트를 직접 실행하고 sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf를 확인하여 별도로 테스트하십시오.