Management > Private CA > ACME 인증서 갱신 가이드(Certbot, acme.sh)
Private CA 서비스는 ACME(automatic certificate management environment) 프로토콜을 지원하여 인증서의 자동 발급 및 갱신을 가능하게 합니다. ACME 클라이언트(예: Certbot, acme.sh)를 사용하면 수동 개입 없이 인증서를 발급 받고 주기적으로 갱신할 수 있습니다.
본 가이드에서는 Private CA ACME 서버를 이용하여 Certbot 또는 acme.sh로 인증서를 발급하고 자동으로 갱신하는 방법을 안내합니다.
알아두기
ACME를 통한 인증서 발급을 시작하기 전에 다음 사항을 준비해야 합니다.
Base 인증서는 ACME 서버가 자동 갱신 시 참조하는 "템플릿" 역할을 합니다.
Private CA 콘솔에서 다음 정보를 확인합니다.
https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directoryACME 클라이언트로 Certbot 또는 acme.sh를 사용할 수 있습니다. 사용 환경에 맞는 도구를 선택하여 진행하세요.
알아두기
Kubernetes 환경에서 인증서를 자동으로 관리하려면 ACME 인증서 갱신 가이드(cert-manager)를 참고하세요.
Certbot은 가장 널리 사용되는 ACME 클라이언트입니다. Certbot 공식 문서를 참고하여 운영 체제에 맞게 설치합니다.
설치 예시(Ubuntu/Debian)
sudo apt update
sudo apt install certbot
설치 예시(CentOS/RHEL)
sudo yum install certbot
다음은 기본적인 인증서 발급 명령어 예시입니다.
certbot certonly \
--manual \
--manual-auth-hook ./pre.sh \
--deploy-hook ./post.sh \
--preferred-challenges http \
--server https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directory \
-d example.com -d www.example.com \
--eab-kid "YOUR_ACME_TOKEN_ID" \
--eab-hmac-key "YOUR_ACME_TOKEN_HMAC_KEY" \
--key-type rsa \
--rsa-key-size 2048 \
--agree-tos \
--register-unsafely-without-email
| 옵션 | 설명 | 필수 | 기본값 |
|---|---|---|---|
--manual |
Challenge 검증을 수동으로 수행합니다. Apache나 Nginx 자동 설정 대신 수동 모드를 사용합니다. | O | - |
--manual-auth-hook |
Challenge 검증 전에 실행할 스크립트를 지정합니다. 빈 스크립트라도 갱신 시 오류 방지를 위해 필요합니다. | O | - |
--deploy-hook |
인증서 발급 성공 후 실행할 스크립트를 지정합니다. 인증서 이동, 배포 등의 후처리에 사용합니다. | X | - |
--preferred-challenges |
Challenge 방식을 지정합니다(http, dns, tls-alpn). 일반적으로 http를 사용합니다. |
O | - |
--server |
ACME 서버의 Directory URL을 지정합니다. | O | - |
-d |
인증서에 포함할 도메인을 지정합니다. Base 인증서의 CN과 SAN을 콘솔에서 확인하여 정확히 입력해야 합니다. | O | - |
--eab-kid |
External Account Binding의 키 ID입니다. Private CA에서 발급한 ACME 토큰 ID를 입력합니다. | O | - |
--eab-hmac-key |
EAB HMAC 키(Base64 인코딩)입니다. Private CA에서 발급한 ACME 토큰 HMAC 키를 입력합니다. | O | - |
--key-type |
개인 키 유형(rsa, ecdsa)을 지정합니다. |
X | rsa |
--rsa-key-size |
RSA 키 길이를 지정합니다. --key-type rsa일 경우에만 사용하며, 2048, 3072, 4096 값을 사용할 수 있습니다. |
X | 2048 |
--elliptic-curve |
ECDSA 키 곡선을 지정합니다. --key-type ecdsa일 경우에만 사용하며, secp256r1, secp384r1, secp521r1 값을 사용할 수 있습니다. |
X | secp256r1 |
--agree-tos |
서비스 약관에 자동으로 동의합니다. 인터랙티브 입력을 방지합니다. | X | - |
--register-unsafely-without-email |
이메일 없이 계정을 등록합니다. 인터랙티브 입력을 방지합니다. | X | - |
알아두기
--manual 모드는 수동 Challenge 검증에 사용됩니다.manual-auth-hook은 인증서 갱신 시 안정성 확보를 위해 반드시 필요합니다.deploy-hook을 활용하면 인증서 발급 후 자동으로 배포 및 후처리 작업을 수행할 수 있습니다.--server, --eab-kid, --eab-hmac-key는 Private CA ACME 서버 연동에 필수입니다.주의
도메인 지정 시 Base 인증서에 설정된 CN(common name)과 도메인 SAN(subject alternative name)을 정확히 입력해야 합니다. 인증서 발급 전 콘솔에서 Base 인증서의 CN과 SAN 정보를 확인하여 -d 옵션에 올바른 도메인을 지정했는지 반드시 검증하세요.
manual-auth-hook은 내용이 비어 있어도 파일로 존재해야 합니다. 이는 인증서 갱신(renew) 시 오류를 방지하기 위함입니다.
#!/bin/bash
# 필요한 인증 전처리 작업을 여기에 추가할 수 있습니다.
deploy-hook은 인증서가 성공적으로 발급된 경우에만 실행됩니다.
#!/bin/bash
# 인증서 발급 완료 후 처리 작업
echo "[post.sh] 인증서 발급 완료!"
# 인증서를 원하는 위치로 복사
cp /etc/letsencrypt/live/example.com/fullchain.pem ~/Downloads/
cp /etc/letsencrypt/live/example.com/privkey.pem ~/Downloads/
# 웹 서버 재시작 등 추가 작업
# systemctl reload nginx
인증서는 기본적으로 다음 경로에 저장됩니다.
/etc/letsencrypt/live/<도메인명(CN)>/
├── cert.pem # 서버 인증서
├── chain.pem # 중간 인증서 체인
├── fullchain.pem # cert.pem + chain.pem
└── privkey.pem # 개인 키
# 인증서 정보 확인
openssl x509 -in /etc/letsencrypt/live/<도메인명(CN)>/cert.pem -text -noout
# 인증서 유효기간 확인
openssl x509 -in /etc/letsencrypt/live/<도메인명(CN)>/cert.pem -noout -dates
Certbot은 만료가 임박한 인증서를 자동으로 갱신할 수 있습니다.
/etc/letsencrypt/renewal/<도메인>.conf 파일이 존재해야 합니다./etc/letsencrypt/live/<도메인>/ 디렉터리에 인증서 파일들이 있어야 합니다.Certbot 설치 시 자동으로 cron 또는 systemd timer가 등록되어 주기적으로 인증서 만료 여부를 확인합니다.
기본 갱신 주기: 만료 30일 전부터 자동 갱신 시도
필요 시 다음 명령어로 수동 갱신을 수행할 수 있습니다.
# 모든 인증서 갱신 시도
sudo certbot renew
# 강제 갱신
sudo certbot renew --force-renewal
자동 갱신이 등록되지 않았다면 수동으로 cron 작업을 추가할 수 있습니다.
# crontab 편집
sudo crontab -e
# 매일 새벽 2시에 갱신 확인
0 2 * * * certbot renew --no-random-sleep-on-renew
/etc/letsencrypt/renewal/<도메인>.conf 파일에서 갱신 주기를 조정할 수 있습니다.
[renewalparams]
renew_before_expiry = 30 days
renew_before_expiry 값을 변경하여 인증서 만료 며칠 전부터 갱신을 시도할지 설정할 수 있습니다.
주의
renew_before_expiry 값은 ACME 서버의 Rate Limit 정책을 고려하여 신중히 조정해야 합니다./etc/cron.d/certbot 파일을 수정하는 것이 권장됩니다.perl -e 'sleep int(rand(43200))')이 포함되어 있습니다. 이는 ACME 서버 과부하 방지를 위한 것으로, 즉시 실행이 필요하면 해당 구문을 제거하거나 --no-random-sleep-on-renew 옵션을 사용해야 합니다.--server 옵션의 URL이 올바른지 확인합니다.--eab-kid와 --eab-hmac-key 값이 정확한지 확인합니다.pre.sh와 post.sh 파일에 실행 권한이 있는지 확인합니다./etc/letsencrypt/renewal/<도메인>.conf 파일이 존재하고 올바른지 확인합니다.manual-auth-hook으로 지정한 스크립트가 여전히 존재하는지 확인합니다.acme.sh는 순수 Unix Shell로 작성된 경량 ACME 클라이언트입니다. 의존성이 적고 설치가 간편하여 다양한 환경에서 사용할 수 있습니다.
acme.sh는 설치 스크립트를 통해 간단히 설치할 수 있습니다.
설치
curl https://get.acme.sh | sh
설치가 완료되면 환경 변수를 로드합니다.
. ~/.acme.sh/acme.sh.env
acme.sh --version
알아두기
. ~/.acme.sh/acme.sh.env 명령어로 환경 변수를 다시 로드해야 합니다.설치 예시(수동 다운로드)
git clone https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install
인증서를 발급하기 전에 먼저 ACME 서버에 계정을 등록해야 합니다.
acme.sh --register-account \
--server https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directory \
--eab-kid "YOUR_ACME_TOKEN_ID" \
--eab-hmac-key "YOUR_ACME_TOKEN_HMAC_KEY"
주의
--eab-kid와 --eab-hmac-key 옵션을 생략할 수 있습니다.계정 등록 후 인증서를 발급할 수 있습니다.
기본 발급 명령어 예시
acme.sh --issue \
-d example.com -d www.example.com \
--server https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directory \
--keylength 2048 \
--standalone
| 옵션 | 설명 | 필수 | 기본값 |
|---|---|---|---|
--register-account |
ACME 서버에 계정을 등록합니다. 최초 1회만 실행합니다. | O(최초) | - |
--issue |
인증서를 발급합니다. | O | - |
--server |
ACME 서버의 Directory URL을 지정합니다. | O | - |
--eab-kid |
External Account Binding의 키 ID입니다. Private CA에서 발급한 ACME 토큰 ID를 입력합니다. 계정 등록 시에만 필요합니다. | O(등록 시) | - |
--eab-hmac-key |
EAB HMAC 키(Base64 인코딩)입니다. Private CA에서 발급한 ACME 토큰 HMAC 키를 입력합니다. 계정 등록 시에만 필요합니다. | O(등록 시) | - |
-d |
인증서에 포함할 도메인을 지정합니다. Base 인증서의 CN과 SAN을 콘솔에서 확인하여 정확히 입력해야 합니다. 여러 개 지정 가능합니다. | O | - |
--standalone |
Standalone 모드로 HTTP-01 Challenge를 처리합니다. acme.sh가 임시 웹 서버를 실행합니다. | O | - |
--httpport |
HTTP-01 Challenge에 사용할 포트 번호를 지정합니다. | X | 80 |
--keylength |
개인 키 길이를 지정합니다. RSA는 2048, 3072, 4096, ECDSA는 ec-256, ec-384, ec-521 값을 사용할 수 있습니다. |
X | 2048 |
--debug |
디버그 모드로 실행하여 상세 로그를 출력합니다. | X | - |
알아두기
--standalone 모드는 acme.sh가 임시 웹 서버를 실행하여 Challenge를 처리합니다. 80번 포트를 사용할 수 있어야 합니다.--eab-kid와 --eab-hmac-key 옵션 없이 인증서를 발급할 수 있습니다.주의
도메인 지정 시 Base 인증서에 설정된 CN(common name)과 도메인 SAN(subject alternative name)을 정확히 입력해야 합니다. 인증서 발급 전 콘솔에서 Base 인증서의 CN과 SAN 정보를 확인하여 -d 옵션에 올바른 도메인을 지정했는지 반드시 검증하세요.
acme.sh가 임시 웹 서버를 실행하여 HTTP-01 Challenge를 처리합니다.
acme.sh --issue \
-d example.com \
--server https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directory \
--keylength 2048 \
--standalone
주의
--httpport 옵션을 추가합니다.인증서는 기본적으로 다음 경로에 저장됩니다.
~/.acme.sh/<도메인명(CN)>/
├── <도메인명>.cer # 서버 인증서(리프 인증서)
├── <도메인명>.key # 개인 키
├── ca.cer # CA 체인(Intermediate + Root)
└── fullchain.cer # 전체 체인(리프 인증서 + CA 체인)
알아두기
<도메인명>.cer: 리프 인증서만 포함fullchain.cer: 리프 인증서 + 중간 인증서 + 루트 인증서 전체 체인ca.cer: CA 체인(중간 인증서 + 루트 인증서)# 인증서 정보 확인
openssl x509 -in ~/.acme.sh/example.com/example.com.cer -text -noout
# 인증서 유효기간 확인
openssl x509 -in ~/.acme.sh/example.com/example.com.cer -noout -dates
acme.sh는 --install-cert 명령어로 인증서를 원하는 위치에 복사하고 웹 서버를 재시작할 수 있습니다.
Nginx 예시
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/privkey.pem \
--cert-file /etc/nginx/ssl/cert.pem \
--fullchain-file /etc/nginx/ssl/fullchain.pem \
--ca-file /etc/nginx/ssl/ca.pem \
--reloadcmd "nginx -s reload"
Apache 예시
acme.sh --install-cert -d example.com \
--key-file /etc/apache2/ssl/privkey.pem \
--cert-file /etc/apache2/ssl/cert.pem \
--fullchain-file /etc/apache2/ssl/fullchain.pem \
--ca-file /etc/apache2/ssl/ca.pem \
--reloadcmd "systemctl reload apache2"
알아두기
--key-file: 개인 키 파일 저장 경로--cert-file: 리프 인증서 저장 경로--fullchain-file: 전체 체인(리프 + CA 체인) 저장 경로--ca-file: CA 체인 저장 경로--reloadcmd: 인증서 설치 후 자동으로 실행할 명령어acme.sh는 설치 시 자동으로 cron 작업을 등록하여 인증서 만료를 확인하고 갱신합니다.
~/.acme.sh/<도메인>/ 디렉터리에 인증서 파일들이 있어야 합니다.acme.sh 설치 시 자동으로 cron 작업이 등록됩니다.
기본 갱신 주기: 만료 60일 전부터 자동 갱신 시도
Cron 작업 확인
crontab -l | grep acme.sh
일반적으로 다음과 같은 형태로 등록됩니다.
0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null
필요 시 다음 명령어로 수동 갱신을 수행할 수 있습니다.
# 모든 인증서 갱신 시도
acme.sh --cron
# 특정 인증서 강제 갱신
acme.sh --renew -d example.com --force
acme.sh는 기본적으로 만료 60일 전부터 갱신을 시도합니다. 이 값을 변경하려면 ~/.acme.sh/account.conf 파일을 수정합니다.
# account.conf 편집
vim ~/.acme.sh/account.conf
다음 라인을 추가하거나 수정합니다.
Le_RenewalDays=30
이렇게 설정하면 만료 30일 전부터 갱신을 시도합니다.
주의
Le_RenewalDays 값은 ACME 서버의 Rate Limit 정책을 고려하여 신중히 조정해야 합니다.--server 옵션의 URL이 올바른지 확인합니다.--register-account 명령어로 먼저 계정을 등록합니다.--debug 옵션을 추가하여 상세 로그를 확인합니다.acme.sh --issue \
-d example.com \
--server https://kr1-pca.api.nhncloudservice.com/acme/v2.0/cert/{certId}/directory \
--keylength 2048 \
--standalone \
--debug
~/.acme.sh/<도메인>/<도메인>.log 파일에서 오류 메시지를 확인합니다.acme.sh --renew -d example.com --force --debug 명령어로 수동 갱신을 시도하여 문제를 진단합니다.Private CA에서 제공하는 ACME Directory URL(/directory)을 통해 ACME 클라이언트는 필요한 모든 엔드포인트 정보를 자동으로 가져옵니다.
ACME 프로토콜의 전체 흐름은 클라이언트에 의해 자동으로 처리되므로, 사용자는 Directory URL만 제공하면 됩니다.
ACME 프로토콜에 대한 자세한 내용은 RFC 8555를 참고하세요.