[2025.02.27] Ubuntu Server HTTPS Setting

아스라이지새는달·2025년 3월 15일
0
post-thumbnail

HTTPS?

HTTPS는 HyperText Transfer Protocol over Secure Socket Layer로 웹 브라우저와 웹 사이트 간에 데이터를 전송하는데 사용되는 기본 프로토콜인 HTTP의 보안 버전이다.


서버에 HTTPS 설정은 왜 하는가?

접속하는 서버가 로컬 기기(노트북)의 카메라/마이크에 접근하려고 하면 서버가 HTTPS를 사용하는지 확인한다.
즉 HTTPS가 아니라면 라이브를 송출하려는 로컬 기기의 카메라/마이크에 접근이 불가능한 것이다.

이로 인해 서버에 인증서를 발급받고 HTTPS를 사용해야 한다.

관련 이슈 : 서버에 라이브 기능 배포시 접근권한으로 인한 송출불가


인증서 발급

인증서 발급은 무료로 발급해주는 Let's Encrypt를 사용하였다.

또한 HTTP로 들어오는 요청을 HTTPS로 리디렉션 해주기 위해 Nginx를 사용하였다.
Nginx를 도커 컨테이너로 실행하고 인증서 발급을 위한 Certbot 또한 도커 컨테이너로 실행하기 위해
Nginx와 Certbot을 docker-compose로 구성하였다.

아래 과정은 도커 설치 이후 docker-compose 구성 단계부터의 과정이다.

1. Docker-compose.yml 파일 생성

먼저 디렉토리를 생성하고 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.confNginx 설정 파일
./certbot/www:/var/www/certbot:ro./certbot/www/var/www/certbotLet's Encrypt 인증 파일 저장
./cerbot/conf:/etc/letsencrypt./certbot/conf/etc/letsencryptSSL 인증서 저장

2. Nginx 설정 파일 생성

Nginx가 인증서 발급 과정에서 HTTP 요청을 처리할 수 있도록 nginx.conf 파일에 기본 설정을 작성한다.

events {}

http {
    server {
        listen 80;
        server_name your-domain.com;

        location /.well-known/acme-challenge/ {
            root /var/www/certbot;
        }
    }
}

3. 컨테이너 실행 후 인증서 발급

다음 명령어를 입력해 도커 컨테이너를 실행한다. 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/certbotcertbot 컨테이너 이미지를 뜻하고 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은 보안 관련 이메일 수신을 원하지 않을 경우 사용하는 옵션이다.

인증서가 발급되는 전체적인 과정은 다음과 같다.

  1. docker run 명령어가 실행되면 Certbot 컨테이너가 임시 실행된다.
  2. 컨테이너 내부에서 certbot/var/www/certbot 디렉토리에 인증 파일을 생성한다. /var/www/certbot 디렉토리는 호스트의 ~/nginx-https/certbot/www와 연결되어 있다.
  3. Let's Encrypt 서버가 http://your-domain.com/.well-known/acme-challenge/토큰값을 요청하면 Nginx가 /var/www/certbot(즉, ./certbot/www)에서 파일을 제공하여 도메인 소유권을 인증한다.
  4. 인증이 성공하면 Let's Encrypt가 SSL 인증서를 발급하고 이 인증서 파일은 /etc/letencrypt(호스트의 ~/nginx-https/certbot/conf)에 저장된다.
  5. 컨테이너가 종료되며 --rm 옵션 덕분에 컨테이너는 자동 삭제된다.
  6. 인증서가 정상적으로 발급되면 ~/nginx-https/certbot/conf/live/your-domain.com/에 인증서 파일이 저장된다.

Trouble Shooting

인증서 발급 과정 중 CAA 레코드 오류가 발생하여 이에 대해 이슈를 작성하였다.
Let's Encrypt 인증서 발급시 CAA 레코드 오류(iptime.org)

Image

4. Nginx를 HTTPS로 설정

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

5. 테스트

브라우저에서 https://your-domain.com에 접속하여 HTTPS가 정상적으로 작동하는지 확인한다.

Image

HTTPS로 접속했을 때 정상적으로 Nginx 첫 화면이 뜨는 것을 확인할 수 있다.

6. 인증서 자동 갱신 설정(선택 사항)

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 옵션은 실제로 갱신을 하지 않고 테스트로 실행한다는 옵션이다.

테스트가 성공적으로 완료되면 아래와 같이 출력된다.

Image

테스트가 정상적으로 작동되었으니 실제 갱신 작업을 크론탭에 등록한다.

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 * * *로 작성해준다.

Trouble Shooting

자동 갱신 테스트 과정 중 오류가 발생하였고 트러블 슈팅 과정을 이슈로 작성하였다.
인증서 자동 갱신 테스트 오류

이렇게 우분투 서버에 Nginx와 Certbot을 사용하여 HTTPS 설정을 하였다.

profile
웹 백엔드 개발자가 되는 그날까지

0개의 댓글