
HTTPS는 HyperText Transfer Protocol over Secure Socket Layer로 웹 브라우저와 웹 사이트 간에 데이터를 전송하는데 사용되는 기본 프로토콜인 HTTP의 보안 버전이다.
접속하는 서버가 로컬 기기(노트북)의 카메라/마이크에 접근하려고 하면 서버가 HTTPS를 사용하는지 확인한다.
즉 HTTPS가 아니라면 라이브를 송출하려는 로컬 기기의 카메라/마이크에 접근이 불가능한 것이다.
이로 인해 서버에 인증서를 발급받고 HTTPS를 사용해야 한다.
관련 이슈 : 서버에 라이브 기능 배포시 접근권한으로 인한 송출불가
인증서 발급은 무료로 발급해주는 Let's Encrypt를 사용하였다.
또한 HTTP로 들어오는 요청을 HTTPS로 리디렉션 해주기 위해 Nginx를 사용하였다.
Nginx를 도커 컨테이너로 실행하고 인증서 발급을 위한 Certbot 또한 도커 컨테이너로 실행하기 위해
Nginx와 Certbot을 docker-compose로 구성하였다.
아래 과정은 도커 설치 이후 docker-compose 구성 단계부터의 과정이다.
먼저 디렉토리를 생성하고 docker-compose.yml 파일을 생성한다.
mkdir -p ~/nginx-https && cd ~/nginx-https
vi docker-compose.yml
mkdir p 옵션은 --parents로 상위 디렉토리가 없을 경우 자동으로 생성하라는 옵션이다.
services:
nginx:
image: nginx:latest
container_name: nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certbot/www:/var/www/certbot:ro
- ./certbot/conf:/etc/letsencrypt
networks:
- web
certbot:
image: certbot/certbot
container_name: certbot
volumes:
- ./certbot/www:/var/www/certbot:rw
- ./certbot/conf:/etc/letsencrypt
networks:
- web
networks:
web:
driver: bridge
볼륨 설정에 관련된 설명은 다음과 같다.
| 볼륨 설정 | Host PC 디렉토리 | 컨테이너 내부 디렉토리 | 설명 |
|---|---|---|---|
./niginx.conf:/etc/nginx/nginx.conf:ro | ./nignx.conf | /etc/nginx/nginx.conf | Nginx 설정 파일 |
./certbot/www:/var/www/certbot:ro | ./certbot/www | /var/www/certbot | Let's Encrypt 인증 파일 저장 |
./cerbot/conf:/etc/letsencrypt | ./certbot/conf | /etc/letsencrypt | SSL 인증서 저장 |
Nginx가 인증서 발급 과정에서 HTTP 요청을 처리할 수 있도록 nginx.conf 파일에 기본 설정을 작성한다.
events {}
http {
server {
listen 80;
server_name your-domain.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
}
}
다음 명령어를 입력해 도커 컨테이너를 실행한다. docker-compose.yml 파일이 있는 nginx-https 디렉토리 내에서 실행해야 한다.
docker-compose up -d
그 후 다음 명령어를 입력해 인증서를 발급한다.
docker run --rm \
-v ~/nginx-https/certbot/conf:/etc/letsencrypt \
-v ~/nginx-https/certbot/www:/var/www/certbot \
certbot/certbot certonly \
--webroot -w /var/www/certbot \
-d your-domain.com \
--email your-email@example.com \
--agree-tos --no-eff-email
--rm옵션은 컨테이너 실행이 끝난 후 자동으로 삭제하는 옵션이다.certbot컨테이너는 인증서 발급 과정에서만 사용되므로 유지할 필요가 없다.
-v옵션은 호스트와 컨테이너 간에 볼륨을 공유하도록 하는 볼륨 마운트 옵션이다. 마운트하는 디렉토리는docker-compose.yml에서 사용한 디렉토리와 동일해야 한다.
certbot/certbot은certbot컨테이너 이미지를 뜻하고certonly는 인증서만 발급하고 웹 서버 설정은 건드리지 않겠다는 것을 의미한다.nginx에서 직접 SSL 설정을 할 것이므로 해당 옵션을 사용한다.
--webroot -w /var/www/certbot은 ACME 챌린지 파일을 특정 웹 루트 디렉토리에 생성하는 방식으로 인증을 수행하고 이 때 저장될 웹 루트 디렉토리를/var/www/certbot로 지정한다는 뜻이다./var/www/certbot디렉토리는 컨테이너 내부 경로이고 볼륨 마운트를 통해 호스트의~/nginx-https/certbot/www디렉토리와 연결된다.
-d your-domain.com은 SSL 인증서를 발급할 도메인 이름을 지정하는 것으로your-domain.com에는 실제 도메인을 입력해야 한다.
--email your-email@example.com은 Let's Encrypt 에서 보내는 알림을 받을 이메일 주소를 입력하는 것이다.
--agree-tos옵션은 Let's Encrypt의 이용 약관에 자동으로 동의한다는 옵션이고--no-eff-email은 보안 관련 이메일 수신을 원하지 않을 경우 사용하는 옵션이다.
인증서가 발급되는 전체적인 과정은 다음과 같다.
docker run 명령어가 실행되면 Certbot 컨테이너가 임시 실행된다.certbot이 /var/www/certbot 디렉토리에 인증 파일을 생성한다. /var/www/certbot 디렉토리는 호스트의 ~/nginx-https/certbot/www와 연결되어 있다.http://your-domain.com/.well-known/acme-challenge/토큰값을 요청하면 Nginx가 /var/www/certbot(즉, ./certbot/www)에서 파일을 제공하여 도메인 소유권을 인증한다./etc/letencrypt(호스트의 ~/nginx-https/certbot/conf)에 저장된다.--rm 옵션 덕분에 컨테이너는 자동 삭제된다.~/nginx-https/certbot/conf/live/your-domain.com/에 인증서 파일이 저장된다.인증서 발급 과정 중 CAA 레코드 오류가 발생하여 이에 대해 이슈를 작성하였다.
Let's Encrypt 인증서 발급시 CAA 레코드 오류(iptime.org)
Nginx가 HTTPS 요청을 처리할 수 있도록 nginx.conf 파일을 다음과 수정한다.
events {}
http {
server {
listen 80;
server_name your-domain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
return 301 https://$host$request_uri;를 통해 HTTP로 들어오는 요청을 HTTPS로 리디렉트한다.
Nginx 설정을 적용하기 위해 컨테이너를 다시 시작한다.
docker-compose down
docker-compose up -d
브라우저에서 https://your-domain.com에 접속하여 HTTPS가 정상적으로 작동하는지 확인한다.
HTTPS로 접속했을 때 정상적으로 Nginx 첫 화면이 뜨는 것을 확인할 수 있다.
Let's Encrypt 인증서는 90일 동안만 유효하므로 자동 갱신을 설정해야 한다.
크론잡에 스케줄을 추가하기 전에 Certbot이 자동 갱신을 정상적으로 작동하는지 테스트 해본다.
docker run --rm \
-v ~/nginx-https/certbot/conf:/etc/letsencrypt \
-v ~/nginx-https/certbot/www:/var/www/certbot \
certbot/certbot renew --dry-run
certbot renew로 실행하면 기존 인증서가 30일 이내로 만료될 경우 자동 갱신을 해주고 만료되지 않은 인증서는 갱신하지 않는다.
--dry-run옵션은 실제로 갱신을 하지 않고 테스트로 실행한다는 옵션이다.
테스트가 성공적으로 완료되면 아래와 같이 출력된다.
테스트가 정상적으로 작동되었으니 실제 갱신 작업을 크론탭에 등록한다.
crontab -e
아래 내용을 추가한다.
0 0 * * * docker run --rm -v ~/nginx-https/certbot/conf:/etc/letsencrypt -v ~/nginx-https/certbot/www:/var/www/certbot certbot/certbot renew && docker-compose restart nginx
crontab은 기본적으로 호스트 OS의 시스템 시간을 따른다. 매일 자정에 해당 작업을 실행하도록 하고 싶은데 호스트 OS의 시스템 시간이 KST이므로
0 0 * * *로 작성해준다.
자동 갱신 테스트 과정 중 오류가 발생하였고 트러블 슈팅 과정을 이슈로 작성하였다.
인증서 자동 갱신 테스트 오류
이렇게 우분투 서버에 Nginx와 Certbot을 사용하여 HTTPS 설정을 하였다.