게시글

강좌25 - NodeJS - 5달 전 등록 / 12일 전 수정

nginx와 let's encrypt로 SSL 적용하기(+자동 갱신)

Node.js교과서 책이 출간되었습니다. 이 포스팅보다는 책이나 동영상 강좌를 보시는 것을 추천합니다.

리눅스에서 letsencrypt를 직접 설치합시다. 2020년 9월부로는 기존 방식보다 snap을 통해서 설치하는 게 더 쉬운 것 같습니다(https://snapcraft.io/certbot)

기존 방식

wget https://dl.eff.org/certbot-auto

실행권한을 추가합니다.

chmod a+x certbot-auto

certbot-auto를 실행합니다.

./certbot-auto

certbot-auto로 인증서를 제공합니다. certbot-auto는 --standalone으로 하면 됩니다. 이 때는 80번, 443번 포트에 아무 프로세스도 없도록 비워둡시다. 참고로 와일드카드 도메인에 대한 인증서를 발급받는 경우 dns 인증이 필요해서 dns쪽 설정을 중간에 할 수도 있습니다.

기존 서버가 있다면 종료합니다. 다음과 같이 프로세스를 확인해서 종료할 수 있습니다.

lsof -i tcp:80 // 또는 443
kill -9 프로세스아이디

설치하시면서 약관에 동의하고 도메인을 입력해주면 됩니다. /etc/letsencrypt/live 디렉터리에 인증서가 저장됩니다. 도메인주소와 동일한 한 이름의 폴더가 생기고 그 안에 fullchain.pem과 privkey.pem이 존재하면 됩니다. 

snap과 nginx

snap과 nginx를 통해서 letsencrypt를 설치할 수도 있습니다. 예시는 다음과 같습니다.

sudo snap install certbot --classic
sudo apt-get install nginx
sudo certbot --nginx

자신의 이메일을 입력하고, 약관에 동의한 후 원하는 도메인을 입력하면 인증서가 발급됩니다. 이후 서버를 실행하면 됩니다. 참고로 와일드카드 도메인에 대한 인증서를 발급받는 경우 dns 인증이 필요해서 dns쪽 설정을 중간에 할 수도 있습니다. 

기존 서버를 종료하기 싫다면 --webroot옵션으로 해도 됩니다. 이 때는 80번 포트를 http 모듈이 사용하고 있어야 하며, express.static이 가리키는 폴더(public 같은 것)를 --webroot-path로 지정해주어야 합니다. 하지만 그냥 서버를 끄고 standalone 옵션을 하는 것을 더 추천합니다. 

nginx의 /etc/nginx/nginx.conf 예시입니다. 대부분 알아서 잡아주지만 안 되는 경우 직접 수정해야합니다. 혹시 설정파일에 sites-enabled/*를 include하는 설정이 있다면 sites-enabled안에 들어있는 파일을수정하세요. listen 80에서는 301로 리다이렉트하고 listen 443에서는 location과 ssl_certificate 와 ssl_certificate_key만 제대로 지정되면 됩니다.

http {
        server {
                server_name nodebird.com www.nodebird.com;
                return 301 https://nodebird.com$request_uri;
        }
        server {
                server_name vue.nodebird.com;
                return 301 https://$host$request_uri;
        }
        server {
                listen 443 ssl;
                server_name nodebird.com;
                ssl_certificate /etc/letsencrypt/live/nodebird.com-0002/fullchain.pem; # managed by Certbot
                ssl_certificate_key /etc/letsencrypt/live/nodebird.com-0002/privkey.pem; # managed by Certbot
                include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
                ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
                location / {
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Forwarded-Proto $scheme;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_pass http://127.0.0.1:3060;
                        proxy_redirect off;
 
               }
       }
       server {
                listen 443 ssl;
                server_name vue.nodebird.com;
                ssl_certificate /etc/letsencrypt/live/nodebird.com-0002/fullchain.pem; # managed by Certbot
                ssl_certificate_key /etc/letsencrypt/live/nodebird.com-0002/privkey.pem; # managed by Certbot
               include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
                ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
                location / {
                        proxy_set_header Host $host;
                        proxy_set_header X-Forwarded-Proto $scheme;
                        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                        proxy_set_header X-Real-IP $remote_addr;
                        proxy_set_header Upgrade $http_upgrade;
                        proxy_set_header Connection "upgrade";
                        proxy_pass http://127.0.0.1:3081;
                        proxy_redirect off;
                }
        }
}

proxy_set_header 부분은 Header들을 넘겨주는 코드입니다. X-Forwarded-Proto는 https를 할 때 필요하고, Upgrade나 Connection은 웹소켓을 할 때 필요합니다. X-Real-IP와 X-Forwarded-For는 IP를 알아내고 싶을 때 있으면 좋습니다.

다음은 nginx 관련 명령어인데 참고해주세요. /etc/nginx/nginx.conf가 바뀔 때마다 재시작이 필요합니다. 시작이나 재시작 시 에러가 있다면 보통 문법 에러인 경우가 많습니다. status로 확인 가능합니다.

// 시작
$ sudo service nginx start
$ sudo systemctl start nginx
$ sudo /etc/init.d/nginx start

// 재시작
$ sudo service nginx restart
$ sudo systemctl restart nginx
$ sudo /etc/init.d/nginx restart

// 중지
$ sudo service nginx stop
$ sudo systemctl stop nginx
$ sudo /etc/init.d/nginx stop

// 상태
$ sudo service nginx status
$ sudo systemctl status nginx

// 설정 reload
$ sudo service nginx reload
$ sudo systemctl reload nginx
$ sudo nginx -s reload

// 설정파일 문법 체크
$ sudo nginx -t

자동 갱신하기

cron을 사용하여 자동갱신 하면 쉽습니다.

/etc/cron.d/certbot 파일을 다음과 같이 수정합니다. 파일이 없다면 생성합니다(vim으로)

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root certbot -q renew --nginx --renew-hook 'service nginx reload'

이렇게 하면 매일 두 번씩 갱신을 시도합니다.

조회수:
0
목록
투표로 게시글에 관해 피드백을 해주시면 게시글 수정 시 반영됩니다. 오류가 있다면 어떤 부분에 오류가 있는지도 알려주세요! 잘못된 정보가 퍼져나가지 않도록 도와주세요.
Copyright 2016- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.

댓글

1개의 댓글이 있습니다.
2달 전
정리된 좋은 자료 감사합니다.

한참 헤매고 있었는데 도움 많이 되었습니다.
서버 재시작 과정에서 bind 관련 오류가 자꾸 생겼는데 다른 분들도 같은 오류 생기면

lsof -i tcp:80 // 또는 443
kill -9 프로세스아이디

sudo fuser -k 80/tcp

등으로 프로세스 종료 확인해 보세요.