[Cloud] Baelog: Markdown 기반 정적 웹 사이트 호스팅

[Cloud] Baelog: Markdown 기반 정적 웹 사이트 호스팅


Cloud Oracle WebServer Astro

Baelog를 만들게 된 이유

  • 인스타그램은 구리고, 블로그는 못생겼고… 그래서 직접 만들었습니다.
  • 저는 일단 마크다운을 굉장히 좋아합니다. 메모도 맨날 마크다운으로 합니다. 일단 쓰기 너무 편하고, 지원하는 애플리케이션이나 플랫폼도 어어엄청나게 다양하고, 무엇보다 문서를 소유한다는 느낌이 좋아가지고…
  • 원래 그냥 오프라인에서만 쌓아놨었는데, 포트폴리오랑 이력서도 같이 올릴겸 앱을 만들게 되었습니다.
  • 그래서 만들 블로그의 조건을
    1. 마크다운 기반 포스트 (포스트 작성 로직은 없음, 상상만 해도 귀찮음!!!)
    2. DB 없는 가벼운 정적 웹 사이트
  • 로 정했습니다.

애플리케이션

Astro 공식 문서

  • 프로그램은 Astro로 작성되었습니다.
  • Docs에 개발 가이드가 친절히 나와있고, 배포 가이드 또한 잘 설명되어 있습니다.
  • 템플릿도 엄청나게 많아 가져다 써도 됩니다.
  • 파일 시스템의 .md 파일을 뿌려주기만 하면 끝

배포

  • 배포는 Oracle Cloud로 했습니다.
  • 공식 문서를 보니 S3 같은 정적 웹 호스팅을 많이 사용하는데, 저는 구성하고 싶은 시스템이 있어서 운영체제 위에 웹 서버를 돌리기로 했습니다.
  • 애플리케이션 도커화는 하지 않았습니다. 리소스가 제한적이기도 하고 너무 간단한 애플리케이션이라서요.
  • 개인 서버로 돌리고 있는 남는 노트북이 하나 있긴 한데, 좀 번거로워서 그냥 클라우드 쓰기로 했습니다.
  • AWS는 프리 티어를 다 써버려서, 새로운 계정을 만들어야 합니다.
  • 하지만 관대한 오라클은 인스턴스 두 개까지 (Arm은 네 개까지) 항상 무료…
  • 여기서 ‘항상 무료’ 계정은 무료인 리소스만 생성이 가능하기에, 신경쓰지 않아도 되는 것이 장점입니다.
  • 오라클 클라우드에서 무료로 쓸 수 있는 Arm 기반 인스턴스가 있는데, 이게 2 코어 12GB 램입니다.
  • 근데 이게 리소스가 없어서, 누가 삭제할 때까지는 생성을 못합니다. (몇 개월째 안 됨, 거의 로또임)

인스턴스 생성

  • 눈물을 머금고 1 코어 1GB 램 인스턴스를 생성했습니다.
  • 그래도 무료니까 감사하게 생각합니다.
  • 이미지는 Ubuntu 20.04로 선택했습니다.
  • 가상 네트워크, 서브넷, 인터넷 게이트웨이, 라우팅 테이블은 자동으로 생성됩니다.
  • 블록 볼륨은 인스턴스 당 100GB 까지 무료입니다.
  • 키 페어는 잘 저장해 뒀습니다.

보안 그룹 생성

  • HTTP, SSH를 위한 인바운드 트래픽을 허용했고, 모든 아웃바운드를 허용했습니다.
  • 조금 나중에 알았는데, 기본적으로 SSH는 열려있었더랬죠…
  • 오라클 클라우드에는 ‘보안 목록’과 ‘보안 그룹’이 따로 있습니다.
  • 이 중 ‘보안 목록’은 서브넷 수준에서 인/아웃바운드 트래픽을 제어하는데, 여기에서 SSH가 열려있었습니다.

인스턴스에 Reserved-IP 연결

  • 인스턴스에 고정 IP를 하나 달아뒀습니다.
  • 인스턴스가 혹시 재시작되어 IP가 바뀌면 귀찮아지니까 미리미리 달아놓았습니다.

SSH 접속

> ssh -i ~/.ssh/oracle_blog_instance.key username@public-ip
  • 프라이빗 저장소에 올려놓은 코드를 Clone 해옵니다.
  • 방법은 정리해두었습니다.

프라이빗 리포지토리 Clone하기

  • .gitignore 파일에 마크다운 형식의 모든 파일을 명시해 놓았습니다.
  • 리포지토리 용량이 500MB이기 때문에 (매우 크긴 하지만), 용량의 압박을 받기 싫어 로컬 머신에서 직접적으로 동기화할 것입니다.

rsync를 이용한 로컬-인스턴스 마크다운 파일 동기화

> rsync -avz --exclude='**/.obsidian/' --exclude='**/.DS_Store' -e 'ssh -i ~/.ssh/oracle.key' /local-machine-path/ username@public-ip:/instance-path/
  • rsync를 사용해 로컬 머신과 인스턴스의 파일 시스템을 동기화할 수 있습니다.
  • 경로 마지막에 /를 꼭 붙여야 제대로 동작합니다.
  • 매번 저 명령을 치기 번거로우니 로컬 머신에 Alias로 등록해 놓습니다.

  • 저는 Alias가 너무 좋습니다.

Nginx 설치 및 설정

  • 정적 웹 호스팅을 구성하기 위해 인스턴스에 웹 서버를 설치합니다.
> sudo apt update
> sudo apt upgrade
> sudo apt install nginx
  • Nginx 설치가 끝나면 설정을 조금 만져줘야 합니다.
> sudo vi /etc/nginx/nginx.conf
  • Astro 공식 문서에는 8080 포트를 열어뒀지만, 저는 80 포트를 열었습니다.
# nginx.conf

worker_processes  1;

events {
  worker_connections  1024;
}

http {
  server {
    listen 80;
    server_name   _;

    root   /usr/share/nginx/html;
    index  index.html index.htm;
    include /etc/nginx/mime.types;

    gzip on;
    gzip_min_length 1000;
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    error_page 404 /404.html;
    location = /404.html {
            root /usr/share/nginx/html;
            internal;
    }

    location / {
            try_files $uri $uri/index.html =404;
    }
  }
}
  • Nginx를 다시 시작하고, 자동 시작을 활성화한 후 상태를 확인합니다.
> sudo systemctl restart nginx
> sudo systemctl enable nginx
> sudo systemctl status nginx
  • netstat 명령어로 80 포트에서 리스닝하고 있는 지 확인합니다.
> netstat -tln | grep 80
  • 각 플래그는 다음을 의미합니다.
    • -t: TCP 프로토콜에 대한 정보를 보여줍니다.
    • -l: 리스닝 상태인 소켓들만 보여줍니다.
    • -n: 주소를 숫자 형태로 보여줍니다. (호스트명을 확인하지 않음)
  • iptables를 사용해 방화벽 규칙을 추가합니다.
> sudo iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
  • 각 플래그는 다음을 의미합니다.
    • -I INPUT 1: 입력 체인의 첫 번째 규칙으로 삽입합니다. 즉, 기존의 모든 규칙보다 우선시됩니다.
    • -p tcp: TCP 프로토콜을 사용하는 트래픽에 대한 규칙을 지정합니다.
    • --dport 80: 목적지 포트가 80인 트래픽에 대한 규칙을 지정합니다. (즉, HTTP 트래픽)
    • -j ACCEPT: 해당 트래픽을 허용합니다.

인스턴스에 Node.js 설치

  • Node.js를 리눅스 환경에 설치하려면 NVM(Node Version Manager)를 다운로드 받아야 합니다.

최신 버전 확인

  • NVM을 활성화 시킨 후 설치 가능한 Node.js 버전을 확인합니다.
> . ~/.nvm/nvm.sh
> nvm ls-remote
  • 사용할 Node.js 버전을 설치합니다.
  • 설치 옵션은 여러가지가 있습니다.
# 1. 가장 최신 LTS 설치
> nvm install --lts

# 2. 가장 최신 버전 설치
> nvm install

# 3. 버전을 직접 지정해 설치
> nvm install 18.0.7
  • 설치한 Node.js 버전을 확인합니다.
> node -v

애플리케이션 빌드

  • 쉘 스크립트를 미리 작성해두었습니다.
  • 애플리케이션을 빌드한 후 생기는 dist 디렉토리 안의 파일(Distribution 파일)들을 Nginx의 기본 문서 루트 디렉토리로 복사하는 스크립트입니다.
# build.sh

#! /bin/bash

cd /home/ubuntu/astrofy

echo "Building the project..."
npm run build

if [ $? -eq 0 ]; then
  echo "Build successful. Deploying to web server..."

  sudo rm -rf /usr/share/nginx/html/*

  sudo cp -R dist/* /usr/share/nginx/html/

  echo "Deployment successful. Files are copied to /usr/share/nginx/html."
else
  echo "Build failed. No files were copied."
fi
  • 스크립트를 실행해 빌드합니다.
> . /home/ubuntu/astrofy/build.sh
  • 매번 포스트에 변경이 생길 때마다 SSH 접속해서 이 스크립트를 실행하는 것은 너무 끔찍한 일이기 때문에 이것 또한 로컬 머신에 Alias로 등록해 둡니다.
  • 로컬 머신에서 인스턴스로 명령을 전달하는 Alias를 다음과 같이 등록했습니다.
# .zshrc

alias baelog-build="ssh -i ~/.ssh/oracle.key username@public-ip 'bash /instance-path/build.sh';"

도메인 연결

  • 가비아에서 “baelog.site” 도메인을 2,090원에 구매했습니다.

  • A 레코드로 도메인과 IP를 1:1 매핑했습니다.
  • 서브 도메인 없이 @로 설정했습니다.
  • DNS 레코드가 캐시되는 시간을 1,800초로 설정했습니다.
© 2024 Seungwon Bae 🇰🇷