본문 바로가기
프론트엔드

AWS + Next.js + Nginx 대환장 파티 경험하기(2)

반응형

안녕하세요. 죽지 않고 돌아온 메리입니다.

저번에 AWS EC2를 사용해서 Next.js를 배포하는 방법을 포스팅했는데요. 엄청난 스샷 때문에 힘들었습니다.

그래도 포스팅을 하면 뿌듯하고, 리마인드가 된 것 같아 조금 더 똑똑해진 제 모습이 마음에 듭니다. (뿌듯)

 

오늘은 두가지에 대한 포스팅을 추가적으로 써보려고 합니다.

1. Github Actions 를 사용해서 배포 자동화 시키기  

2. 가비아로 구매한 호스팅 연결하기 


1. Github Actions 를 사용해서 배포 자동화 시키기

1-1. 기존 설정 수정

이전 포스팅에서 Nginx를 사용해서 배포할 때 index.html을 연결해 주느라 next export로 정적 파일을 생성해 주었는데요.

여러 블로그를 참고하는 과정에서 이해가 안 가는 부분이 있어서 아래와 같이 수정해 주었습니다. 

 

이전에 만들어두었던 Nginx설정 파일 /etc/nginx/sites-available 경로에서

여러분이 만들어두었던 conf 파일을 아래와 같이 수정해 줍니다. 

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        location / {
                proxy_pass http://127.0.0.1:3000;
                proxy_set_header Host $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;
        }
}

 

Nginx로 들어오는 요청을 http://127.0.0.1:3000 경로로 포트포워딩  시키는 방식입니다. 

그리고 깃허브에서 클론 받은 디렉터리 위치로 이동후 npm start를 실행시켜주고, 탄력적 IP로 확인해 보시길 바랍니다.

 

여기까지는 이해가 됐는데, npm이 정지되면 Nginx에 올라간 것도 동시에 정지되는 어처구니없는 일이 발생하였습니다.

→ 사실 이쪽이 이해가 잘 안되서 이전 포스팅에서 정적으로 배포했습니다(당당✌)

 

다시 구글 검색을 하다가, PM2(Process Manager)라는 것을 발견했습니다. 

무중단 배포를 하고자 하기에 해당 패키지를 설치해 주었습니다. 

 

PM2란

더보기

Node.js 애플리케이션을 쉽게 관리할 수 있게 해주는 Process Manager로 원활한 서버 운영을 위한 패키지입니다. 

대표적으로 아래와 같은 기능을 제공합니다.

 

1. 서비스를 제공하고 있는 도중 갑자기 서버가 중지돼도 서버를 다시 켜준다. 

2. Node는 싱글 스레드 기반이지만, 멀티 코어 또는 하이퍼 스레딩을 사용할 수 있게 해 준다.

3. 클라이언트로 요청이 올 때 알아서 로드밸런싱을 해준다. 

 

기타 등등..

 

1-2. PM2 설정

//pm2를 전역에 설치
sudo npm install -g pm2
pm2 start npm --name "여러분이넣고싶은이름" -- start --prefix "깃허브경로"

 

위의 사진과 동일하게 정상실행 되었다면 Nginx를 재실행시켜줍니다. 

sudo systemctl restart nginx

 

PM2 명령어 ❗❗

//pm2 시작
pm2 start "설정한이름"

//pm2 목록
pm2 list

//pm2 중단
pm2 stop "리스트에서확인한id" | "설정한이름"

//pm2 삭제
pm2 delete "리스트에서확인한id" | "설정한이름"

//pm2 로그확인
pm2 logs "설정한이름"

 

1-3. Github Actions 구성

Github Actions을 구성하기 전에 SSH 키를 생성해 줍니다. 

 

SSH란 

더보기

네트워크 상의 다른 컴퓨터에 로그인하거나 원격 시스템에서 명령을 실행하고

다른 시스템으로 파일을 복사할 수 있도록 해주는 응용 프로그램 또는 프로토콜을 가리킵니다. 

우선 SSH 키가 있는지 확인합니다.

//SSH 키 확인
ls -al ~/.ssh

 

저는 위의 사진과 같이 생성된 키가 없으니 키를 생성하고 권한을 줍니다. 

//SSH 키 생성
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

//권한 설정
chmod 600 ~/.ssh/id_rsa

 

키를 생성하고 다시 ls -al ~/.ssh 명령어를 입력하면 아까와는 다르게 키가 생성되어 있는 것을 확인하실 수 있습니다. 

 

그럼 생성된 키를 Github에 추가해 줍니다. 

//생성된 키 출력
cat ~/.ssh/id_rsa.pub

 

출력된 키를 복사합니다. 

깃허브 Settings > SSH and GPG keys로 이동합니다. 

 

새로운 SSH key를 생성해 줍니다. 

 

성공적으로 SSH key를 생성했으면, 

깃허브 레포지토리로 이동한 후  Settings > Secrets and variables > Actions로 이동합니다. 

 

아래 사진처럼 레포지토리 시크릿키를 생성해 줍니다.

  • EC2_HOST : EC2 인스턴스의 퍼블릭 IP 주소
  • EC2_KEY : EC2 인스턴스에 액세스 할 수 있는 개인 SSH 키
  • EC2_USER : EC2 인스턴스의 사용자 이름 (= ubuntu)

※ EC2 인스턴스에 액세스 할 수 있는 개인 SSH 키란 인스턴스를 처음 생성할 때 발급받은 키페어입니다. 

메모장으로 열어보시면 아래 형식과 같은 키를 확인할 수 있는데요. 이것을 복사 붙여 넣으시면 됩니다.

(BEGIN RSA PRIVATE KEY , END RSA PRIVATE KEY 이 부분도 모두 붙여 넣어주세요!)

 

레포지토리 시크릿 키를 모두 생성했으면 워크플로우를 생성합니다. 

깃허브 레포지토리로 이동해 Actions > set up workflow yourself를 클릭해 새로운 워크플로우를 생성합니다.

 

name: Deploy

on:
  push:
    branches:
      - master 
jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Set up SSH agent
      uses: webfactory/ssh-agent@v0.6.0
      with:
        ssh-private-key: ${{ secrets.EC2_KEY }}

    - name: Deploy to EC2
      uses: appleboy/ssh-action@v0.1.2
      with:
        key: ${{ secrets.EC2_KEY }}
        username: ${{ secrets.EC2_USER }}
        host: ${{ secrets.EC2_HOST }}
        port: 22
        script: |
          cd /home/ubuntu/여러분레포지토리
          git fetch origin
          git status
          git pull
          npm run build
          pm2 restart 아까설정한PM2이름

 

 

1-4. SSH 설정 

워크플로우를 저장했다면, sshd_config 설정을 변경합니다.

sudo vim /etc/ssh/sshd_config
PubkeyAuthentication yes 
PubkeyAcceptedKeyTypes=+ssh-rsa

 

ESC + :wq!로 저장해 주었다면 SSH를 재실행해줍니다.

sudo systemctl restart ssh

 

다음으로 기존에 클론 받았던 레포지토리를 HTTPS > SSH로 변경합니다.

아래 이미지를 참고해서 원격 저장소를 변경해 주세요. 

git remote -v

git remote set-url origin git@github.com:사용자이름/레파지토리명.git

 

SSH 에이전트에 키를 추가하고 연결테스트를 해봅니다. 

//SSH 에이전트에 키 추가
eval "$(ssh-agent -s)"
//Github와 SSH 연결 테스트
ssh -T git@github.com

 

성공적으로 연결이 되면 위의 사진과 같은 메시지가 나타납니다. 

여기까지 되셨다면 아무거나 master 브랜치에 커밋 후 워크플로우가 정상 실행 되는지 확인해 봅니다.

정상 실행 되었다면 탄력적 IP로 들어가 수정사항이 반영되었는지도 확인해 주세요!


1-5. 에러발생

ssh.ParsePrivateKey: ssh: no key found (Github Actions workflow에서 발생)  / ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain  (Github Actions workflow에서 발생)

: Github Actions 레파지토리 시크릿 키 중 개인 SSH 키를 잘못 설정함 (인스턴스를 생성할 때 발급받은 키페어. pem 키 값을 넣어줘야 함)

 

The authenticity of host 'ec2- compute.amazonaws.com' can't be established. ED25519 key fingerprint is SHA256. This key is not known by any other names.

: EC2 인스턴스에 수동으로 SSH 접속해 줌

ssh -i ~/.ssh/id_rsa ubuntu@퍼블릭 IPv4 DNS

The authenticity of host '주소' can't be established.
ED25519 key fingerprint is SHA256:키값.
Are you sure you want to continue connecting (yes/no)?

yes

 

✅ Warning: Permanently added 'github.com' (ED25519) to the list of known hosts. 내 깃허브이메일: Permission denied (publickey).

: 깃허브와 SSH가 연결 안 됨

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
//SSH 디버깅 모드 사용
ssh -vT git@github.com

2. 가비아로 구매한 도메인 연결

저는 이전에 에디님이 구매해 두신 도메인이 있어서 서브도메인으로 연결해 두었습니다. 

DNS 설정은 아래와 같이 진행했습니다. 

  • 타입: A
  • 호스트: 원하는 서브도메인
  • 값/위치: 인스턴스의 퍼블릭 IPv4 주소
  • TTL: 1800

그리고 Nginx설정파일에 server_name을 추가해 주었습니다. 

 

이전에 만들어두었던 Nginx설정 파일 /etc/nginx/sites-available 경로에서

여러분이 만들어두었던 conf 파일을 아래와 같이 수정해 줍니다. 

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        server_name test.codedream.co.kr; //구매한 도매인

        location / {
                proxy_pass http://127.0.0.1:3000;
                proxy_set_header Host $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;
        }
}

 

수정 후 Nginx를 재시작해줍니다.

sudo systemctl restart nginx


2-1. 에러발생

DNS_PROBE_FINISHED_NXDOMAIN (크롬에서 발생)

: 브라우저 내 캐시가 업데이트되지 않음

 

크롬 DNS_Probe_Finished_NXDomain 해결 방법

크롬(Chrome)에서 웹 서핑 도중 "사이트에 연결할 수 없음 - DNS_PROBE_FINISHED_N...

blog.naver.com

 

HTTP에서만 작동 (크롬에서 발생)

: Nginx에 SSL 인증서가 설정되지 않아 HTTPS로 연결이 안 되는 문제

 

//Certbot 설치(Let's Encrypt 인증서 발급 도구)
sudo apt update
sudo apt install certbot python3-certbot-nginx

//test.codedream.co.kr 도메인에 대한 SSL 인증서를 발급
sudo certbot --nginx -d test.codedream.co.kr -d

//이메일 입력하고
//Y
//Y

 

위의 사진과 같은 메시지가 뜬다면 성공적으로 SSL 인증서를 발급받았습니다. 

저희가 발급받은 인증서는 90일 동안 유효합니다. 

 

다음으로 Nginx 설정 파일을 변경해 줍니다. 

test.codedream.co.kr이라고 쓰여있는 부분을 특정 도메인으로 변경해 주세요!

server {
    listen 80;
    listen [::]:80;
    server_name test.codedream.co.kr;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name test.codedream.co.kr;

    ssl_certificate /etc/letsencrypt/live/test.codedream.co.kr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.codedream.co.kr/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $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;
    }
}

 

설정 파일을 수정 후 Nginx를 재실행하면, https에서도 정상작동하는 것을 확인할 수 있습니다.

sudo systemctl restart nginx

 

Let's Encrypt SSL 인증서를 자동 갱신하고 싶다면 아래 명령어를 참고해 주세요.

sudo certbot renew --dry-run

어쩌다 보니 시작한 공부가 여기까지 오게 될 줄을 생각도 못했습니다. 

이제 인스턴스를 중단하고, 다시 Vercel로 옮길 거지만 재밌는 경험이 된 것 같습니다.(Vercel 최고👍)

 

그리고 여러 블로그를 참고하면서 알게 된 것들이 참 많습니다. gpt의 도움도 아주 많이 받았고요.

 

실제로 gpt에게 이렇게 물어봤습니다. 처음에는 뭐라고 물어봐야 할지도 몰랐습니다. 

이렇게 질문하기까지 많은 자료들을 봤고, 테스트도 여러 번 하면서 엄청난 시행착오가 있었습니다.

역시 사람은 뭐라도 알아야 해! 우하하!

 

저희는 스터디를 통해 글을 기록하고 있습니다. 피드백은 언제나 환영입니다 :)

 

 

반응형