SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-07

Certbot 와일드카드 인증서 발급 및 DNS-01 설정 방법

Certbot을 사용하여 DNS-01 챌린지로 와일드카드 인증서를 발급받는 방법을 설명합니다. TXT 레코드 검증 원리부터 DNS 플러그인을 통한 자동 갱신 설정까지, 수동 방식의 한계를 극복하고 API를 활용하여 인증서를 관리하는 실무 가이드를 제공합니다.

와일드카드 인증서에 DNS-01이 필요한 이유

와일드카드 인증서는 도메인의 모든 1단계 서브도메인을 포괄합니다. *.example.comapp.example.com, blog.example.com 및 한 레이블 깊이의 다른 모든 이름을 포함합니다. Let's Encrypt는 DNS-01 챌린지를 통해서만 와일드카드 인증서를 발급하므로, Certbot은 _acme-challenge.example.com에 TXT 레코드를 게시하여 도메인의 DNS 제어권을 증명해야 합니다. HTTP-01 챌린지는 검증 서버가 파일을 가져온 특정 호스트네임에 대한 제어권만 증명할 수 있으므로 와일드카드 인증서에는 적합하지 않습니다. 와일드카드는 도메인 하위의 모든 가능한 이름에 대한 권한을 주장하는 것이며, 전체 네임스페이스를 대변할 수 있는 유일한 공개 기록은 DNS뿐이기 때문입니다.

이 하나의 요구 사항이 이 페이지의 모든 내용을 결정합니다. DNS-01을 통과하려면 수동으로 또는 DNS 제공업체의 API(application programming interface)를 통해 도메인 영역에 TXT 레코드를 생성할 수 있어야 합니다. 수동 방식은 한 번은 작동하지만 아래에 설명된 구체적인 이유로 인해 갱신 시 실패하게 됩니다. Certbot DNS 플러그인을 사용하는 API 방식은 자동으로 갱신되므로, 최종적으로 이 방식을 구축해야 합니다.

이 장은 Certbot 가이드의 와일드카드 관련 내용입니다. 일반적인 단일 호스트네임 인증서, 웹 서버 설정 및 포트 80 규칙은 Ubuntu 24.04에서 Nginx와 Certbot 사용하기Ubuntu 24.04에서 Apache와 Certbot 사용하기에서 다룹니다.

_acme-challenge TXT 레코드의 작동 원리

Certbot이 *.example.com를 요청하면, Let's Encrypt는 임의의 토큰을 반환합니다. Certbot은 이 토큰을 사용자의 ACME(automatic certificate management environment) 계정 키와 결합하고 SHA-256으로 해싱하여 짧은 텍스트 값을 생성합니다. 이 값은 반드시 _acme-challenge.example.com에 TXT 레코드로 등록되어야 합니다. 이후 Let's Encrypt는 자사 인프라에서 사용자의 도메인 권한 네임 서버를 조회합니다. 읽어 들인 레코드가 예상한 값과 일치하면 사용자가 해당 존(zone)을 제어하고 있음을 증명하게 되며, 존에 대한 제어권은 그 하위의 모든 이름에 대한 제어권으로 인정됩니다.

다음 두 가지 세부 사항이 대부분의 실패 원인이 됩니다.

  • 동일한 인증서에 example.com*.example.com을 함께 요청하면 두 개의 개별 챌린지가 발생하며, 두 TXT 레코드 모두 동일한 이름인 _acme-challenge.example.com에 위치해야 합니다. 따라서 두 레코드가 동시에 존재해야 합니다. 두 번째 레코드를 추가하는 것은 올바른 방법이지만, 첫 번째 레코드를 두 번째 레코드로 교체하면 첫 번째 챌린지가 실패합니다.
  • 검증 과정은 권한 네임 서버를 직접 읽지만, DNS 제공업체의 제어판에서 새로운 레코드를 전파하는 데 1분 이상의 시간이 소요될 수 있습니다. 검증을 실행하기 전에 외부에서 먼저 확인하십시오.
dig +short TXT _acme-challenge.example.com @1.1.1.1

위 명령이 Certbot이 요청한 값을 출력하면 검증이 성공할 수 있습니다. 아무것도 출력되지 않는다면 잠시 기다린 후 다시 실행하십시오.

수동 모드로 작동 확인하기

수동 모드에서는 사용자가 직접 DNS 레코드를 수정해야 합니다. 자동화하기 전에 메커니즘을 이해하는 가장 좋은 방법입니다.

sudo certbot certonly --manual --preferred-challenges dns -d example.com -d '*.example.com'

와일드카드 주위에 따옴표를 사용하는 이유는 셸이 *를 파일 이름 패턴으로 처리하지 않도록 하기 위함입니다. Certbot은 지침을 표시하고 일시 중지합니다.

Please deploy a DNS TXT record under the name:
_acme-challenge.example.com.
with the following value:
Jx9mQ2wLr8vTn5cKp0aYdG3hB7fZs4eN1oiRuXqMk6E

DNS 제공업체의 관리 패널에서 해당 TXT 레코드를 생성하고, 위 dig 명령어로 레코드가 확인되는지 먼저 검증한 뒤 Enter를 누르십시오. 이번 실행은 베어 도메인과 와일드카드를 모두 요청하므로 Certbot이 두 번 안내합니다. 발급이 완료될 때까지 두 레코드 모두 유지하십시오. 성공하면 다음과 같은 익숙한 메시지가 출력됩니다.

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem

수동 모드에서 자동 갱신이 불가능한 이유

모든 갱신은 새로운 토큰을 사용하는 새로운 챌린지이므로, TXT 값은 매번 변경됩니다. 오늘 붙여넣은 레코드는 60일 뒤에는 사용할 수 없습니다. 갱신 타이머는 하루에 두 번 Certbot을 자동으로 실행하지만, 사용자가 직접 새로운 값을 입력할 수는 없습니다. 따라서 수동으로 발급받은 인증서는 갱신 시점에 정확히 이 오류와 함께 실패하게 됩니다.

Failed to renew certificate example.com with error: The manual plugin is not
working; there may be problems with your existing configuration.
The error was: PluginError('An authentication script must be provided with
--manual-auth-hook when using the manual plugin non-interactively.')

DNS 제공업체의 API를 호출하는 --manual-auth-hook 스크립트를 작성하면 이 요구 사항을 충족할 수 있지만, 이는 사실상 DNS 플러그인을 직접 다시 만드는 것과 다름없습니다. 수동 모드는 흐름을 학습하거나, 아직 DNS 자동화를 지원하지 않는 도메인에서 일회성으로 발급받을 때만 사용하십시오. Let's Encrypt는 더 이상 만료 알림 이메일을 보내지 않으므로, 90일이 되기 전에 미리 알림을 설정해야 합니다. 그 외의 모든 경우에는 플러그인을 사용하십시오.

플러그인 방식: Ubuntu 24.04에서 certbot-dns-cloudflare 사용하기

DNS 플러그인은 DNS 제공업체의 API 자격 증명을 보관하며, 인증서 발급 및 매 갱신 시마다 TXT 레코드 생성 과정을 자동으로 수행합니다. 여기서는 가장 많은 사용자가 필요로 하는 Cloudflare를 예시로 들며, 해당 플러그인은 Ubuntu 패키지로 제공됩니다.

Certbot 가이드에서는 Ubuntu 24.04에서 apt 패키지 사용을 권장하며, Cloudflare의 경우에도 이 방침은 동일합니다.

sudo apt update
sudo apt install certbot python3-certbot-dns-cloudflare

버전과 관련하여 한 가지 참고할 점이 있습니다. 24.04 저장소는 Certbot 2.9.0과 함께 이 플러그인 2.0.0 버전을 제공합니다. apt policy python3-certbot-dns-cloudflare 명령으로 버전을 확인할 수 있습니다. 이 버전 차이는 문제가 되지 않으며, 범위가 제한된(scoped) API 토큰도 정상적으로 작동합니다. 이는 24.04의 기반이 되는 python3-cloudflare 라이브러리 버전이 2.11.1로, 토큰 지원에 필요한 2.3.1보다 높기 때문입니다. 이전 Ubuntu 릴리스에서는 해당 라이브러리 버전이 낮아 토큰을 사용할 수 없었으며, 온라인에서 apt 플러그인이 Global API Key 사용을 강제한다는 경고는 바로 이 때문에 발생한 것입니다. 24.04에서는 더 이상 해당하지 않는 내용입니다.

Cloudflare 대시보드에서 Global API Key가 아닌 범위가 제한된 API 토큰을 생성하십시오. [My Profile] -> [API Tokens] -> [Create Token] 순으로 이동한 뒤, 권한을 [Zone / DNS / Edit] 하나로 설정하고 인증서를 발급받을 특정 영역(zone)으로 제한하십시오. 이 토큰을 root 사용자만 읽을 수 있는 파일에 저장하십시오.

sudo mkdir -p /root/.secrets
sudo tee /root/.secrets/cloudflare.ini > /dev/null <<'EOF'
dns_cloudflare_api_token = paste_your_scoped_token_here
EOF
sudo chmod 600 /root/.secrets/cloudflare.ini

Certbot은 파일 모드를 확인하며, 다른 사용자가 읽을 수 있는 경우 Unsafe permissions on credentials configuration file에 대해 경고를 표시합니다. 이제 다음 명령으로 발급을 진행하십시오.

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

플러그인은 API를 통해 TXT 레코드를 생성하고, 짧은 전파 지연 시간을 기다린 뒤 검증을 수행하고, 마지막으로 레코드를 삭제합니다. 사용 중인 영역의 네임 서버가 변경 사항을 반영하는 데 시간이 걸린다면 --dns-cloudflare-propagation-seconds 60 옵션으로 대기 시간을 늘리십시오. 인증서는 /etc/letsencrypt/live/example.com/에 저장됩니다. 기본 가이드에 설명된 대로 deploy hook을 포함하여 nginx나 Apache에서 fullchain.pemprivkey.pem 경로를 지정하십시오.

제공업체의 플러그인이 apt에 없는 경우

24.04 아카이브는 Cloudflare, Route 53, DigitalOcean 및 범용 RFC 2136 인터페이스를 포함한 소수의 제공업체용 플러그인만 패키지로 제공합니다. 사용 가능한 목록을 보려면 apt search certbot-dns를 실행하십시오. 사용 중인 제공업체가 목록에 없다면, apt 우선 원칙에서 벗어나야 하는 유일한 상황입니다. 이 경우 apt 버전의 Certbot을 먼저 삭제하여 두 갱신 타이머가 /etc/letsencrypt을 두고 충돌하지 않도록 한 뒤, snap을 통해 Certbot과 해당 플러그인을 설치하십시오.

sudo apt remove certbot python3-certbot-dns-cloudflare
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-yourprovider

snap 플러그인은 snap 버전의 Certbot에만 연결되며 apt 버전은 확장할 수 없습니다. 이것이 두 설치 방식을 함께 사용해서는 안 되는 이유입니다. 만약 DNS 호스트가 API를 전혀 제공하지 않는다면, 현실적인 대안은 API를 지원하는 제공업체로 도메인의 DNS를 이전하거나, 직접 네임 서버를 운영하고 rfc2136 플러그인을 해당 서버로 연결하는 것입니다.

갱신: 60일 뒤가 아닌 지금 즉시 증명하기

Certbot은 각 인증서가 어떻게 발급되었는지 /etc/letsencrypt/renewal/example.com.conf에 기록하며, 여기에는 authenticator = dns-cloudflare 및 자격 증명 경로가 포함됩니다. 따라서 표준적인 일일 2회 타이머가 사용자의 개입 없이 인증서를 갱신합니다. 스테이징 환경을 대상으로 전체 과정을 미리 연습해 보십시오:

sudo certbot renew --dry-run

테스트를 통과했다면 자격 증명이 정상 작동하며 검증이 처음부터 끝까지 완료된 것입니다. 60일 뒤에 수행될 실제 갱신도 동일한 경로를 따릅니다. 오늘 두 가지 후속 조치를 수행하는 것이 좋습니다. 첫째, 디스크에 갱신된 인증서가 저장되어도 웹 서버가 이를 다시 불러오기 전까지는 아무런 변화가 없습니다. 따라서 nginx 및 Apache 가이드에 설명된 배포 훅(deploy hook)을 연결하십시오. 둘째, 자격 증명 파일을 신중하게 다루어야 합니다. 해당 파일을 읽을 수 있는 사람은 누구나 DNS 영역을 수정할 수 있으며, 이는 메일을 리다이렉트하거나 직접 DNS-01 챌린지를 통과하기에 충분한 권한입니다. 파일을 /root 하위에서 모드 600으로 유지하고, 토큰의 범위를 하나의 영역으로 제한하며, 유출이 의심되는 경우 즉시 교체하십시오.

와일드카드 인증서가 필요하지 않은 경우

와일드카드는 많은 수의 서브도메인이나 예측할 수 없는 서브도메인을 다룰 때 적합한 도구입니다. 하지만 그 외의 모든 상황에서 기본값으로 사용하는 것은 옳지 않습니다.

  • 서브도메인이 하나이거나 소수라면 일반적인 SAN(Subject Alternative Name) 인증서가 더 간단합니다. certbot --nginx -d example.com -d www.example.com -d app.example.com는 일반적인 HTTP-01 방식을 통해 최대 100개의 도메인 이름을 포함할 수 있으며, 서버에 DNS API 자격 증명을 저장할 필요가 없습니다.
  • 와일드카드는 정확히 하나의 레이블만 일치시킵니다. *.example.com은 기본 도메인인 example.com을 포함하지 않으므로 앞선 명령어들에서 두 가지를 모두 요청한 것입니다. 또한 a.b.example.com도 포함하지 않으며, 이를 위해서는 *.b.example.com가 필요합니다.
  • 모든 서브도메인이 하나의 개인 키를 공유합니다. 해당 키를 보관하는 서버가 침해되면 와일드카드가 적용된 모든 도메인이 즉시 위험에 노출됩니다.
  • Traefik이 컨테이너의 TLS(Transport Layer Security)를 종료하는 환경이라면 Certbot을 사용할 필요가 전혀 없습니다. Traefik은 DNS-01을 통해 직접 와일드카드 인증서를 요청하며, 이때 동일한 종류의 공급자 토큰을 사용합니다.

와일드카드가 진정으로 유용한 경우는 인증서를 재발급하는 속도보다 빠르게 고객별 또는 애플리케이션별 서브도메인을 생성해야 할 때입니다. 또한, WireGuard VPN을 통해서만 접근 가능한 서비스처럼 외부로 80번 포트가 열려 있지 않은 내부 호스트를 운영할 때도 유용합니다. DNS-01 방식은 인증 대상 호스트에 직접 연결하지 않으므로, 완전히 폐쇄된 내부망의 서버라도 공인된 인증서를 발급받을 수 있습니다.

FAQ

Certbot은 HTTP-01 방식으로 와일드카드 인증서를 발급할 수 있습니까?

아니요. HTTP-01은 검증 서버가 특정 호스트명에서 토큰 파일을 직접 가져오는 방식이므로 단일 호스트명에 대한 제어권만 증명할 수 있습니다. 와일드카드 인증서는 도메인 하위의 모든 이름을 포함하므로 Let's Encrypt는 이를 위해 DNS-01 챌린지를 요구하며, --nginx, --apache, --webroot--standalone 인증 방식은 모두 HTTP 기반입니다. 유일한 방법은 _acme-challenge.example.com에 TXT 레코드를 수동으로 추가하거나 DNS 플러그인을 사용하는 것입니다.

와일드카드 인증서가 루트 도메인도 포함합니까?

아니요. 와일드카드는 정확히 하나의 레이블만 일치시키므로 *.example.comwww.example.com을 포함하지만, 루트 도메인인 example.com이나 a.b.example.com은 포함하지 않습니다. 두 이름을 모두 포함하려면 -d example.com -d '*.example.com'를 사용하여 하나의 인증서로 요청하십시오. 이 경우 두 개의 챌린지가 생성되며, 두 TXT 레코드 모두 동일한 _acme-challenge.example.com 이름에 위치하게 되므로 첫 번째 레코드를 삭제하지 말고 두 번째 레코드를 추가해야 합니다.

와일드카드 인증서가 자동으로 갱신되지 않는 이유는 무엇입니까?

--manual을 사용하여 발급되었기 때문입니다. 갱신할 때마다 새로운 TXT 값이 필요한데, 자동화된 타이머는 이를 입력할 방법이 없으므로 An authentication script must be provided with --manual-auth-hook when using the manual plugin non-interactively 오류와 함께 갱신이 중단됩니다. certbot-dns-cloudflare과 같은 DNS 플러그인을 사용하여 인증서를 재발급하거나, 제공업체의 API를 통해 레코드를 수정하는 --manual-auth-hook--manual-cleanup-hook 스크립트를 제공하십시오.

_acme-challenge TXT 레코드가 나타나기까지 얼마나 걸립니까?

DNS 제공업체에 따라 다르며, 수 초에서 수 분까지 소요될 수 있습니다. 검증 과정은 해당 존의 권한 있는 서버를 읽으므로, 수동으로 실행할 때는 dig +short TXT _acme-challenge.example.com @1.1.1.1을 사용하여 예상한 값이 나타날 때까지 기다린 후 진행하십시오. 플러그인을 사용하는 경우, 검증 과정에서 레코드를 찾을 수 없다는 오류가 발생하면 플러그인의 전파 대기 옵션(예: --dns-cloudflare-propagation-seconds 60)을 사용하여 대기 시간을 늘리십시오.

와일드카드 인증서는 일반 인증서보다 보안이 취약합니까?

암호화 수준은 동일합니다. 차이점은 운영 방식에 있습니다. 하나의 개인 키가 모든 하위 도메인을 보호하므로 키가 유출될 경우 피해 범위가 더 넓으며, 자동화에 필요한 DNS API 자격 증명 자체가 서버에 저장되는 민감한 비밀 정보입니다. 소수의 알려진 하위 도메인만 운영한다면 SAN 인증서가 이러한 우려를 모두 피할 수 있으므로, 이 가이드에서는 그런 경우 와일드카드 사용을 건너뛸 것을 권장합니다.