게시글

강좌25 - NodeJS - 일 년 전 등록 / 2달 전 수정

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

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

리눅스에서 letsencrypt를 직접 설치합시다. snap을 통해서 설치하는 게 제일 쉽습니다(https://snapcraft.io/certbot) 

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 옵션을 하는 것을 더 추천합니다. 

실행 후에는 /etc/letsencrypt/live 디렉터리에 인증서가 저장됩니다. 도메인주소와 동일한 한 이름의 폴더가 생기고 그 안에 fullchain.pem과 privkey.pem이 존재하면 됩니다.

nginx는 /etc/nginx/nginx.conf에 설정 파일이 있습니다. 만약 여기에 include /etc/nginx/sites-enabled/*; 이라는 문구가 있다면 /etc/nginx/sites-enabled 폴더에 default라는 파일명으로 설정이 존재할 겁니다. 이 때는 default를 수정하시면 됩니다. default가 존재하는데 nginx.conf를 수정하면 default가 nginx.conf를 덮어쓸 수도 있습니다.

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

다음 코드를 필요한 도메인에 맞게 수정해서 쓰시면 됩니다.

/etc/nginx/sites-enabled/default

server {
        server_name nodebird.com www.nodebird.com;
        return 301 https://nodebird.com$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;
       }
}

# managed by Certbot 주석이 붙은 줄은 건들지 마세요.

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

참고로 /etc/nginx/nginx.conf는 다음과 같습니다.

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 768;
        # multi_accept on;
}

http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

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

        gzip on;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
} 

다음은 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- . 무단 전재 및 재배포 금지. 출처 표기 시 인용 가능.

댓글

3개의 댓글이 있습니다.
한 달 전
안녕하세요 그런데 질문이있어요 마지막에 자동 갱신은 매일 날짜가 갱신이 되는건가요 아니면 3달이 지나면 갱신이 되나요? 저걸 생성하고 세줄 입력했는데 인증서 유효기간이 변하지않는데 적용이 안된걸까요? 아니면 3달 지나봐야 알수있을까요.??
한 달 전
저 명령어는 매 12시간마다 갱신 요청을 합니다. 다만 갱신은 만료 1달 전부터인가 할 수 있을겁니다. 그래서 2달 뒤에나 확인하실 수 있습니다.
한 달 전
아하 그렇군요! 제대로 적용이 안된건지 궁금했는데 감사합니다.
4달 전
제로초님 제가 이해한것이 맞는지 잘 모르겠습니다. nginx conf파일을 들어가보면 server에 listen설정하는곳있잖아요? 그게 만약listen 80으로 설정해두고 proxy_pass http://127.0.0.1:3065;으로 해두면 80번으로 요청을 보내도 3065포트번호로 접근이 가능하다는 의미인가요?.. 또한 실제서비스에서 127.0.0.1이렇게 로컬 주소를 쓰는 이유가 무엇인지 궁금합니다 실제서비스에서는 인스턴스 ip를 사용하는것이 아닌가욥??
4달 전
80번으로 요청 보낼 때 3065번으로 요청을 전달합니다. 127.0.0.1은 내 서버에서 자기 자신을 가리키는 것이고, 인스턴스 ip는 서버 외부에서 인스턴스에 접근할 때를 가리키는 겁니다.
일 년 전
정리된 좋은 자료 감사합니다.

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

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

sudo fuser -k 80/tcp

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