“ 당신은 소프트웨어 품질을 추구할 수도 있고, 포인터 연산을 할 수도 있다. 그러나 두 개를 동시에 할 수는 없다. ”
이번 포스팅에서는 Docker-compose로 Nginx와 CertBot 이미지를 사용해
LetsEncrypt SSL 인증서를 발급하는 방법에 대해서 설명해 볼까 합니다.
Cetbot 인증서
Certbot 인증 방법에는 아래 3개 방법 이외에도 방법이 있지만 간단하게 설명드리고 제가 진행할 방법은 와일드카드 방식으로 인증서를 발급해 보겠습니다.
- webroot : 사이트 디렉터리 내에 인증서 유효성을 확인할 수 있는 파일을 업로드하여 인증서를 발급하는 방법
- 이 방법의 단점은 하나의 인증 명령에 하나의 도메인 인증서만 발급 가능
- Standalone : 사이트 작동을 멈추고 이 사이트의 네크워킹을 이용해 사이트 유효성을 확인해 Let’s Encrypt SSL 인증서를 발급하는 방법
- 이 방법은 동시에 여러 도메인을 발급받을 수 있지만, 인증서 발급 전에 Nginx를 중단하고 발급 완료 후 다시 Nginx를 시작해야 된다.
- DNS : 도메인을 쿼리해 확인되는 TXT 레코드로 사이트 유효성을 확인하는 방법
- 와일드카드 방식으로 인증서를 발급 가능
- 와일드카드를 이용하면 *. example.com 앞에 * 어떠한 주소가 오더라도 (서브도메인) HTTPS를 적용할 수 있는 장점이 있다.
- 와일드카드 방식으로 인증서를 발급 가능
도메인 구입 (호스팅케이알)
이번에 도메인은 호스팅 케이알을 통해서 구매를 했습니다. 도메인 연결 연습할 겸 적당한 가격으로 도메인 하나 샀습니다.
저번 시간에 docker-compose로 portainer를 설치했는데 이 사이트를 한번 https로 도메인 적용을 해보도록 하겠습니다.
[IT/docker] - [Docker] docker-compose로 portainer 설치하자
도메인 구입 이후 "나의 도메인"에서 네임서버/DNS로 들어가셔서 DNS 레코드 관리에서 새 래코드 추가를 합니다.
portainer 사이트를 연결할 거니 서브 도메인명은 portainer로 하겠습니다.
유형 A
이름: portainer
값 : 본인 공유기 외부 IP (192.168.0.1로 공유기 관리사이트에서 확인하시면 됩니다.)
Nginx 폴더 구성
우분투 서버까지 샀으면 좋았겠지만 연습용이니 환경은 M1 맥북 16인치 제 노트북으로 진행하겠습니다.
위에 이전 포스팅에서 docker 폴더를 만들어서 portainer 폴더에 구성했으니 이번에도 docker 폴더에 nginx폴더를 구성해 봅니다.
# docker 폴더 진입 (없다면 mkdir docker -> cd docker)
cd docker
mkdir nginx
nginx 폴더를 생성하셨으면 아래 이미지처럼 폴더를 구성하시면 됩니다. 어차피 docker-compose Volume로 잡아둘 거라 자동 생성되니
폴더 구성과 파일구성만 아래처럼 만들어줍니다.
nginx.conf 파일 작성
nginx폴더에서 conf폴더에 nginx.conf 파일을 생성하여 아래 내용을 작성합니다. (그대로 복사해서 넣으셔도 됩니다.)
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for" -- $host';
#access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
서브 도메인 conf 파일 작성
portainer 서브도메인 conf 파일을 작성해 줍니다. 도메인명은 예를 들어서 example.com으로 하겠습니다.
conf폴더에 portainer.example.com.conf 파일을 생성하여 작성합니다.
log_format main '$sent_http_X_DEBUG_MESSAGE';
server {
listen 80; #80 포트
server_name portainer.example.com; #접근 도메인
#letsencrypt 도메인 확인
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# path
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl; #443 포트
server_name portainer.example.com; #서브도메인을 입력
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; #메인도메인 입력
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; #메인도메인 입력
location / {
add_header X_DEBUG_MESSAGE "portainer.example.com";
proxy_pass http://111.11.11.111:55555; #공유기 외부 ip와 portainer 외부 포트
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
access_log /var/log/nginx/access.log main;
}
공유기 외부 IP와 이전 포스팅에서 portainer 외부포트로 열어줬던 포트를 입력합니다. 꼭 http://로 작성해 주시면 됩니다.
아래 공유기 포트포워드 설정에서 http와 https 포트를 꼭 설정해주셔야 합니다.
cert.sh 파일 작성
이제 certbot으로 letsencrypt ssl 인증서를 발급해 봅니다. conf폴더에서 나와서 nginx 폴더에 cert.sh파일을 작성하겠습니다.
와일드카드 방식이라 cert.sh파일 작성 후 아래 이미지처럼 진행하시면 됩니다.
docker-compose run --rm --entrypoint "\
certbot certonly \
-d example.com \
-d *.example.com \
--email aaa@gmail.com \
--manual --preferred-challenges dns \
--server https://acme-v02.api.letsencrypt.org/directory \
--force-renewal" certbot
docker-compose exec nginx nginx -s reload
docker-compose.yml 파일 작성
아래와 같이 위에 설정해 놨던 파일을 volume로 연결해 주고 port설정을 해주시면 됩니다. 아래 파일에서 본인의 서브 도메인명만 바꾸시면 될 거 같습니다.
version: '3.8'
services:
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
nginx:
image: nginx
container_name: nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
- ./conf/nginx.conf:/etc/nginx/nginx.conf
- ./conf/portainer.example.com.conf:/etc/nginx/conf.d/portainer.example.com.conf
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
nginx 폴더에서 sh cert.sh 명령어로 실행하면 아래 이미지처럼 진행이 됩니다.
첫 번째 빨간 상자가 DNS TXT 키 값인데 저게 나오고나서 Enter누르라고 나오는데 누르지 마시고 호스팅 케이알로 돌아갑니다.
example.com , *example.com 등록했으니 두개가 나올겁니다 하나 나오면 엔터누르면 두번째가 나옵니다 그 이후에 진행하셔도됩니다.
호스팅 케이알 DNS 레코드 관리에서 아래처럼 작성합니다.
유형 : TXT
이름 : _acme-challenge
값 : 위에 이미지 첫번째 빨간 상자 키값 입력
호스팅케이알 DNS 레코드관리에서 첫번째 코드와 두번째 코드 같은 유형과 이름으로 두개 등록하시면 됩니다.
그리고 엔터 누르시면 진행이 됩니다.
혹시나 두번째 박스에 URL로 TXT 레코드 확인하기 싫으시다면
nslookup -q=txt _acme-challenge.example.com으로 확인하시면 됩니다.
자 완료가 되면 아래처럼 완료가 됩니다. 그리고 nginx폴더 cetbot폴더 conf폴더로 가보시면 이미지처럼 key가 발급된 거를 확인할 수 있습니다.
docker-compose.yml 파일 실행
마지막으로 도커 컴포즈 파일을 실행합니다.
docker-compose up -d
이제 https://portainer.example.com으로 접속하시면 ssl 인증서가 제대로 적용된 상태가 보입니다.
메인 도메인은 아마 따로 설정하시지 않았다면 nginx 기본 페이지가 나올 겁니다. 추후에 개인블로그를 직접 만드시거나 할 때 메인도메인으로 연결하시면 됩니다.