들어가며

Photo by Jan Antonin Kolar on Unsplash

웹서버가 제 기능을 하기 위해서는 DB도 필요하다. 서버에 mysql을 설치해서 nodejs서버에서 통신하는 것까지 해보려고 한다.

 

Mysql 설치

아래 명령어로 mysql server를 설치한다. - [1]

$ sudo yum install mysql-server

설치되었으면 systemctl을 이용해서 실행한다. 추가로 enable으로 서버가 재시작될 때 실행되도록 한다.

$ sudo systemctl start mysqld
$ sudo systemctl enable mysqld

mysql에 접속하기 전에 root 계정 설정을 해주어야 한다. 아래 명령어로 설정한다.

$ mysql_secure_installation

원하는 옵션으로 선택해서 비밀번호를 만든다. 설정한 비밀번호로 mysql에 접속한다.

$mysql -u root -p
Enter password:

비밀번호를 입력하면 mysql에 접속된다. 간단한 select문으로 테스트해본다.

mysql> select "Hello World!";
+--------------+
| Hello World! |
+--------------+
| Hello World! |
+--------------+
1 row in set (0.00 sec)

 

외부 접속 계정 생성

root 계정으로는 localhost에서만 접속이 가능하다. 새로운 계정을 생성해서 권한을 준다. - [2]

mysql> create user '<username>'@'%' identified by '<password>';
mysql> grant all privileges on *.* to '<username>'@'%';
mysql> flush privileges;

grant *.* 명령어를 이용해 모든 DB의 권한을 주었다. 특정 DB로 한정하기 위해서는 <DBname>.* 으로 줄 수도 있다.

외부에서 접근하기 위해 3306 포트를 열어준다.

$ sudo firewall-cmd --permanent --add-port=3306/tcp
$ sudo firewall-cmd --reload

reload 명령어로 방화벽을 적용하면 외부에서 접근이 가능하다. 

나는 Sequal Ace를 통해 접속했다. host에 도메인을 입력하고 username과 password를 맞게 입력하면 연결할 수 있다.

 

Mysql 테스트 프로젝트

mysql 연결 테스트를 위한 간단한 프로젝트를 만들 것이다. 우선 Mysql에 테스트용 DB를 생성한다.

mysql> CREATE DATABASE test;
mysql> USE test;
mysql> CREATE TABLE `message` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `message` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
mysql> INSERT INTO message (message) VALUES ("Hello World!");

message 테이블을 만들고 Hello World! 데이터를 추가한다. 실제로는 Sequel pro 상에서 진행한다.

 

이제 node 프로젝트를 생성한다.

$ mkdir node-mysql-test
$ cd node-mysql-test
$ node -v
v18.2.0
$ npm init

노드 버전을 확인하고 npm init으로 새로운 프로젝트를 초기화한다.

 

mysql을 연결하기 위해서는 연결 정보가 필요한데, git에 올릴 수 없으므로 따로 db_config.json 파일을 만들어 저장한다.

{
	"host": "xivnick.me",
	"user": "<username>",
	"password": "<password>",
	"database": "test"
}

host는 역시 도메인이고, 해당하는 user와 password를 입력한다. json포맷이므로 마지막 줄에 ,(쉼표)를 넣지 않도록 주의한다.

 

이제 db 처리를 담당할 db.js를 생성한다.

const mysql = require('mysql2/promise');
const db_config = require('./db_config.json');

const queryFormat = (query, values) => {
	if (!values) return query;
	return query.replace(/:(\w+)/g, (txt, key) => {
  		if (Object.prototype.hasOwnProperty.call(values, key)) {
   			return mysql.escape(values[key]);
  		}
  		return txt;
	});
}

const pool = mysql.createPool({
	host: db_config.host,
	user: db_config.user,
	password: db_config.password,
	database: db_config.database,
	queryFormat,
});

module.exports = {
	pool,
};

db.js에서는 mysql 모듈을 가져와 pool을 생성해 반환한다.

queryFormat은 sql injection을 방지하기 위한 escape 코드이다. 이번 프로젝트에서 사용하지는 않지만 추가했다. - [3]

db_config에서 설정을 가져와 createPool의 파라미터를 입력한다. db_config는 같은 폴더에 있도록 구성했다.

 

db 구성이 준비되었으니 서버의 메인 파일 index.js를 작성한다.

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

const DB = require('./db');

app.get('/', async (req, res) => {

	const [ messages ] = await DB.pool.query('SELECT * FROM message');

	return res.send(messages);
});

app.listen(port, () => {
  console.log(`Node Mysql Test app listening on port ${port}`);
});

루트로 접근하면 DB에서 select 쿼리를 수행해 리턴해주는 서버 코드다.

포트가 3000으로 이전 프로젝트와 같으면 실행할 수 없으므로 환경변수에서 PORT를 가져와주고, 없다면 그대로 3000으로 실행한다.

$ npm i express mysql2
$ node index.js
Node Mysql Test app listening on port 3000

npm으로 필요한 모듈을 설치하고 서버를 실행한다. 따로 환경변수를 설정하지 않았기 때문에 3000번 포트로 실행된다.

[{"id":1,"message":"Hello World!"}]

localhost:3000으로 접속하면 위 결과를 얻을 수 있다.

 

Git 설정하기

프로젝트를 서버로 옮기기 위해 git에 올린다. git에 올리지 않을 파일들을 .gitignore 파일에 추가한다.

node_modules/
db_config.json

기존에도 추가했던 node_modules/ 외에 password가 저장되어 있는 DB 설정 파일도 git에서 제외한다.

 

github에서 레포지토리를 생성한다. 안내 문구에 따라 다음 명령어를 실행한다.

$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin git@github.com:xivnick/node-mysql-test.git
$ git push -u origin main

ssh로 서버에 접속해서 클론한다.

$ git clone git@github.com:xivnick/node-mysql-test.git

git에서 다운로드한 파일에는 db_config가 빠져 있으므로 파일을 생성해준다.

$ cd node-mysql-test
$ vi db_config

config 파일은 위에서 작성한 것과 같이 작성한다.

{
	"host": "xivnick.me",
	"user": "<username>",
	"password": "<password>",
	"database": "test"
}

아래 명령어로 필요한 모듈도 설치해 준다.

$ npm install

실행하더라도 기본 port가 겹칠뿐더러, 방화벽도 닫혀있기 때문에 서비스를 만들어서 실행하도록 하자.

 

시스템 서비스 설정

시스템 서비스 파일을 만들어준다. - [4]

$ vi node-mysql-test.service

해당 파일은 이전과 비슷하게 적어 주되, PORT=3001이라는 환경 변수를 추가해준다. - [5]

[Unit]
Description=Node.js Mysql Test Project

[Service]
Environment="PORT=3001"
ExecStart=/home/xivnick/.nvm/versions/node/v18.2.0/bin/node index.js
Restart=always
User=xivnick
WorkingDirectory=/home/xivnick/node-mysql-test/

[Install]
WantedBy=multi-user.target

만든 시스템 파일을 링크해준다.

$ sudo systemctl link /home/xivnick/node-mysql-test.service
$ sudo systemctl start node-mysql-test

이제 3001번 포트에서 노드 서버가 실행된다.

 

Nginx 설정

마찬가지로 subdomain을 연결해 준다. - [6]

$ sudo vi /etc/nginx/sites-available/test2.conf

우선 sites-available에 test2 설정 파일을 만들어 아래 내용을 적는다.

server {
	listen 80;

	server_name test2.xivnick.me;

	return 301 https://$host$request_uri;	
} 

server {
    listen 443 ssl;

    server_name test2.xivnick.me;

	ssl_certificate /etc/letsencrypt/live/xivnick.me/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/xivnick.me/privkey.pem;

    location / {
        proxy_pass http://localhost:3001;
        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;
    }
}

앞서 했던 설정 파일과 큰 차이가 나지는 않는다. 서브도메인과 연결해주는 port정도의 차이가 있다.

$ sudo ln -s /etc/nginx/sites-available/test2.conf /etc/nginx/sites-enabled/test2.conf
$ sudo systemctl restart nginx

enable 폴더에 링크를 걸어주고 Nginx를 재시작한다. 이제 test2.<domain>으로 접속을 확인할 수 있다!

 

Reference

[1] https://info-lab.tistory.com/172

[2] https://velog.io/@jdk9908/외부에서-MySQL-접속하기

[3] https://github.com/mysqljs/mysql/issues/1626

[4] https://xiv-dev.tistory.com/5

[5] https://serverfault.com/questions/413397/how-to-set-environment-variable-in-systemd-service

[6] https://xiv-dev.tistory.com/6 

 

 

들어가며

Photo by Markus Winkler on Unsplash

이전 글에서 만든 서버에 접속하면 보안 안됨 경고가 뜨는데, 이는 http 연결을 사용하고 있기 때문이다. 이번 글에서는 Let's encrypt를 이용하여 https 연결을 구축하려고 한다.

 

Let's encrypt 인증서 설치

인증서 발급을 위해 certbot을 설치해야 한다. - [1]

$ sudo yum install epel-release
$ sudo yum install certbot

 

epel 저장소를 추가한 후 certbot을 설치해 준다.

* centOS9에서는 yum으로 certbot을 설치할 수 없다. 대신 snap을 이용할 수 있다. - [2]

* 여기서는 그냥 centOS8로 다운그레이드하고 새로 세팅했다.

와일드카드 인증을 위해 아래 명령어를 실행한다. - [3]

$ sudo certbot certonly --manual -d *.xivnick.me -d xivnick.me --preferred-challenges dns

*.xivnick.me와 xivnick.me 도메인을 등록하는데, 소유 인증 방식은 dns를 이용하겠다는 뜻이다.

(와일드카드 인증을 위해서는 dns 추가만 가능한데, 이 경우에는 자동 갱신이 되지 않으니 주의한다.)

이메일을 입력하고 동의를 두 번 누르고 나면 아래와 같은 메시지가 뜬다.

Please deploy a DNS TXT record under the name:

_acme-challenge.xivnick.me.

with the following value:

n74WNHAG1oGRtyCvLOTk1S0Y45O0p83jDDVhGmXdkYo

DNS 설정에서 _acme-challenge에 코드를 추가하여야 한다. Vultr로 연결해 두었으므로 Vultr에서 설정한다.

VULTR : Product - DNS - xivnick.me

이때 하나 더 추가해야 하기 때문에 TTL을 짧게 설정하는 것이 좋다. 기본인 3600으로 설정하면 한 시간을 기다려야 갱신된다.

다시 콘솔에서 엔터를 한번 더 누르면 위 메시지가 한번 더 뜬다. 도메인을 두 개 추가하기 때문인 것 같다.

Please deploy a DNS TXT record under the name:

_acme-challenge.xivnick.me.

with the following value:

DRIBfQIve7gZna_I2tGdNhT9MH6T0j3xZl4qSNjzyxs

(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)

Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.xivnick.me.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.

추가한 후에 바로 엔터를 누르면 안 되고, 적힌 링크(https://toolbox.googleapps.com/apps/dig/)로 들어가 제대로 등록이 갱신되어 있는지 확인해야 한다.

Google 관리 콘솔 도구 상자&nbsp;Dig

두 개를 넣었기 때문에 두 개가 모두 나와야 정상이다. 하나만 뜬다면 설정한 TTL시간을 기다렸다가 다시 요청해본다.

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/xivnick.me/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/xivnick.me/privkey.pem
This certificate expires on 2022-08-31.
These files will be updated when the certificate renews.

 

두 개가 뜬 것을 확인하고 엔터를 누르면 위와 같은 결과 화면이 나오게 된다.

 

Nginx 설정하기

nginx가 ssl 설정을 사용하고, http로 들어온 요청을 https로 리다이렉트 해주기 위해 설정을 변경해준다.

$ sudo vi /etc/nginx/sites-available/test.conf

이전에 작성했던 test.conf를 열고 아래 내용으로 새로 작성한다.

server {
	listen 80;

	server_name test.xivnick.me;

	return 301 https://$host$request_uri;	
} 

server {
        listen 443 ssl;

        server_name test.xivnick.me;

	ssl_certificate /etc/letsencrypt/live/xivnick.me/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/xivnick.me/privkey.pem;

        location / {
                proxy_pass http://localhost: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;
        }
}

80 포트로 들어온 요청은 https로 리다이렉트 하고, 443으로 들어온 요청은 아까 만들어진 pem key를 통해 인증한 후 nodejs 서버로 proxy pass 해준다.

$ sudo systemctl restart nginx

nginx를 재시작해주면 test.xivnick.me로 접속했을 때 https로 연결된다!

 

인증서 갱신 준비

와일드카드를 위한 DNS인증의 경우 자동 갱신을 할 수 없다. (certbot이 DNS인증이 불가능하기 때문)

때문에 시기에 맞춰서 갱신을 해주어야 한다. certificates를 이용하면 인증 기간을 확인할 수 있다.

$ sudo certbot certificates
$ sudo certbot certonly --manual -d *.xivnick.me -d xivnick.me --preferred-challenges dns

 

인증 명령어를 다시 입력하면 갱신할 수 있다.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Certificate not yet due for renewal

You have an existing certificate that has exactly the same domains or certificate name you requested and isn't close to expiry.
(ref: /etc/letsencrypt/renewal/xivnick.me.conf)

What would you like to do?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Keep the existing certificate for now
2: Renew & replace the certificate (may be subject to CA rate limits)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

지금은 위처럼 renewal 기간이 아니라고 하고, 2를 선택하면 갱신이 되는 것 같다.

Let's Encrypt는 3개월마다 갱신이 필요하니까, 시기를 잘 맞추도록 하자.

필요하다면 네이버 클라우드 플랫폼 등에 등록하여 알림을 받을 수 있다. - [4]

 

Reference

[1] https://jootc.com/p/201901062488

[2] https://www.linuxcapable.com/ko/how-to-install-apache-on-centos-9-stream/

[3] https://oasisfores.com/letsencrypt-wildcard-ssl-certificate/

[4] https://bboggi.com/entry/linux-CentOS-78에-무료SSL-인증서-Lets-encrypt-발급-및-설치

 

들어가며

Photo by Let's go Together on&nbsp; Unsplash

이전 글에서 IP주소와 port로 서버에 접속할 수 있게 되었다. 하지만 12자리의 IP주소는 외우기 어렵고, port 또한 좋지 않기 때문에 도메인을 구입해 연결하고 nginx를 이용하여 subdomain으로 원하는 port에 연결해보도록 하자.

 

도메인 연결하기

우선 사용할 도메인을 구입한다. 나는 가비아에서 구입했다. 

 

웹을 넘어 클라우드로. 가비아

그룹웨어부터 멀티클라우드까지 하나의 클라우드 허브

www.gabia.com

hosting.kr 같은 선택지도 있고, 연습용이라면 freenom에서 무료 도메인을 임시로 할당받을 수도 있다.

가비아에서 도메인을 구입할 때 vultr에 연결하기 위해 네임서버를 ns1.vultr.com, ns2.vultr.com으로 등록한다. - [1]

Vultr에서 Product-DNS 탭으로 들어가 새 도메인을 추가한다.

VULTR : Products - DNS - New Domain

이때 아래에 등록된 인스턴스의 IP를 선택해서 추가할 수 있다.

네임서버 업데이트에 시간이 좀 걸리기 때문에, 잠시 기다리면 <domain>:3000으로 접속해서 Hello World를 확인할 수 있다.

도메인이 연결되었기 때문에 이제 ssh 접속도 도메인을 통해 가능하다.

 

Nginx 서버 설정하기

먼저 서버에 nginx를 설치한다. nginx를 설치하기 위해서는 yum repo를 등록해야 한다.

$ sudo vi /etc/yum.repos.d/nginx.repo

nginx.repo를 생성하고 아래 내용을 입력한다. - [2]

[nginx]
name=nginx repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

파일을 저장하고 yum을 이용해 nginx를 설치한다.

$ sudo yum install nginx
$ nginx -v
nginx version: nginx/1.22.0

nginx 버전은 CentOS 버전에 따라 달라질 수 있다. CentOS8을 사용할 경우 1.14 버전이 설치되었다.

nginx 설정은 /etc/nginx/nginx.conf에서 확인할 수 있다.

$ cat /etc/nginx/nginx.conf

방화벽 포트를 열고 nginx를 실행한다.

$ sudo firewall-cmd --permanent --zone=public --add-service=http
$ sudo firewall-cmd --permanent --zone=public --add-service=https
$ sudo firewall-cmd --reload
$ sudo systemctl start nginx

 여는 김에 https 포트도 함께 열고 reload 했다. systemctl을 이용해 nginx를 실행한다.

xivnick.me로 접속하면 nginx 기본 페이지가 뜬다!

 

서브도메인 연결하기

이제 서브도메인을 이용하여 test.xivnick.me를 3000 포트를 듣고 있는 nodejs 서버로 연결해 줄 것이다. 이를 위해 nginx에 서버 설정을 추가해서 proxy pass를 해주어야 한다.

nginx에 서버 설정을 추가하는 방법은 여러가지가 있다.

  1. /etc/nginx/nginx.conf 파일에 직접 추가
  2. /etc/nginx/conf.d 폴더에 .conf파일 추가
  3. 새로운 폴더에 .conf파일 추가하고 nginx.conf에서 Include 하기

1,2번이 더 간단하지만, 확장성을 위해 여기서는 3번을 이용할 것이다. 주로 sites-available과 sites-enabled 폴더를 생성하여 available에 설정 파일을 보관하고, enabled에 링크로 연결하여 nginx.conf에서는 enabled만 include 하는 방식을 사용한다.

nginx server block 튜토리얼을 참고하여 폴더를 생성하고 설정 파일을 만든다. - [3]

$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
$ sudo vi /etc/nginx/sites-available/test.conf

위 명령어로 폴더를 생성하고 파일을 연다. test.conf에는 proxy pass를 위한 설정 파일을 작성한다. - [4]

server {
        listen 80;

        server_name test.xivnick.me;

        location / {
                proxy_pass http://localhost: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;
        }
}

test.xivnick.me로 들어오는 요청을 localhost:3000으로 연결해주는 설정 파일이다.

test.xivnick.me 부분은 원하는 <subdomain>.<domain>형태로 적으면 된다.

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

만든 test.conf의 링크를 enabled 폴더에 생성한 후 nginx.conf의 http 블록 마지막에 아래 코드를 추가해준다. - [3]

include /etc/nginx/sites-enabled/*.conf;
server_names_hash_bucket_size 64;

기존에 conf.d 폴더에 있는 .conf파일을 include 한 것처럼 sites-enabled의 .conf파일들도 include 하는 코드이다.

두 번째 줄은 도메인을 늘렸기 때문에 네임 해시를 늘리는 코드라고 한다. (레퍼런스 참조)

$ sudo systemctl restart nginx

위 명령어로 nginx를 재시작하면 test.xivnick.me로 접속해서 nodejs의 Hello World! 를 확인할 수 있다!

 

이제 3000번 포트는 사용하지 않으니 다시 닫아준다. - [5]

$ sudo firewall-cmd --permanent --remove-port=3000/tcp
$ sudo firewall-cmd --reload

reload로 재시작하면 이제 3000 포트는 닫히고 test.xivnick.me로만 접속할 수 있게 된다.

 

IP 접속도 도메인으로 redirect 하기

포트를 닫고 나니 IP로 접속했을 때도 도메인으로 넘겨주고 싶어서 추가로 작성한다.

$ sudo vi /etc/nginx/conf.d/redirect-ip.conf

이번에는 한 서버에 해당하는 내용은 아니라서 conf.d 폴더 내에 설정 파일을 추가했다.

server {
	listen 80;

	server_name <Server-IP>;
	return 301 $scheme://xivnick.me$request_uri;
}

 

서버 아이피로 들어온 요청을 301을 이용하여 xivnick.me로 넘겨주는 설정 파일이다. - [6]

$ sudo systemctl restart nginx

위 명령어로 nginx를 재시작하면 ip로 접속했을때 xivnick.me로 redirecting 되는 것을 확인할 수 있다.

 

Reference

[1] https://www.vultr.com/docs/introduction-to-vultr-dns

[2] https://www.nginx.com/resources/wiki/start/topics/tutorials/install/

[3] https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-on-centos-7

[4] https://velog.io/@iamsupercool/Nginx-proxy-pass-설정

[5] https://uxgjs.tistory.com/162

[6] https://memorynotfound.com/nginx-redirect-ip-address-domain-name/

 

들어가며

Photo by Vladislav Klapin on Unsplash

서버에 뭐라도 올려놔야 서버가 잘 작동하는지 알 수 있으니 테스트 프로젝트를 하나 올리기로 한다.

테스트 프로젝트를 올리는 것도 잘 정리해놔야 나중에 신생 프로젝트를 올릴 때 도움이 될 것이다.

코드를 서버에 직접 작성하기보다는 Github을 이용해서 확장성을 높인다.

 

프로젝트 만들기

node.js로 간단한 Hello World 프로젝트를 작성한다.

node가 설치되어 있지 않다면 nvm을 이용해 설치하도록 한다. 여기서는 작성일 기준 최신 버전인 18.2.0 버전을 사용했다.

$ node -v
v18.2.0
$ npm init

npm init 명령어를 이용해 node 프로젝트에 필요한 package.json을 생성한다. 생성 과정에서 입력한 파일 명(기본 index.js)을 기억해야 한다.

 

express 서버 생성하기

웹 서버를 만들기 위해 express를 이용한다. 우선 express를 설치한다. - [1]

$ npm i express

위 명령어를 이용해 express를 설치할 수 있다. i는 install의 줄임말이며, --save를 생략하더라도 저장된다.

이제 express starter를 참고하여 index.js에 Hello World 예제를 작성한다. - [2]

const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
})

3000 포트에서 루트에 요청이 들어오면 Hello World!를 반환하는 예제이다.

다음 명령어를 이용하여 서버를 실행해볼 수 있다.

$ node index.js
Example app listening on port 3000

실행중인 서버는 localhost:3000으로 접속해서 확인해 볼 수 있다.

 

추가로 Git 세팅 전에 빌드 파일들을 제외하기 위해 .gitignore파일을 생성한다.

node_modules/

위와 같이 작성하면 node_modules 폴더를 git에서 추적하지 않는다.

 

Github 연결하기

코드를 만들었으니 Github에 연결할 차례다. 다른 git 서비스들을 사용할 수도 있다.

 

GitHub: Where the world builds software

GitHub is where over 83 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat...

github.com

Github에 로그인해서 레포지토리를 생성한다.

아무것도 없이 레포지토리를 생성하면 새 깃을 설정하는 방법이 나온다. 참고해서 명령어를 입력한다.

$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin git@github.com:xivnick/node-hello-world.git
$ git push -u origin main

위 명령어를 순차적으로 입력하면 모든 파일을 추가해서 커밋하고, 커밋한 내용을 origin에 Push 할 수 있다.

 

서버에 Git 연결하기

이제 github에 업로드한 코드들을 서버에서 다운받아야 한다. 저번 글에서처럼 ssh를 이용해 서버에 접속한다.

$ ssh <username>@<server-ip>
<username>@<server-ip>'s password: <password>

저번 게시글을 따라 user를 생성했다면 user home에 위치해 있을 것이다. 여기서 프로젝트마다 폴더를 만들어 관리하도록 한다.

이제 git에서 클론하려고하면.. git이 없다고 뜬다. 서버에도 git을 설치해준다.

$ sudo yum install git

추가로 ssh 연결을 위해서는 ssh 설정을 해주어야 한다. (http로 연결할 것이라면 넘어가도 좋다.)

아래 명령어를 통해 개인키-공개키 쌍을 만든 후 공개키를 복사한다. - [3]

$ ssh-keygen -t ed25519 -C "sample@email.com"
$ cat ~/.ssh/id_ed25519.pub

이때 sample@email.com 부분을 본인의 이메일로 설정하면 된다. 생성 시에 비밀번호를 물어보는데, 비워둘 수도 있고 적당한 비밀번호를 설정할 수도 있다.

복사한 공개키를 github에 등록한다.

github : settings - ssh keys - add new

원하는 이름을 입력하고 key 부분에 공개키를 붙여 넣은 뒤 add ssh key버튼을 이용하여 등록한다.

이제 git clone을 할 준비가 완료되었다.

$ git clone git@github.com:<username>/<repository-name>.git

위 명령어를 통해 git clone을 진행한다. git 주소는 github에서 복사해오면 된다.

$ cd <repository-name>
$ ls
index.js  package.json  package-lock.json

파일이 잘 복사된 것을 확인할 수 있다.

 

서버에 node 설치 및 실행

서버에는 node가 없기 때문에 nvm을 이용해 설치해 준다. nvm을 설치하고, node를 설치한다. - [4]

$ wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash
$ source ~/.bashrc

$ nvm install 18.2.0
$ node -v
v18.2.0

로컬과 맞추기 위해 18.2.0 버전을 설치했다. node -v를 통해 확인해준다.

$ npm install
$ node index.js
Example app listening on port 3000

npm install으로 필요한 모듈을 설치하고 로컬에서와 같이 node index.js를 실행하면 서버가 실행된다. - 하지만 접속되지는 않는다. CentOS가 방화벽으로 막아놓았기 때문이다.

 

방화벽에서 포트 허용하기

firewall-cmd를 이용하여 방화벽에 3000포트를 열어준다. - [5]

$ sudo firewall-cmd --permanent --add-port=3000/tcp
$ sudo firewall-cmd --reload

reload를 이용해 재시작해주면 설정이 적용된다. 다시 서버를 실행해본다.

$ node index.js
Example app listening on port 3000

이제 <server-ip>:3000으로 접속하면 Hello World! 페이지를 볼 수 있다.

 

서비스 등록하기

위처럼 node를 실행하면 연결을 끊었을 때 서버도 종료되게 된다. 항시 연결을 유지하고 있을 수는 없으므로 백그라운드에서 실행할 방법이 필요하다. nohup이나 pm2등의 방법이 있지만, 여기서는 system service를 이용해 실행하려고 한다.

$ which node
~/.nvm/versions/node/v18.2.0/bin/node

첫 번째로, 사용하는 노드의 위치를 확인한다. nvm으로 설치하였기 때문에 위와 같이 위치하고 있다.

위 정보를 활용하여 node-hello-world.service 파일을 작성한다.

[Unit]
Description=Node.js Hello World App

[Service]
ExecStart=/home/xivnick/.nvm/versions/node/v18.2.0/bin/node index.js
Restart=always
User=xivnick
WorkingDirectory=/home/xivnick/node-hello-world/

[Install]
WantedBy=multi-user.target

위 서비스로는 User가 WorkingDirectory에서 ExecStart를 실행하는 것과 같은 효과를 준다.

만든 서비스 파일을 systemctl에 등록한다.

$ sudo systemctl link /home/xivnick/node-hello-world.service

 

CentOS에는 SELinux가 켜져 있어서 보안적으로 막혀있는 파일들이 있어 에러가 난다.

아래 명령어를 이용해 SELinux를 종료해 준다. - [7]

$ sudo setenforce 0

이제 start를 이용하여 백그라운드에서 실행할 수 있다.

$ sudo systemctl start node-hello-world

이제 터미널을 종료해도 서버가 돌아가게 된다.

 

Reference

[1] https://expressjs.com/ko/starter/installing.html

[2] https://expressjs.com/ko/starter/hello-world.html

[3] https://www.lainyzine.com/ko/article/creating-ssh-key-for-github/

[4] https://firework-ham.tistory.com/35

[5] https://uxgjs.tistory.com/162

[6] https://fred16157.github.io/node.js/nodejs-linux-add-systemd-service/

[7] https://www.oss.kr/info_install/show/b0d63b55-ec8f-4038-bf38-3d9602f062b1

들어가며

Photo by Wilhelm Gunkel on Unsplash

초기화를 몇 번째 하는지 모르겠다. 그런데 원래 공부는 이름 쌓기처럼 A-AB-ABC-ABCD-... 순서로 해야 하는 걸지도 모른다.

그래서 다시 시작하는 A 파트는 초기화 및 기본 세팅입니다.

 

VULTR 서버 초기화

서버는 VULTR 서비스를 사용한다.

 

SSD VPS Servers, Cloud Servers and Cloud Hosting by Vultr

Vultr Global Cloud Hosting - Brilliantly Fast SSD VPS Cloud Servers. 100% KVM Virtualization

www.vultr.com

회사에서는 주로 AWS를 사용하는 만큼 AWS와 VULTR 중 고민을 많이 했는데, 좀 더 순수한 서버를 하나 다뤄보는 것이 나을 것 같아 VULTR를 계속 사용하기로 했다.

1 vCPU, 1GB Memory, 25GB SSD 옵션의 서버에 CentOS9를 얹어 사용하고 있다.

* 수정 : certbot 설치를 위해 CentOS8로 변경하였다.

 

서버 호스트명 변경

개인 서버로 쓰기 위해서 기존에 사용하던 호스트명을 xiv-server로 변경하기로 했다.

서버 호스트명을 바꾸면 Reinstall도 자동으로 진행되니 따로 초기화할 필요는 없어 보인다.

VULTR : Settings - Change Hostname

변경할 Hostname을 입력하고 Reinstall 버튼을 누르면 경고문이 뜨고, 동의 후 진행하면 재설치가 진행된다.

VULTR 내의 서버 라벨이 바뀌지는 않기 때문에 서버 라벨을 눌러 라벨도 변경해 주었다.

 

서버 접속 및 SSH 설정

VULTR에서 콘솔 창을 제공하긴 하지만 Terminal 상에서 작업하는 것이 편하기 때문에 ssh 설정을 해준다.

VULTR : Overview

Overview 화면에서 IP주소와 username, password를 확인할 수 있다. 아마 username은 root일 것이다.

터미널에 아래 명령어를 입력하여 접속해 준다.

$ ssh root@<Server-IP>
root@<Server-IP>'s password: <password>

비밀번호를 입력하라고 하면 Overview화면에서 복사해온 password를 이용한다.

 

Trouble Shooting : 

여기서 나는 기존에 있던 서버에 연결했던 기록이 남아 있어 RSA 공유키 충돌이 일어나 Warning이 발생했다.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

아래 코드를 이용하여 기존에 있던 기록을 초기화할 수 있다 - [1]

$ ssh-keygen -R <Server-IP>

이후 다시 접속해보면 정상적으로 접속되는 것을 확인할 수 있다.

 

관리자 계정 생성

root를 그대로 사용하는 것은 비밀번호를 외우기도 어려울 뿐더러 보안적인 문제가 발생할 수 있다.

서버 관리에 사용할 새 계정을 생성한다.

# useradd <username>
# passwd <username>
Changing password for user <username>.
New password: <password>
Retype new password: <password>

위 명령어를 이용해 새로운 계정을 생성하고 비밀번호를 설정한다. - [2]

 

관리자 그룹 등록

생성한 계정을 관리자로 등록해야 sudo를 사용할 수 있다.

visudo로 직접 관리자 등록을 해 주는 방법과, 관리자 그룹인 wheel에 추가하는 방법이 있는데 여기서는 후자를 이용한다.

# usermod -a -G wheel <username>

위 명령어로 해당 계정을 관리자 그룹에 추가할 수 있다. - [3]

 

SSH 접속 테스트

생성한 관리자 계정으로 SSH 접속을 테스트해보자.

Ctrl + D를 눌러 연결을 끊거나 새로운 Terminal 창을 열어 다시 연결한다.

$ ssh <username>@<server-ip>
<username>@<server-ip>'s password: <password>

정상적으로 연결되는 것을 확인할 수 있다.

 

Reference

[1] https://cpuu.postype.com/post/30065

[2] https://ksr930.tistory.com/119

[3] https://jjig810906.tistory.com/61

들어가며

Photo by  Aubrey Odom-Mabey  on  Unsplash

내 서버 마련의 꿈 카테고리를 신설했다. 사실 별건 아니고 그냥 개인 서버 관리하는 글을 게시할 공간이다.

기본 설정 하는 부분들을 기록하여 추후에 찾아볼 수 있도록 하려고 한다.

 

P.S. 언젠가는 다들 자기 집이나 자기 PC처럼 자기 서버를 하나씩 가지게 되지 않을까?

 

 

+ Recent posts