2. Nginx 설치 부터 spring boot 기반 앱 배포 - Cerbot 인증서 발급과 SSL 적용

박지현·2021년 8월 25일
5
post-thumbnail

지난번에 nginx에 대한 메인 개념에 대해 이야기 해봤다. 최근 진행중에 있던 프로젝트가 마무리되면서 아마존 EC2 환경에서 도메인이름으로 웹 서비스를 배포할 일이 생겼다. 그런데 서비스를 배포할 때 데이터가 안전하게 오고가는 것을 보장하기 위해서는 https가 지원되어야 해야하는데 이 때 반드시 유효한 ssl/tls 인증서가 필요하다. cerbot 라이브러리로 무료 인증서를 발급 받고 nginx를 통해 https 페이지를 만들어보자.
(nginx 설치 ~ nginx를 활용한 https 적용 까지 다룰 것이다)

배포환경

나의 배포환경은 다음과 같다

  • AWS EC2 (Ubuntu 18.0)
  • .jar 의 spring boot 어플리케이션 (webpack형태로 프론트와 백엔드가 통합된 상태)
  • .jar파일을 docker로 실행하고 있음
  • https를 적용한 도메인/퍼블릭 주소에서는 openvidu라는 다른 앱이 러닝되고 있는 상태
  • 해당 spring boot 어플리케이션은 8443포트로 배포하고 있는 상태

-> openvidu 서비스를 다른 특정 포트에서 접근하도록 바꾸고, spring boot 어플리케이션을 https 페이지로 만드는 것이 나의 목표다.

Openvidu 서비스의 포트 설정

기존에 도메인 주소로 배포되는 앱이 없다면 이 과정을 과감히 생략하자.

openvidu 자체적으로 redis, coturn, niginx를 docker로 실행시키고 있기 때문에 443을 비롯한 예약 포트들을 쓰고 있다. 기존에 나는 openvidu서비스를 돌리고 있었기 때문에 spring boot 앱을 https 페이지로 만들기 위해서 예약된 포트들의 번호를 다른 포트로 바꿔 줄 필요가 있었다.

  1. 실행중인 오픈비두 앱을 중지하고, 설정 파일을 연다.
# EC2 접속 후 openvidu 설치 경로로 이동
$ ./openvidu stop
$ vi .env
  1. .env 파일에서 HTTP 포트 번호와, HTTPS 포트 번호 부분의 주석을 풀고 사용할 포트를 설정한다.
....
HTTP_PORT=8448
...
HTTPS_PORT=8447
  1. esc를 누르고 :wq를 입력하여 저장하고 빠져나온 뒤 restart한다.
$./openvidu restart

NGINX 설정

Nginx 설치

다음의 명령어를 입력해서 nginx를 설치하고 실행상태까지 확인해보자.

$ sudo apt-get update #운영체제에서 사용 가능한 패키지들과 그 버전에 대한 정보(리스트) 업데이트 
$ sudo apt install nginx -y #nginx 설치하기
$ nginx -v #설치한 nginx 버전 확인
$ sudo service nginx status #nginx running 상태 확인

실행상태가 다음과 같으면 정상작동하고 있는 것이다.

만약 빨간 부분으로 inactive라고 표시된다면 실행중이지 않은 것이니 다음 명령어를 입력하여 nginx를 실행한다.

 $ sudo service nginx start

* 참고 : nginx에 대한 기본적인 명령어들

$ sudo service nginx start #nginx 실행

$ sudo service nginx restart #nginx 셧다운 후 재실행

$ sudo servcie nginx reload #수정된 설정 파일 적용하여 nginx 실행

$ sudo service nginx stop #nginx 중지

$ nginx -t #nginx 설정파일의 문법이 올바른지 확인

Certbot

nginx를 잘 설치 했다면 이번에는 certbot으로 https페이지를 만들기 위한 인증서를 발급받을 것이다.

Certbot이란?

https페이지를 만들기 위해서는 ssl인증서를 발급받아 적용해야한다. 과거에 인증서는 유료로 발급받았어야 했다. 이에 https를 확산시키기 위한 움직임으로 letsencrypt의 형태로 ssl/tls 인증서를 무료로 제공하는 certbot라이브러리가 등장했다. 기본적인 .conf 파일을 작성한뒤 certbot을 적용하면 알아서 추가적인 인증서 설정을 해준다

짐깐! SSL/SSL에 대하여 (아주 간략)
SSL/TLS는 응용계층과 전송계층 사이에서 보안 채널을 형성해주는 역할을 수행하는 보안용 프로토콜이다. 회원가입등의 민감 정보들이 오고가기 때문에 이에 대한 암호화작업을 해야한다. 통신이 이루어질 때마다 민감 정보 데이터를 암호화하는 방법도 있겠지만 번거롭기에 주로 SSL/TLS를 사용한다. (그리고 SSL은 TLS의 이전의 프로토콜이다.)

Certbot설치

다음의 과정을 거친다.
1. 먼저 cerbot을 설치한다.

$ add-apt-repository ppa:certbot/certbot
  1. 해당 저장소에 담긴 패키지 정보(리브스)를 확인할 수 있도록 다음과 같은 명령어로 리스트 업데이트를 한다
$ apt-get update
  1. apt-get을 이용해 cerbot을 설치한다.
apt-get install python3-certbot-nginx
  1. 설치된 certbot을 이용하여 도메인(ex. example.com) 에 대한 SSL 인증서만 발급받는다.
$ certbot certonly --nginx -d example.com

4번 과정중에 도메일 관리자의 이메일 주소를 입력하라고 하는데 그냥 입력해준다. (그냥 만료일에 대한 정보를 주는 것이다.) 그 다음 약관에 대한 동의를 (A)/(C)를 묻는데 동의에 해당하는 (A)를 입력해야한다. 마지막으로 EFF재단과 이메일을 공유할지 묻는 부분이 있는데 이건 마음에 따라 하면된다. 나는 No했다.

  1. 그다음 다음 경로에서 5개의 파일(4개의 .pem, 1개의 readme)이 생성되었는지 확인한다.
    ( 실제로 이파일들은 /etc/letsencrypt/live/[도메인주소]에 대한 심볼릭 링크이다.)
$ ls -al /etc/letsencrypt/live/example.com
total 12
drwxr-xr-x 2 root root 4096 Aug 21 23:03 .
drwx------ 3 root root 4096 Aug 21 23:03 ..
-rw-r--r-- 1 root root  692 Aug 21 23:03 README
lrwxrwxrwx 1 root root   41 Aug 21 23:03 cert.pem -> ../../archive/example.com/cert1.pem
lrwxrwxrwx 1 root root   42 Aug 21 23:03 chain.pem -> ../../archive/example.com/chain1.pem
lrwxrwxrwx 1 root root   46 Aug 21 23:03 fullchain.pem -> ../../archive/example.com/fullchain1.pem
lrwxrwxrwx 1 root root   44 Aug 21 23:03 privkey.pem -> ../../archive/example.com/privkey1.pem

추가. 90일마다 만료되는 인증서 자동 갱신하기

$ sudo certbot renew --dry-run

Nginx 설정 파일 수정

인증서 발급까지 잘 완료했다면 다음으로 https://도메인 주소를 '땅' 쳤을 때 spring boot 서비스로 접속할 수 있도록 nginx의 설정파일을 수정해야한다.

그 전에 nginx의 기본 파일과 폴더들에 대해서 간략하게 알아보자

Nginx의 기본 폴더, 파일

  • /ets/nginx/nginx.conf
    Nginx에 관련한 설정파일로 Nginx 설정에 관한 블록들이 작성되어 있다. 이 파일에서 sites-enabled 폴더에 있는 파일들을 include하여 파일들을 가져온다.

  • /ets/nginx/sites-available
    가상 서버 환경들에 대한 설정 파일들이 위치하는 디렉토리이다. 실제 가상 서버가 돌던 안 돌던 가상 서버와 관련된 설정 파일들은 여기에 놓도록 한다.

  • /ets/nginx/sites-enabled
    sites-available에 있는 가상 서버 파일들중에서 실행시키고 싶은 파일을 symbolic link로 연결한 폴더이다. 이 폴더에 위치한 가상서버 환경 파일들을 읽어서 실제 서버를 세팅한다.

일단 nginx의 메인 설정 파일은 /etc/nginx 아래에 nginx.conf의 이름으로 존재하고 있다.
다음 명령어들을 입력해서 nginx.conf를 열어보자.

$ cd /etc/nginx
$ vi nginx.conf

nginx.conf 파일을 열어보면 여러 server{} , http{} 등 여러 설정 블록들이 있을거다. 여기서 http블록안을 보면 끝부분 즈음 다음과 같은 내용이 있을 것이다.

이 두문장은 다음과 같은 말이다.
1. /etc/nginx/conf.d 아래에 있는 모든 .conf 파일들을 inclue한다.
2. /etc/nginx/sites-enabled의 모든 파일들을 include한다.

만약 두 부분이 없으면 추가해주자.

직접 nginx.conf에서 설정 정보를 수정/추가할 수도 있지만 그보다는 기본 설정을 안 거드리면서 1번 방법을 이용하거나 2번 방법으로 가상 서버 환경 파일을 만들어 심볼릭 링크로 연결해주는 방식이 더 안전하다.

그래서 우리는 /etc/nginx/sites-availabe 아래 새로운 test.conf라는 새로운 파일과, sites-enabled 폴더에 심볼릭 링크를 만들어 sites-enabled가 test.conf를 가르키도록 할 것이다.

잠깐! symbolic link란?
링크를 연결해 원본 파일을 직접 사용하는 것과 같은 효과를 내는 링크이다. 윈도우의 바로가기와 비슷한 개념이라고 생각하면된다. 특정 폴더에 링크를 걸어 원본파일을 사용하기 위해 사용한다.
출처 : https://qjadud22.tistory.com/22


그래서 실제 설정파일들은 위와 같은 구조 될 것이다.
이제 다음의 과정들을 거쳐 최종적인 cert봇으로 제공받은 ssl인증서를 적용한 https페이지를 만들어보겠다.

1. /etc/nginx/sites-available 아래 test.conf파일을 만든다. (사실 이름은 자기 취향껏 만들면 된다.ㅋㅋ)

* example.com은 도메인주소이니 여기에는 본인의 도메인주소를 넣으면 된다.

server {
  listen 80; #80포트로 받을 때
  server_name example.com; #도메인주소, 없을경우 localhost
  return 301 https://example.com$request_uri;

}
server {
  listen 443 ssl http2;
  server_name example.com;

  # ssl 인증서 적용하기
  ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
  
  location / { # location 이후 특정 url을 처리하는 방법을 정의(여기서는 / -> 즉, 모든 request)
    proxy_pass https://localhost:8443; # Request에 대해 어디로 리다이렉트하는지 작성. 8443 -> 자신의 springboot app이사용하는 포트
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}
server {
    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


  listen 80;
  server_name example.com;
    return 404; # managed by Certbot


}

간단하게 설명을 해보자면
맨위에 서버 블럭은
80포트로 들어오는 요청 즉, http로 들어오는 모든 요청을 https로 리다이렉션을 하는 것이다.

그리고 그 바로 아래 서버 블록은 https://도메인 으로 들어온 요청에 대해 localhost 8443포트로 접속하게 해주는 것이다. 그리고 여기서 8443 포트로는 아까 말한 spring boot앱이 실행되고 있는 상태이다. 즉, 도메인이름으로 접속하면 바로 spring boot앱이 연결되도록 한 것이다.

그리고 다음 명령어를 통해서 작성한 test.conf의 문법을 확인한다.

$ sudo nginx -t

2. test.conf를 저장하고 빠져나온 뒤 sites-enabled에 심볼릭 링크를 만든다.

sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled

3. sites-enabled로 이동하여 test.conf가 추가된 것을 확인한다.

$ cd /etc/nginx/sites-enabled
$ ls -l
total 0
lrwxrwxrwx 1 root root 34 Aug 21 22:18 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 36 Aug 21 23:58 test.conf -> /etc/nginx/sites-available/test.conf

사실 여기 default.conf에 해당하는 심볼릭 링크를 지워야 test.conf가 먹힌다고 하는데 나는 삭제 안했는데도 잘 된다. 만약 안 먹힌다면 삭제해보자.

4. Nginx 재구동/재시작 -> 확인

$ sudo service nginx reload
또는
$ sudo service nginx restart

마치며

이상으로 nginx설치하는 과정부터 인증서를 발급받아 https를 적용한 spring boot앱을 배포하는 과정을 알아보았다. 나는 이상하게 ssl 인증서가 잘 안 먹혀서 400에러가 자주 떴었다. ssl인증서 발급받고 다시 .conf 적용하면서 어찌저찌 해결이 되었다.

함께 보면 좋을 참고자료
Nginx 설치부터 무료 인증서 발급까지:
https://fureweb-com.github.io/blog/2017/08/07/applying-free-ssl-to-your-ubuntu-server-using-nginx-and-let%27sencrypt-from-scratch.html
spring boot 앱 배포하기 :
https://berrrrr.github.io/programming/2021/07/18/aws-springboot-nginx-dns-ssl/
https://velog.io/@damiano1027/Nginx-Nginx와-SpringBoot-내장-Tomcat-연동
nginx 가상 서버 :
https://twpower.github.io/50-make-nginx-virtual-servers
SSL/TLS정의 :
https://www.digicert.com/kr/what-is-ssl-tls-https/
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=hai0416&logNo=221623579719

profile
여행과 tea를 좋아하는 젼

1개의 댓글

comment-user-thumbnail
2022년 10월 17일

도움이 정말 많이되었습니다!! 감사합니다 !

답글 달기