S-HOOK 운영 서버 설정기

shook·2023년 8월 14일
0

우아한테크코스 백엔드 크루 베로입니다 👾

드디어 S-HOOK 도 개발 서버를 벗어나 운영 환경에서 실행하기 위해 운영 서버를 설정하게 되었습니다.

운영 서버를 설정하며 겪은 트러블 슈팅 과정과 함께 설정 과정을 기록해보았습니다.

서버 기본 설정

서비스 코드를 가져오기 위해 서비스 레포지토리를 clone 합니다.

git clone https://github.com/woowacourse-teams/2023-shook.git

저희가 설정한 커스텀 로그 저장을 위해 새롭게 /etc/log 디렉터리를 생성해주었습니다. /etc/log 내부에는 app, warn, error 디렉터리를 추가해두었습니다.

nginx 설정

nginx 를 설치합니다.

sudo apt-get install nginx

Certbot 설정

SSL 인증서 발급을 위해 Certbot 을 설치합니다.

sudo apt-get install certbot python3-certbot-nginx

S-HOOK 의 도메인을 연결할 때 www 호스트도 연결해주기 위해 여러 개의 도메인 인증서 발급을 위한 명령어를 입력합니다.

sudo certbot --nginx -d s-hook.com -d www.s-hook.com

그런데 에러가 발생했습니다... 🔨

가비아 서브 도메인 오기입

문제는 가비아 서브 도메인을 잘못 설정했기 때문이었습니다.

기존에는 CNAME 으로 호스트 이름에 dev, 값에 s-hook.com 으로 해두었는데, 기존 s-hook.com 개발 서버로 연결되었습니다. CNAME 의 값에 도메인 이름을 넣으면, 기존 도메인으로 리다이렉트 해주는 듯 합니다.

다행히 해결 방법은 쉬웠습니다!
A 레코드로 호스트 이름에 새로운 서브도메인으로 사용할 prefix를 작성하고 (ex. dev) 값에 새로운 운영 서버 ip 를 작성해주면 됩니다.

그렇게 다시 도메인 등록을 시도해보았지만, 또 다시 도메인을 등록할 수 없다는 에러가 발생했습니다.

개발 서버 도메인 인증서 삭제

운영 서버가 없을 당시, 개발 서버가 s-hook.com 도메인을 사용하고 있었습니다. 이제 운영 서버가 생겼으니 s-hook.com 도메인은 운영 서버로 옮겨져야 합니다.

기존에 개발 서버에서 s-hook.com 을 사용하고 있었기 때문에 s-hook.com 을 사용하기 위해서는 개발 서버의 인증서를 삭제해야 합니다.

certbot delete --cert-name s-hook.com 로 기존 도메인을 삭제했습니다.

혼동을 피하기 위해 nginx default 파일 (/etc/nginx/sites-enabled) 에서 certbot 이 작성한 코드를 삭제해줍니다.

도메인이 없어진 개발 서버에는 개발 서브 도메인을 새롭게 연결해주었습니다.

프론트엔드 .env.production 파일에서는 서버의 URL 을 global로 관리하고 있습니다. 개발 서버의 도메인 이름이 변경되었으므로, 개발 서버의 frontend 하위의 파일들을 재빌드해줍니다.

sudo npm ci
sudo npm run build

이렇게 하면 개발 도메인 주소로 접근하면 개발 서버로 연결되어 잘 접속할 수 있습니다.

다시 운영 서버 인증서 발급

이제 운영 서버에서 s-hook.com 도메인을 사용할 수 있게 되었습니다! 다음과 같이 운영 서버에서 새롭게 인증서를 발급받습니다.

sudo certbot --nginx -d s-hook.com www.s-hook.com

여기까지 진행하면 certbot 이 nginx 파일을 변경해줍니다.

nginx -t
sudo service nginx restart

서브 모듈 설정

S-HOOK 은 민감한 환경 변수 값들을 보호하기 위해 서브 모듈을 사용합니다.

그러나 서버에 아무 설정도 하지 않으면 운영 서버에서 서브 모듈을 pull 받아올 수 없습니다. 서브모듈은 private 레포이기 때문입니다.

따라서 운영 서버에도 서브 모듈을 사용하려면 SSH 설정을 해주어야 합니다!

다음과 같이 ssh 키를 생성해줍니다.

ssh-keygen -t rsa

생성된 ssh key를 서브모듈 레포지토리 owner 의 SSH Key 에 넣어주면 됩니다.

새롭게 서브모듈을 등록하는 것이기 때문에 init 을 해주어야 합니다.

git submodule init
git submodule update

여기까지 했는데 갑자기 Username 을 적으라고 하더니 에러가 발생했습니다.

아무리 Username 과 Password 를 쳐도 소용 없습니다.
처음 레포지토리를 clone 해올 때 남아있는 캐시가 있는 모양입니다.

다시 서브모듈을 등록하기 위해 서브 모듈 디렉터리를 삭제하고, 캐시도 지워줍니다.

rm -rf shook-security/
git rm -r --cached shook-security

삭제 후, Git Submodule 을 다시 clone 받았습니다.
clone 에 사용하는 url은 SSH 주소로 받아와야 합니다.

프론트엔드 npm 설정

이제 프론트엔드 파일을 빌드해주어야 하는데, npm 이 없어서 sudo apt-get install npm 을 해주었습니다.

순탄하게 설치될 줄 알았지만... npm 설치 후, frontend 파일들을 build 했더니 EC2 인스턴스가 멈출 뻔했습니다. 아예 서버 접속이 안 되는 문제가 발생했어요.

10분 정도 기다리니 접속은 됐는데, npm build를 하느라 메모리를 다 쓰고 있었습니다. 🔨🔨🔨

npm --version 명령어가 10분이나 걸리다니. 충격적입니다.

스왑 메모리 설정

빌드할 때 메모리가 부족하니, 스왑 메모리를 설정해주었습니다.

sudo fallocate -l 4G /swapfile # 스왑 메모리의 크기는 4G 로 설정합니다. 
sudo chmod 600 /swapfile # 읽기 / 쓰기 권한을 소유자에게 부여합니다.
sudo mkswap /swapfile  # swapfile 설정
sudo swapon /swapfile # swap 메모리 켜기

npm, node 버전 이슈

메모리가 부족하지는 않으니 frontend 파일들을 다시 build 했습니다. 그런데 npm 버전이 낮아 버전 오류가 주루룩 발생했습니다.

잘못 다운로드된 버전의 npm 을 삭제하고 LTS npm 을 설치합니다.

sudo apt-get remove npm
sudo apt-get install npm

node 버전이 안 맞아서 node 버전 업그레이드도 해주었습니다.

sudo n lts  # 노드 최신 버전 업그레이드
hash -r # 캐시 삭제

frontend 파일들이 있는 곳에서 sudo npm install 을 입력하니 잘 설치되었습니다!

Frontend 파일 빌드

운영 서버 /frontend/.env.env.production 파일에 API 를 요청할 운영 서버 도메인 이름을 적어준 뒤, frontend 파일들을 빌드합니다.

sudo npm ci
sudo npm run build

여기까지 진행하면 S-HOOK 서비스도 운영 서버에서 whitelabel이 아닌 서비스 화면을 볼 수 있습니다 😂

Java 설치

backend 배포만 하면 완성입니다.
nohup java -jar... 를 실행하는데 Java 가 없는 걸 발견했습니다.

즉시 설치해주겠습니다. 🔨🔨🔨🔨

wget -O- [https://apt.corretto.aws/corretto.key](https://apt.corretto.aws/corretto.key) | sudo apt-key add -  
 sudo add-apt-repository ‘deb [https://apt.corretto.aws](https://apt.corretto.aws/) stable main’

sudo apt-get install -y java-17-amazon-corretto-jdk

백엔드 배포를 했더니 에러가 발생했습니다!!
에러가 발생한다는 건 jar 파일이 잘 실행되었다는 뜻입니다.
드디어 ㅠㅠㅠ

발생한 에러가 슬랙으로 알림이 잘 오는 것도 확인했습니다.

에러가 발생한 이유는 운영 DB 를 제대로 설정해주지 않았기 때문입니다.

이제 운영 DB를 설정해보겠습니다!

운영 DB 설정하기

pem 키 옮기기

DB 서버는 private ip 만 존재하기 때문에 운영 서버에서만 접근할 수 있습니다.
그래서 로컬에 있는 운영 서버 pem 키를 운영 서버로 전송했습니다.

bad permission 에러를 막기 위해 pem key 에 권한을 부여해주었습니다.

chmod 400 2023-shook.pem

파일을 전송합니다!

scp -i pem키이름 전송할파일 호스트@운영서버ip:~

이제 운영 서버에서 DB 서버로 접속할 수 있습니다. 👍

ssh -i pem키이름 호스트@DB서버ip

MySQL 설치

S-HOOK은 운영 서버 DB로 MySQL 을 사용할 것이므로 MySQL 을 설치해주었습니다.

sudo apt-get update
sudo apt-get install mysql-server

MySQL 을 설치하고

sudo systemctl start mysql

MySQL 에 잘 접속할 수 있었습니다.

sudo /usr/bin/mysql -u root -p

저희 팀은 root 사용자 대신 새로운 사용자를 등록하기로 정했기 때문에, MySQL 에 새로운 사용자를 추가해주겠습니다.

MySQL 사용자 추가

새로운 사용자를 추가하기 위해서는 다음과 같이 설정해주면 됩니다.

create user 사용자이름@운영서버ip identified by '비밀번호';

만약 설정하다가 잘못된 유저를 만든 경우 (그게 바로 우리) 잘못 만든 유저를 삭제해줍니다.

drop user '사용자이름'@'호스트';

사용자를 만든 뒤에, 권한을 설정해주어야 합니다.
모든 권한을 주려면 아래와 같이 설정합니다.

grant all privileges on *.* to '사용자이름'@'호스트';
flush privileges;

데이터베이스 생성

운영 서버에서 사용할 데이터베이스를 생성해줍니다.

create database 데이터베이스이름;

현재 운영 서버에는 sql.init=always 설정이 되어 있기 때문에 data.sql 파일을 삭제했습니다.
개발용으로 사용하던 더미 데이터가 운영 DB에 올라가면 안 되기 때문입니다.

운영 서버 설정 이후에는 sql.init 설정은 사용하지 않을 예정입니다.

bind-address 설정

DB 로 들어오는 외부 접속을 허용해주기 위해 /etc/mysql/mysql.conf.dmysqld.cnf 파일에서 bind-address 를 수정해줍니다.

설정 파일을 수정한 뒤, mysql 을 재시작합니다.

sudo systemctl restart mysql

백엔드 배포

log 디렉터리 권한 에러

다시 배포 스크립트를 사용해서 배포를 시작했는데, etc/log 디렉터리에 권한 에러가 발생했습니다. 🥲

로그와 관련된 모든 디렉터리에 권한을 할당해주었습니다.

sudo chmod 775 etc/
sudo chmod 777 app
sudo chmod 777 error
sudo chmod 777 warn

권한 설정을 해주니 권한 에러는 더 이상 발생하지 않았습니다.
그런데 중간 중간 로그 파일을 보다 보니 뭔가 이상합니다.
지금은 오후 9시인데 로그 파일은 오후 12시입니다.

그렇습니다. 서버 시간 설정을 까먹었습니다.

서버 시간 설정하기

서버 시간을 서울 시간대로 변경해주었습니다.

sudo timedatectl set-timezone Asia/Seoul

배포 완료!

드디어 백엔드 서버까지 잘 배포되었습니다!

장장 3시간 동안 운영서버를 배포해 보았습니다.

profile
S-HOOK 🎧 의 팀 블로그 입니다

1개의 댓글

comment-user-thumbnail
2023년 8월 14일

유익한 자료 감사합니다.

답글 달기

관련 채용 정보