Nginx SSL 인증서 설치와 설정 - Let's Encrypt 무료 인증서 사용

무료로 사용할 수 있는 SSL 인증서 서비스인 Let's Encrypt 인증서를 NGINX에 적용하는 방법을 알아보겠습니다.

  • 먼저 NGINX가 설치되어 있어야 합니다.
  • 등록한 도메인이 있어야 합니다.
  • NGINX에 80포트 접속이 가능하도록 설정이 구성되어 있어야 합니다.

무료 인증서를 발급하려는 도메인은 mydomain.com 으로 합니다. 우분투를 기준으로 설명합니다.

Let's Encrypt 클라이언트 설치

certboxpython-certbot-nginx 두개를 모두 설치해야 합니다.

apt update
apt install certbot
apt install python3-certbot-nginx

NGINX 80포트 도메인 설정

NGINX의 개별 사이트별 설정 파일은 다음과 같습니다.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mydomain.com;

    root /var/www/mydomain.com;

    index index.html;

    access_log /var/log/nginx/mydomain.com.access.log;
    error_log /var/log/nginx/mydomain.com.error.log;
}

NGINX로 사이트를 호스팅 할 때 루트 도메인과, www 도메인을 모두 하나의 사이트에서 접근이 가능하도록 하려면 "server_name" 항목에 풀 도메인을 모두 나열해야 합니다.

server_name mydomain.com www.mydomain.com

Certbot으로 인증서를 발급받을 때도 mydomain.com, www.mydomain.com 두 개의 도메인에 대한 인증서를 발급받아야 합니다.

Certbot으로 인증서를 발급받으면 발급 후 다운로드 한 인증서를 설정파일에 구성까지 자동으로 해줍니다. NGINX의 사이트 설정 내용을 80포트로 웹사이트 접속이 가능한 상태의 구성파일이면 됩니다.

dev 도메인은 http:// 접속이 불가능하도록 크롬 브라우저 단에서 차단이 되기 때문에 80포트 연결이 되지 않습니다. 80포트 접근이 안되도 Let's Encrypt 인증서 발급은 문제없이 됩니다.

SSL 인증서 발급

서트봇으로 엔진엑스용 인증서를 발급받는 커맨드는 다음과 같습니다.

  • -d 도메인 : 인증서를 발급받을 도메인을 입력합니다. 도메인이 여러개면 -d 도메인1 -d 도메인2 처럼 나열해서 표시하면 한꺼번에 인증서를 발급합니다.
  • --nginx : 인증서를 다운로드 받은 후 nginx에 인증서 구성 과정까지 한꺼번에 진행합니다.
certbot --nginx -d mydomain.com

인증서를 발급받는 과정에서 이메일 주소와 이용 동의를 하면 인증서가 발급됩니다.

$ certbot --nginx -d mydomain.com -d www.mydomain.com

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
 (Enter 'c' to cancel): extflash@gmail.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.4-April-3-2024.pdf. You must agree in
order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for mydomain.com and www.mydomain.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/mydomain.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/mydomain.com/privkey.pem
This certificate expires on 2024-07-09.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

Deploying certificate
Successfully deployed certificate for mydomain.com to /etc/nginx/sites-enabled/mydomain.com
Successfully deployed certificate for www.mydomain.com to /etc/nginx/sites-enabled/mydomain.com
Congratulations! You have successfully enabled HTTPS on https://mydomain.com and https://www.mydomain.com

인증서 발급과 NGINX 설정까지 자동으로 완료가 되면 NGINX의 해당 도메인을 위한 설정 파일은 다음과 같이 변경됩니다.

서트봇에 의해 변경되고 관리되는 부분은 "# managed by Certbot" 이라는 주석문이 행 끝에 표시됩니다.

NGINX에 멀티 도메인을 설정할 때와 default 사이트 하나만 구성할 때 내용이 약간 다릅니다. 멀티 도메인 설정을 하면 "default_server" 와 관련된 설정 내용이 없습니다.

server {

    listen 80 default_server;
    listen [::]:80 default_server;
    server_name mydomain.com;

    root /var/www/mydomain.com;

    index index.php index.html;

    access_log /var/log/nginx/mydomain.com.access.log;
    error_log /var/log/nginx/mydomain.com.error.log;

    ## Certbot에 의해 추가되는 부분------------------
    
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/bbibu.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/bbibu.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    if ($host = mydomain.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
    return 404; # managed by Certbot
}

Certbot이 추가한 라인에는 "# managed by Certbot"라고 주석이 붙어있습니다. 총 9행이 추가되므로 나중에 인증서를 폐기하거나 하게 되면 추가된 9행을 지우면 됩니다.

크론탭 자동 갱신 설정

Let's Encrypt 인증서는 90일 후에 만료가 되기 때문에 주기적으로 갱신을 해야 합니다. certbot으로 인증서 갱신을 요청하면 Let's Encrypt 서비스는 인증서가 30일 이내로 남았는지 확인 후 30일 이내로 남았으면 인증서를 갱신합니다.

하루에 한번씩 인증서 갱신 요청을 하면 30일 이내로 인증서 유효기간이 남았을 때 자동으로 갱신이 되면서 인증서를 계속해서 사용할 수 있게 됩니다.

크론탭 목록 파일을 엽니다.

crontab -e

다음 크론탭 스캐줄을 추가합니다. 매일 오전 1시에 서트봇 갱신을 요청합니다. --quiet 옵션은 서트봇 실행 결과로 표시하는 메시지를 표시하지 않는 옵션입니다.

0 1 * * * /usr/bin/certbot renew --quiet

서트봇 SSL 인증서 갱신 커맨드가 잘 실행되는지 확인하려면 다음처럼 갱신 커맨드를 실행해보면 됩니다.

$ /usr/bin/certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/mydomain.com.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Certificate not yet due for renewal