
HTTPS를 지원하기 위해서는 인증서 발급이 필요하며, 보통 연단위 비용이 청구된다. 하지만 Let's Encrypt와 cerbot 서비스 이용 시 연단위 비용 없이 인증서를 발급 받을 수 있다. 대신 일정 기간(90일)마다 갱신이 필요하다.
Let's Encrypt
Let's Encrypt는 인터넷 보안 연구 그룹인 ISRG(Internet Security Research Group)에서 운영하는 인증 기관(CA)이다. 해당 서비스는 웹사이트 소유자에게 무료 SSL/TLS 인증서를 제공하여 HTTPS 통신을 사용할 수 있도록 해준다.
Certbot
Electronic Frontier Foundation(EFF)에서 개발한 오픈 소스 소프트웨어이다. Certbot을 사용하면 Let's Encrypt의 인증서 발급 및 갱신을 자동화할 수 있다.
cerbot 프로그램을 제공해주며, 해당 프로그램에 다음 옵션을 넣어 인증서를 발급 받을 수 있다.
cerbot certonly --cert-name cert --standalone -d
domain.com,www.domain.com
도메인 구입 및 DNS 레코드 설정
가비아에서 도메인 구입 후, 가비아에서 DNS 레코드 설정을 하여 자신의 EC2 고정 IP를 도메인에 연결시켜 준다.
타입은 A로 선택해주고, 값/위치란에는 EC2에 할당된 고정 IP를 입력해준다.
@ : 아무 문자열을 의미한다.
설정 과련 참고 링크 : https://customer.gabia.com/manual/dns/3041/3040
AWS EC2 서버 구축 및 고정 IP(탄력적 IP) 연결
certbot certonly --dry-run --webroot --webroot-path=/usr/share/nginx/html
--email [이메일] --agree-tos --no-eff-email --keep-untill-expiring -d [도메인 주소1 ex. inkyung.site] -d [도메인 주소2 ex. www.inkyung.site]
certbot certonly
certonly는 certbot 프로그램의 플러그인으로 인증서를 받는 서브 명령이다.
--dry-run
테스트 시 해당 옵션을 사용하여 테스트 해준다. 해당 옵션 없이 반복적으로 테스트를 진행하면, 에러가 발생한다.
cf. Let's Encrypt도 양산용 서버와 테스트 서버가 있다고 생각하면 된다. 따라서 테스트를 할 때에는 위 명령어를 사용해 테스트 서버에 인증서 발급 요청을 하는 것이 좋다. 위 명령어 없이 테스트 시 실제 양산 서버에 인증서를 수 없이 요청하게 되어 나중에는 요청 수가 초과되었다는 오류가 발생하게 된다.
--webroot
자신이 발급받은 도메인과 연결된 웹 서버에 접속하여 정상적으로 동작하는지 확인 후, 인증서를 발급 받도록 하는 옵션이다.
다른 유사 옵션들과 달리 --webroot 옵션을 사용하면 인증서를 발급받을 동안에도 서버가 중단되지 않아 해당 옵션을 사용한다.
--webroot-path
해당 옵션을 사용하여 웹 서버의 루트 디렉토리를 지정하면, 인증서 발급 과정 중 해당 디렉토리에 임시 파일을 생성하여 Let's Encrypt가 도메인 소유 여부를 확인할 수 있다. (보통은 각 웹 서버에서 지정해놓은 루트 폴더로 설정한다.)
--email
인증서 복구 등을 위한 이메일을 등록하는 옵션이다.
--agree-tos
Let's Encrypt 인증서를 요청할 때 이용 약관에 동의하는 것을 자동화하는 옵션이다. Let's Encrypt는 SSL/TLS 인증서를 무료로 제공하며, 이용 약관에 동의해야 인증서를 발급받을 수 있다. 보통은 수동으로 약관에 동의를 해야하지만, 해당 옵션 사용시 약관 동의를 자동화 할 수 있다.
--no-eff-email
일반적으로 Let's Encrypt의 이용 약관에 따라 SSL/TLS 인증서를 발급받을 때, 이메일 주소를 제공해야 한다. 하지만 해당 옵션을 사용하면 이메일 주소를 제공하지 않고 인증서를 요청할 수 있다.
그러나 주의해야 할 점은 이메일 통보를 받지 못하면 인증서의 만료나 기타 중요한 사항을 알지 못할 수 있으므로, 주기적으로 SSL/TLS 인증서를 관리하고 갱신해야 한다.
--keep-until-expiring
아직 인증서의 재발급이 필요하지 않으면, 갱신하지 않고 기존 인증서를 보존하는 옵션이다. 인증서의 기본 유효기간은 90일이다.
-d
인증서를 발급받을 도메인 이름을 지정하는 옵션이다. 해당 옵션을 사용하여 하나 이상의 도메인 이름을 지정하면, 해당 도메인에 대한 SSL/TLS 인증서를 발급받을 수 있다. 위와 같이 2개의 도메인 주소를 사용하는 것이 일반적이다.
version: "3"
services:
webserver:
image: nginx:latest
container_name: proxy
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- ./myweb:/usr/share/nginx/html
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./certbot-etc:/etc/letsencrypt
nginx:
image: nginx:latest
container_name: myweb
restart: always
volumes:
- ./myweb:/usr/share/nginx/html
certbot:
depends_on:
- webserver
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot-etc:/etc/letsencrypt
- ./myweb:/usr/share/nginx/html
command: certonly --dry-run --webroot --webroot-path=/usr/share/nginx/html --email kom347@naver.com --agree-tos --no-eff-email --keep-until-expiring -d inkyung.site -d www.inkyung.site
--webroot 옵션을 사용했기 때문에 webserver 컨테이너가 선행되어야지만 정상적으로 실행되기 때문에 depends on 옵션을 사용해준다.
HTTPS 통신을 위해서는 443번 포트를 열어주어야 한다.
EC2 서버에서도 443번 포트를 열어주는 인바운드 규칙을 추가해줘야 한다.
./myweb:/usr/share/nginx/html
--webroot --webroot-path=/usr/share/nginx/html 옵션으로 인해 인증서 발급 과정 중 해당 디렉토리에 Let's Encrypt가 도메인 소유 여부를 확인할 수 있는 임시 파일을 생성하게 된다.
그리고 -webroot 옵션으로 인해, 도메인과 연결된 서버(webserver 컨테이너)에 접속하여 이 임시파일을 확인하고 정상적으로 Let's Encrypt가 도메인 소유 여부를 확인하면 인증서를 ./certbot-etc:/etc/letsencrypt 경로로 발급하게 된다.
따라서 webserver 컨테이너의 볼륨 옵션으로 ./myweb:/usr/share/nginx/html를 설정해주는 것이다.
./certbot-etc:/etc/letsencrypt
webserver 컨테이너(프록시 서버)가 HTTPS를 지원하게 되고, 인증서를 체크하게 되는데 해당 인증서는 ./certbot-etc:/etc/letsencrypt 경로에 저장이 되어있다. 따라서 해당 프록시 서버에서 인증서를 확인할 수 있도록 볼륨 옵션으로 ./certbot-etc:/etc/letsencrypt를 설정해주는 것이다.
cf. 외부에서 프록시 서버로 진입할 때만 HTTPS 통신을 하고 내부 서버들 간의 통신은 HTTP 통신을 할 것이기에 nginx 컨테이너의 볼륨 옵션에는 ./certbot-etc:/etc/letsencrypt 설정을 할 필요가 없다.
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
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" "$request_uri" "$uri"'
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
upstream docker-web {
server nginx:80;
}
server {
location ~ /.well-known/acme-challenge {
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
}
location / {
allow all;
root /usr/share/nginx/html;
try_files $uri =404;
}
}
}
docker-compose up -d
위 명령어를 사용해 컨테이너들을 생성해주고 아래 명령어를 통해 인증서가 성공적으로 발급되었는지를 확인한다.
docker logs certbot
certbot 컨테이너의 로그를 확인하는 명령어이다.
해당 명령어를 입력후 아래 내용이 뜨면 성공적으로 인증서가 발급되었다는 것이다.