우분투 NginX + Let's Encrypt

우분투 NginX + Let's Encrypt

지난 방화벽 설정에 이어 또 헷갈렸던 명령어를 (미래의 나를 위해) 가져왔다. NginX에 Let's Encrypt를 설정하는데 내가 했었던 것, 의도하는 것을 ChatGPT한테 장황하게 상황 설명만 하다가 힘이 빠져서 꼭 남겨놔야 겠다는 생각이 들었다.


1. 서버 셋팅

우선 NginX에서 인증서를 받으려는 도메인을 각 다음과 같이 설정해둔다.

server {
    listen 80;
    listen [::]:80;

    server_name {{ SERVER_HOST }}

    location /.well-known {
      root /home/{{ USER_NAME }}/temp;
    }
}
...

저 위치만 굳이 별도로 처리하는 이유는 인증서 처리를 위한 영역이라는 것을 구분하고 싶었고 근래에는 웹서버를 프록시 용도로만 쓰다보니 굳이 별도의 root를 지정하고 싶지 않았다.


2. 인증서 생성

이후 letsencrypt 설치 후 다음 명령어를 실행한다.

sudo apt install letsencrypt
sudo certbot certonly --webroot --webroot-path=/home/{{ USER_NAME }}/temp -d {{ SERVER_HOST }} -d {{ SERVER_HOST_2 }} -d {{ SERVER_HOST_3 }} --dry-run

내부적인 정확한 원리는 알 수 없지만 이렇게 하면 letsencrypt에서 해당 경로에 파일을 올리고 해당 도메인으로 접근해서 여러가지를 체크하는 모양이다.

--dry-run은 해당 작업을 시뮬레이션으로 처리하는 옵션인데, letsencrypt의 경우 명령을 처리할 수 있는 횟수가 (일시적으로) 정해져 있기 때문에 작업을 무분별하게 실행하면 안된다. 시뮬레이션을 통해서 제대로 설정했는지 먼저 확인하고 이후 정상적으로 보이면 --dry-run을 제거하고 실제로 작동시킨다.

그리고 SSL/TLS 구성에 필요한 마지막 파일을 OpenSSL 명령으로 생성해준다.

sudo openssl dhparam -out /etc/ssl/certs/dhparams.pem 2048


3. 인증서 갱신 자동화

letsencrypt로 생성한 인증서는 3개월 마다 갱신을 해줘야하는데, 이걸 자동화하지 않으면 다음과 같은 상황을 맞이할 수 있다.

어떤 의미로... 바보 인증

sudo vi /etc/letsencrypt/renewal-hooks/deploy/restart-nginx.sh
#!/bin/bash

sudo service nginx reload
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/restart-nginx.sh

restart가 아닌 reload를 사용하는 이유는 restart는 일시적인 다운타임이 발생하기 때문이다. 또한 스크립트를 실행할 수 있도록 실행 권한을 꼭 주자.

sudo certbot renew --deploy-hook "/etc/letsencrypt/renewal-hooks/deploy/restart-nginx.sh"

이렇게 등록해두면 인증서 갱신이 성공적으로 이뤄졌을 때 등록한 스크립트가 실행된다. 이제 갱신을 적절한 타이밍에 자동으로 진행하도록 처리해두자.

sudo crontab -e
10 5 * * 1 /usr/bin/certbot renew

앞에 규칙은 자신이 생각하는 이상적인 시간으로 바꿔서 쓰면 되겠다.


4. SSL/TLS 적용

초기에 설정했던 서버 설정을 다음과 같이 변경하자.

server {
    listen 80;
    listen [::]:80;
    listen 443 ssl http2;

    server_name {{ SERVER_HOST }};

    ssl_certificate "/etc/letsencrypt/live/{{ SERVER_HOST }}/fullchain.pem";
    ssl_certificate_key "/etc/letsencrypt/live/{{ SERVER_HOST }}/privkey.pem";
    ssl_dhparam "/etc/ssl/certs/dhparams.pem";

    location /.well-known {
        root /home/{{ USER_NAME }}/temp;
    }
        
    if ($scheme = http) {
        return 301 https://$server_name$request_uri;
    }
}

각각의 인증서 등록과 443 포트를 통한 통신이 가능하도록 설정해준다. 마지막으로 http로 접근한 사용자는 강제로 https로 변경하는 조건문을 추가해 주었다. https 통신이 가능한 상황에서 http로의 접근은 불필요하거니와 매우 위험하기 때문이다.

이 글이 도움이 되었나요?

신고하기
0분 전
작성된 댓글이 없습니다. 첫 댓글을 달아보세요!
    댓글을 작성하려면 로그인이 필요합니다.