Nginx에서 Letsencrypt를 통해 SSL을 적용하는 방법

Ubuntu의 Nginx 환경에서 Letsencrypt를 통해 SSL인증서를 발급받는 방법을 소개합니다.

Letsencrypt를 통해 SSL 적용

Letsencrypt에서 SSL인증서를 발급받았습니다. Ubuntu16.04 환경에서 certbot와 nginx를 이용하였습니다. Letsencrypt와 nginx에 대해서 잘 몰라서 많은 시간 헤멨네요...

Letsencrypt에서 인증서를 발급 받는 방법 중에 standalone과 webroot 방식이 있는데요. 80포트 서비스가 실행 중인 상태에서도 사용 가능한 방법이 webroot라고 해서 webroot를 시도해보았는데 실패해서 standalone으로 했습니다.

webroot으로 SSL 인증

아쉽게도 여러번 시도해봤지만 webroot로 SSL인증서를 받지 못했습니다. history를 기록차원에서 실패 로그를 남깁니다. 나중에 성공하면 다시 업데이트 할께요.

webroot는 80포트가 서비스 중인 상태에서도 인증이 가능한 방법이라고 합니다. 특정 위치에 key를 저장하고 Letsencrypt가 이 파일의 key를 읽어 도메인의 소유자를 인증하는 것 같습니다. Nginx를 이용하여 특정 위치에 key를 저장할 수 있도록 세팅하였습니다.

Nginx에서 SSL 설정

예를들어 자신의 도메인이 first.com라고 한다면 미리 서버의 IP를 DNS에 등록해둡니다. 그리고 http://first.com/.well-known/acme-challenge/ 와 같은 경로에 파일 접근이 가능한 상태가 되도록 nginx를 설정해야 합니다.

nginx를 설치했다면, 아래 명령어로 다음과 같은 경로에 폴더를 생성합니다.

$ mkdir /var/www/first

그리고 /etc/nginx/sites-available/first.conf 파일을 생성하고 아래처럼 설정합니다. 자신의 도메인의 root 경로를 /var/www/first로 설정하겠다는 의미입니다.

server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    server_name first.com www.first.com;
    root /var/www/first;

    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

사용하지 않는 default 설정 파일을 지우고, ../sites-enabled에 first.conf에 대한 링크를 만듭니다. 그리고 nginx를 실행하고 서버가 정상적으로 실행되는지 상태를 확인합니다.

$ sudo rm /etc/nginx/sites-available/default
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo ln -s /etc/nginx/sites-available/first.conf /etc/nginx/sites-enabled/first.conf

$ sudo nginx -t
$ sudo systemctl stop nginx
$ sudo systemctl start nginx
$ sudo systemctl status nginx

nginx설정은 끝났습니다. 테스트로 /var/www/first/.well-known/acme-challenge/test.txt 경로에 파일을 생성하고 아무 text를 입력합니다. http://first.com/text/.well-known/acme-challenge/test.txt에 접근해서 자신이 입력한 text가 보이는지 확인합니다.

Certbot으로 SSL 인증서 발급

certbot 이라는 프로그램을 이용하면 쉽게 SSL인증서 발급을 할 수 있다고 합니다.

아래 명령어로 certbot을 설치합니다.

$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto

certbot을 실행해서 의존성 파일들을 설치합니다.

$ sudo ./certbot-auto

그리고 아래 명령어를 입력하면 SSL 인증서를 얻을 수 있습니다.

$ sudo ./certbot-auto certonly --webroot -w /var/www/letsencrypt -d first.com

Congratulations~라는 text로 인증서를 발급받았다고 나오면 성공한 것인데, 저는 실패했습니다. 원인을 찾아봐도 몰라서 그냥 standalone으로 발급받았습니다.

standalone 방식으로 인증서 발급

webroot 방식이 잘 안되서 standalone으로 인증서를 발급받았습니다. 80포트가 서비스 중인 상태에서 standalone 방식을 사용할 수 없습니다.

먼저 nginx를 중단합니다.

$ service nginx stop

다음과 같은 명령어를 입력하고, 아래처럼 성공 로그가 보인다면 인증서를 발급 받은 것입니다.

$ certbot-auto certonly --standalone -d first.com

# 성공 로그
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
 ....

인증서는 /etc/letsencrypt/live/first.com/ 처럼 도메인 이름의 폴더가 생성되고 그 안에 인증서 파일이 있습니다.

nginx에 SSL 적용

nginx에 인증서를 적용해보았습니다.

저는 elasticsearch 서버를 구축하고 있었고 /etc/nginx/nginx.conf 파일을 아래처럼 수정했습니다.

upstream elasticsearch {
  server 127.0.0.1:9200;
  keepalive 15;
}
server {
  listen 8443;

  location / {
    proxy_pass http://elasticsearch;
    proxy_http_version 1.1;
    proxy_set_header Connection "Keep-Alive";
    proxy_set_header Proxy-Connection "Keep-Alive";
  }
}

server {
  listen 443;
  ssl on;
  server_name first.com;

  ssl_certificate /etc/letsencrypt/live/first.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/first.com/privkey.pem;

  location / {
    proxy_pass http://elasticsearch;
    proxy_http_version 1.1;
    proxy_set_header Connection "Keep-Alive";
    proxy_set_header Proxy-Connection "Keep-Alive";
  }
}

인증서 자동갱신

Letsencrypt는 3달마다 갱신이 필요하다고 합니다. 아래 명령어를 입력하면 서버에서 인증받은 도메인에 대해서 갱신을 합니다.

$ certbot-auto renew

기간이 많이 남은 경우 갱신이 되지 않습니다.

Processing /etc/letsencrypt/renewal/first.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal

아래 옵션으로 강제로 갱신할 수 있습니다.

$ certbot-auto renew --dry-run

하지만 80포트가 열려있는 경우 standalone은 실패를 합니다. nginx를 종료하고 시도해야 합니다.

Problem binding to port 80: Could not bind to IPv4 or IPv6.. Skipping.

renew하기 전/후에 ngix 종료/실행하도록 hook을 설정하였습니다. standalone은 이렇게 하니 편하네요.

$ certbot-auto renew --pre-hook "service nginx stop" --post-hook "service nginx start" --dry-run

갱신일이 궁금하다며 다음 명령어로 확인이 가능합니다.

$ echo | openssl s_client -connect localhost:443 2>/dev/null | openssl x509 -noout -dates

참고

Loading script...

Related Posts

codechachaCopyright ©2019 codechacha