Ubuntu Node.js 및 Ghost 설치 매뉴얼

Ubuntu 서버에서 NVM으로 Node.js를 설치하고 Ghost 블로그를 배포하는 절차입니다. Node.js와 Ghost의 지원 버전은 바뀔 수 있으므로 실제 설치 시 Ghost 공식 요구 사항을 확인하십시오.

1. 준비 사항

  • Ubuntu 서버에 sudo 권한이 있는 일반 사용자로 접속합니다. Ghost 설치를 root 사용자로 직접 실행하지 않습니다.
  • 도메인의 DNS가 서버를 가리키도록 설정합니다.
  • Ghost에서 사용할 MySQL 데이터베이스와 전용 계정을 준비합니다. 데이터베이스 서버의 원격 접속 허용 범위도 함께 제한합니다.
  • 웹 서비스용 TCP 80/443 포트를 클라우드 및 서버 방화벽에서 허용합니다.

2. NVM 및 Node.js 설치

NVM은 사용자별로 Node.js 버전을 관리하므로 시스템 전역 설치보다 버전 전환이 쉽습니다. 설치 스크립트를 실행하기 전에 공식 NVM 프로젝트의 최신 설치 안내와 버전을 확인하십시오.

sudo apt update
sudo apt install -y curl build-essential
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc

NVM이 인식되는지 확인합니다.

nvm --version

Ghost가 요구하는 Node.js 버전을 공식 호환성 안내에서 확인한 뒤 설치합니다. 다음은 특정 버전의 예이며, 해당 버전이 현재 Ghost 릴리스와 호환되는지 확인해야 합니다.

nvm install 22.23.1
nvm use 22.23.1
nvm alias default 22.23.1
node --version
npm --version

NVM으로 설치한 Node.js는 해당 Unix 사용자 환경에 적용됩니다. Ghost 명령을 실행하는 사용자와 서비스 실행 환경이 Node.js 경로를 사용할 수 있도록 하고, 버전 변경 뒤에는 Ghost 서비스 동작을 확인합니다.

3. Ghost 설치 사용자 및 디렉터리 준비

Ghost 운영 전용 사용자 계정을 만듭니다. 원본 메모에서는 해당 사용자에 sudo 권한을 부여했지만, 상시 운영 계정에 불필요한 관리자 권한을 부여하지 말고 설치에 필요한 권한만 관리하십시오. Ghost-CLI가 시스템 설정을 위해 sudo를 요구하는 단계에서는 신뢰할 수 있는 관리자 계정으로 승인합니다.

sudo adduser ghostuser

Ghost-CLI를 실행할 계정으로 전환합니다.

sudo -iu ghostuser

사용자 계정에서 Node.js/NVM을 사용할 수 있는지 확인하고 Ghost-CLI를 설치합니다.

node --version
npm install -g ghost-cli@latest

Ghost 설치 디렉터리를 만들고 소유권을 설정합니다.

sudo mkdir -p /var/www/appsworld
sudo chown ghostuser:ghostuser /var/www/appsworld
cd /var/www/appsworld

appsworld는 예시 디렉터리 이름입니다. 실제 서비스 도메인이나 앱 이름에 맞게 바꾸십시오. /home/ghostuser 권한을 무조건 넓히는 방식(chmod 755)은 사용하지 말고, 필요한 디렉터리만 최소 권한으로 설정합니다.

4. Ghost 설치

설치 프로그램을 시작합니다.

ghost install

대화형 설정에서는 다음 항목을 입력합니다.

  • 블로그 URL: https://<도메인>
  • MySQL 호스트: 데이터베이스 서버 주소 또는 localhost
  • MySQL 사용자명 및 비밀번호: Ghost 전용 계정 정보
  • Ghost 데이터베이스 이름
  • Nginx 설정: 해당 서버에서 Nginx를 사용하는 경우 활성화
  • SSL 설정: 도메인 DNS와 외부 80/443 연결이 준비된 경우 활성화
  • Systemd 및 서비스 시작: 서버에서 상시 운영하는 경우 활성화

실제 비밀번호를 문서, 셸 기록 또는 공개 저장소에 남기지 마십시오. 별도의 안전한 비밀 저장 수단을 사용합니다.

설치 후 상태 확인:

ghost doctor
ghost ls
sudo systemctl status ghost_<사이트_이름> --no-pager

Ghost-CLI가 생성하는 서비스 이름은 설치된 사이트 이름에 따라 다릅니다. 실제 이름은 ghost ls 또는 다음 명령으로 확인합니다.

systemctl list-units 'ghost*' --all

5. HTTPS 설정 및 인증서 갱신

Ghost-CLI 설치 과정에서 SSL 설정이 실패하면 먼저 오류 메시지에 나온 조건을 해결합니다. acme.sh의 자동 갱신 작업을 설정하려면 cron이 필요할 수 있습니다.

sudo apt update
sudo apt install -y cron
sudo systemctl enable --now cron

그런 다음 Ghost 디렉터리에서 SSL 설정을 다시 시도합니다.

ghost setup ssl

cron 없이 강제로 설치를 진행하는 옵션은 자동 갱신이 설정되지 않을 수 있으므로 일반적인 해결책으로 사용하지 마십시오. 인증서 발급 뒤 자동 갱신 작업과 인증서 갱신 테스트 방법을 확인하십시오.

Ghost-CLI의 Nginx/SSL 자동 설정을 사용하지 않고 별도로 관리하는 경우에는 별도의 Ubuntu 설치 매뉴얼에 있는 Certbot 절차를 사용합니다. 동일한 도메인의 인증서와 Nginx 설정을 두 방식에서 중복 관리하지 않도록 주의합니다.

6. 문제 해결

Ghost와 Node.js 버전 호환 오류

오류에 설치된 Node.js 버전과 Ghost가 요구하는 범위가 함께 표시되면, Ghost가 지원하는 Node.js 버전을 NVM으로 설치하고 사용한 뒤 설치를 다시 진행합니다.

nvm install <지원되는_Node.js_버전>
nvm use <지원되는_Node.js_버전>
node --version

이미 생성된 서비스가 계속 이전 Node.js 경로를 사용하는지 확인하고, 버전을 변경한 경우 서비스를 재시작한 뒤 로그를 살펴봅니다.

MySQL Access denied 오류

오류에 표시된 MySQL 사용자와 접속 호스트를 확인한 뒤 다음을 점검합니다.

  1. Ghost 설정에 입력한 데이터베이스 이름과 사용자명이 올바른지 확인합니다.
  2. MySQL 계정의 host가 Ghost 서버의 실제 접속 주소를 허용하는지 확인합니다.
  3. 해당 사용자에게 Ghost 데이터베이스 권한이 부여됐는지 확인합니다.
  4. 원격 MySQL이라면 서버의 bind 주소, TCP 3306 방화벽 규칙 및 클라우드 보안 규칙을 확인합니다.
  5. 비밀번호가 맞는지 확인하고, 필요한 경우 안전한 방법으로 비밀번호를 재설정합니다.

서비스 로그:

sudo journalctl -u <Ghost_서비스_이름> -n 100 --no-pager

애플리케이션 로그:

ls -lt ~/.ghost/logs/

SSL 설치 실패 또는 자동 갱신 실패

  • DNS가 서버의 공인 IP를 가리키는지 확인합니다.
  • 클라우드와 서버 방화벽에서 TCP 80/443이 허용됐는지 확인합니다.
  • cron 서비스가 실행 중인지 확인합니다.
  • Ghost-CLI와 ACME 도구가 출력한 구체적인 오류와 로그를 확인합니다.
  • 인증서 발급 도구가 자동 갱신 예약을 완료했는지 확인합니다.

설치 진단

ghost doctor
sudo systemctl --failed
sudo journalctl -u <Ghost_서비스_이름> -n 100 --no-pager

원본 메모의 IP 주소, 이메일, 계정 및 비밀번호는 환경별 값이므로 이 매뉴얼에서는 사용하지 않습니다. 배포 시 실제 값은 서버의 안전한 설정 위치에 입력하십시오.