본문 바로가기
Linux

Docker, Certbot을 이용한 Let's encrypt 인증서 발급 및 관리

by 올엠 2023. 1. 1.
반응형

Certbot과 Nginx를 이용한 Let's encrypt관리 방안을 기존에 정리하였는데, 이번에는 Docker를 활용하는 방법을 정리해보고자 한다.

Ubuntu - Let's Encrypt으로 Nginx에 무료 SSL 적용 (asecurity.dev)

 

Ubuntu - Let's Encrypt으로 Nginx에 무료 SSL 적용

SSL 인증서는 구매하여 사용하기에는 큰 대형 사이트가 아니라면, 일반적인 작은 사이트 혹은 프리랜서용 사이트라면 부담이 클 수 있다. 이를 해결해 주는 것이 바로 Let's Encrypt 에서 제공하는

asecurity.dev

호스트에 Docker를 활용하지 않고 Certbot을 직접 설치해서 진행해도 되지만, Docker를 활용한다면, 설치 없이 진행이 가능하기 때문에, 호스트의 환경적 문제점에서 벗어날 수 있다. 그리고 Docker 환경이 익숙하신분이라면, 도커를 활용하는 것에 대해서도 인지해 놓는 다면 나쁘지 않을 것 같다.(개념 이해등에 보다 도움이 된다..;;)

그럼 Docker 실행 방법부터 정리해 보자.

Certbot Docker 실행

Certbot용 Docker 이미지를 활용하요 실행하도록 하자.

 

$ sudo docker run -it --rm --name certbot \
   -v '/etc/letsencrypt:/etc/letsencrypt' \
   -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
   certbot/certbot certonly -d 'xxx.yourdomain.com' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory

위에 보면 명령이 길다. Docker 관련된 옵션과 Certbot 관련된 옵션이 있는데, 가장 마지막 certbot/certbot 이후 명령이 certbot 관련 옵션이다.

먼저 Docker run 관련 옵션을 알아보자.

-it : interactive + tty의 약자로서 상호작용을 위한 터미널을 연결할 때 사용된다.

-rm: 컨테이너가 중지되면 컨테이너를 자동적으로 삭제하도록 한다.(본 옵션이 없다면, 컨테이너가 남아있어, 사용한 기록이 유지 된다.)

-v: 볼륨을 연결할 때 사용하는 옵션이다. 보통 호스트와 볼륨을 연결하거나, 별도의 Docker 전용 볼륨을 생성해 컨터이너이외의 주요 정보를 기록하는데 사용된다. <호스트경로/별도의 Docker볼륨>:<연결할 Docker내경로> 로 지정하여 사용된다.

다음으로 certbot 옵션이다.

-d: 인증서를 발급받을 도메인 주소를 입력하낟.

--manual --preferred-challenges: certbot에서 지원하는 도메인 인증 방식중 DNS의 TXT 레코드를 사용하겠다는  옵션이다. 기본적으로는 자체적인 웹서비스를 실행하여 Web으로 접근하여 인증하게 된다.

--server: 발급을 요청할 Let's encrypt 주소를 적는다. 적지 않아도 되지만, 와일드카드(*) 는 v02에서만 지원한다고 한다.

여기서 잠깐, Certbot의 도메인 인증 방식에 대해서 알아보자.

Certbot의 도메인 소유 인증

1.웹 서버를 통한 도메인 인증

Certbot이 직접 웹 서버를 띄워서 URL을 통해 해당 웹 서버로 접속을 시도하여 도메인의 소유를 검증하는 방법이다.

접근 로그를 확인해보면, yourdomain.com이라는 도메인의 인증서를 발급받을때, certbot은 yourdomain.com/.well-known/acme-challenge URL을 통해 여러분의 서버에 접속하여 실제 발급을 시도 중인 서버가 맞는지 확인하게된다.

이방법이 간편하지만, 단점으로 웹 서비스를 자체적으로 실행하기 때문에,

현재 서비스 중인 경우 서비스를 잠시 내려놓아야 하는 단점이 있어 많이 추천되지 않는다.

2.DNS 를 통한 도메인 인증

가장 많이 이용하는 방식으로 DNS에 고유한 TXT 레코드를 생성하여 이를 확인해 인증하는 방식이다.

TXT 레코드를 생성해줘야 한다는 단점이 있지만, 서비스를 중지하지 않아도 도메인 검증이 가능하기 때문에 가장 유용한 방법이라고 할 수 있다.

그럼 위 Docker 명령을 실행했을때, Certbot에서 어떻게 진행되는지 실행 로그를 살펴보도록 하자.

실행 로그

$ sudo docker run -it --rm --name certbot \
>   -v '/etc/letsencrypt:/etc/letsencrypt' \
>   -v '/var/lib/letsencrypt:/var/lib/letsencrypt' \
>   certbot/certbot certonly -d 'xxx.yourdomain.com' --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
Unable to find image 'certbot/certbot:latest' locally
latest: Pulling from certbot/certbot
ca7dd9ec2225: Pull complete 
9e124a36b9ab: Pull complete 
42cba90def7f: Pull complete 
036c0ab6a768: Pull complete 
faeb1dfdd591: Pull complete 
efbbe3974aef: Pull complete 
9b0ae0adc7ea: Pull complete 
2324cb2b8d1e: Pull complete 
113f0194043e: Pull complete 
ce510d19afd7: Pull complete 
a3b4d4194c7c: Pull complete 
d44fe23bda67: Pull complete 
6c4372d31f21: Pull complete 
Digest: sha256:27189337effa1c007e51f83743b6e855b78c9b8088dba9c93d080d6206175a4f
Status: Downloaded newer image for certbot/certbot:latest
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): youremail@domain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
Account registered.
Requesting a certificate for xxx.yourdomain.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:

_xxxx.xxx.yourdomain.com.

with the following value:

pl75xxxxx_Tk

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.api.geoip.one.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue

Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
  Domain: xxx.yourdomain.com
  Type:   dns
  Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.xxx.yourdomain.com - check that a DNS record exists for this domain

Hint: The Certificate Authority failed to verify the manually created DNS TXT records. Ensure that you created these in the correct location, or try waiting longer for DNS propagation on the next attempt.

Domain의 소유주의 메일 주소를 물어본 후, 인증서 작업에 동의를 한다고 하면, DNS에 TXT 레코드를 생성할 고유한 값을 

알려준다. 필자 역시 DNS의 TXT 레코드 생성방법으로 진행했기 때문에, 위 Docker 를 실행하면, 아래와 같이 TXT 레코드를 생성하고 엔터를 누르라는 메세지를 확인 할 수 있다.

그러면 실제 도메인 레코드 관리 센터를 열어서 TXT 레코드를 생성하여 엔터를 누르면 정상적으로 인증을 완료하고 인증서를 발급받게 된다.

아래는 Google Domain의 레코드 관리 화면이다.

발급 받은 인증서의 위치와 만료 기간을 알 수 있다.

본 인증서를 관리하기 위해서는 추가적으로 NEXT STEPS에서 나오는 것과 같이 갱신을 진행하라고 한다. 

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/xxx.yourdomain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/xxx.yourdomain.com/privkey.pem
This certificate expires on 2023-04-01.
These files will be updated when the certificate renews.

NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.
We were unable to subscribe you the EFF mailing list because your e-mail address appears to be invalid. You can try again later by visiting https://act.eff.org.

보통은 1개월에 1번 실행하는 것을 추천하며,  Docker 를 통해서 진행하여기 때문에, 갱신도 Docker를 통해서 진행하도록 하자. 갱신시에는 별도의 입력이 필요하지 않기 때문에 crontab을 활용하여 갱신을 진행하면 된다.

아래는 갱신 명령이다. 정상적으로 실행이 되는지 확인한 이후에 crontab에 등록하도록 하자.

docker run -it --rm --name certbot -v '/etc/letsencrypt:/etc/letsencrypt' -v '/var/lib/letsencrypt:/var/lib/letsencrypt' certbot/certbot renew

실행해보면, 아직 실행하지 않아도 된다고 한다. 만약 오류가 나타난다면, 문제가 무엇인지 로그를 확인하도록 하자.

실행이 정상적으로 가능하므로,  crontab은 sudo를 이용하여 root 권한으로 동작하도록 해야 권한 오류로 인한 갱신 실패가 발생하지 않는다.

sudo crontab -e 관련 내용

$ sudo crontab -e
# crontab 내용
0 1 1 * * docker run -it --rm --name certbot -v '/etc/letsencrypt:/etc/letsencrypt' -v '/var/lib/letsencrypt:/var/lib/letsencrypt' certbot/certbot renew

이렇게 Docker를 활용한 인증서 갱신은 완료되었다.

이제 서비스에서 활용하는 것에 대해 짧게 요약해보도록 하겠다.

Docker에서 적용 및 활용

이렇게 발급 받은 인증서를 활용하고자 한다면, 호스트 서버에 파일이 위치하고 있으므로, Docker 기준으로 볼륨으로 마운트를 해주어야 한다.

Docker run을 이용하는 경우 certbot 실행하는 것과 같이 -v 옵션으로 볼륨 추가가 가능하며, Docker-compose를 사용한다면, 아래와 같이 volumes를 지정해서 활용할 수 있다.

version: "3.3"

services:
  mariadb:
    image: mariadb:latest
    ports:
      - 3306:3306
    volumes:
      - mariadb-data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: skfwk123
      MYSQL_DATABASE: geoip
  api:
    image: fastapi:latest
    ports:
      - 443:8080
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - /var/lib/letsencrypt:/var/lib/letsencrypt
    depends_on:
      - mariadb

volumes:
  mariadb-data:

호스트 서버의 파일 위치를 추가하면, Let's encrypt로 부터 인증된 인증서 접근이 가능하게 된다.

 

아래는 실제  FastAPI기준으로 아래와 같이 SSL 인증서를 적용할 수 있다.

 

반응형