목차
개요
아직도 PHP와 Node.js를 비교해서 장단점을 설명하지는 못하겠지만 내가 직접 사용해보고 느낀 바로는 확실히 Node.js를 이용한 사이트들이 속도가 더 빠른 것 같다.
인터넷도 나날이 발전해서 사실 속도에 큰 차이는 없다고도 하다만 개인적으로는 확실히 체감이 되는 느낌이다.
웹사이트의 대부분이 PHP, 그 중에서도 워드프레스를 가장 많이 사용하지만 최근에는 Ghost로 블로그를 제작하는 것을 많이 보았다.
내가 Node.js 기반으로 제작된 NodeBB를 사용하다 보니 자연스레 Node.js로 할 수 있는 다른 것들에도 관심이 생겨 남는 VM 인스턴스에 Ghost도 설치해봤다.
평생 무료로 사용이 가능한 것이 포인트기 때문에 돈 한 푼 안 들이고 오라클 클라우드에서 SSL 자동 갱신까지 되게 할 것이다.
오라클 클라우드 VM 인스턴스 생성
다른 글들과 마찬가지로 아래 글을 따라 VM 인스턴스를 먼저 생성한다.
VM 인스턴스 생성까지가 귀찮지 그 이후는 다른 CMS에 비해 훨씬 간단했다.
참고: 오라클 클라우드 Free-Tier 계정으로 VM 인스턴스 생성
도메인 연결
다른 글들에서는 중간에 도메인을 연결했는데, Ghost에서는 미리 도메인을 연결해줘야 한다.
앞서 말한 것처럼 평생 무료가 포인트기 때문에 이번에도 freenom에서 무료 도메인을 신청한다.
도메인을 신청하고 VM 인스턴스에 지정한 공용 IP를 연결해주면 된다.
개인적으로는 freenom의 DNS 설정이 조금 이상한 것 같아 Cloudflare까지 사용을 하는 것이 좋다고 생각한다.
참고: 오라클 클라우드 라이믹스&미디어위키 설치
Ghost 설치 전 준비 과정
Ghost도 설치에 필요한 것들이 있다.
다행히 MySQL을 제외한 세부 설정은 Ghost가 알아서 해준다.
VM 인스턴스 생성 과정에서 패키지의 업데이트와 업그레이드를 진행했지만 하지 않았다면 아래 명령어로 다시 진행한다.
$ sudo apt update && sudo apt -y upgrade
Ghost를 설치하기 전 4가지를 설치해야 되는데, 우선 아래 명령어로 nginx와 MySQL부터 설치를 해준다.
$ sudo apt-get install nginx
$ sudo apt-get install mysql-server
아래 명령어로 MySQL의 설정을 진행한다.
$ sudo mysql
> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '설정할비밀번호';
> quit
마지막으로 Node.js와 Ghost-CLI를 설치한다.
$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash
$ sudo apt-get install -y nodejs
$ sudo npm install ghost-cli@latest -g
Ghost 설치
우선 Ghost를 설치할 폴더를 생성해준다.
실제 사용할 주소와는 상관이 없고, 관리자 화면에 접속할 때 해당 주소를 사용해야 한다.
생성 후에는 권한을 변경하고 해당 폴더로 이동한다.
$ sudo mkdir -p /var/www/폴더이름
$ sudo chown ubuntu:ubuntu /var/www/폴더이름
$ sudo chmod 775 /var/www/폴더이름
$ cd /var/www/폴더이름
이제 바로 설치를 진행할 수 있는데, 나는 오라클 클라우드에선 항상 iptables 때문에 문제가 생겼다.
시스템이 켜질 때마다 아래 명령어를 입력해야 뭘 설치하든 정상적으로 진행된다.
$ sudo iptables -F
이제 바로 Ghost의 설치를 시작한다.
명령어를 입력하기 전 현재 폴더가 /var/www/폴더이름 폴더가 맞는지 다시 확인한다.
$ ghost install
URL → freenom에서 신청한 도메인
MySQL hostname → 엔터
MySQL username → root
MySQL password → 위에서 설정한 비밀번호
Ghost database name → 엔터
ghost MySQL user → Y
Set up NGINX → Y
Set up SSL → Y
Enter your email → 사용 중인 이메일 주소
Set up systemd → Y
Start Ghost → Y
여기까지만 진행해도 https://도메인/폴더이름 주소로 이동했을 때 Ghost 블로그가 생성된 것을 확인할 수 있다.
하지만 오라클 클라우드가 문제인 건지 www 도메인으로 이동하면 redirect가 자동으로 되지 않아 추가로 작업을 해줘야 했다.
Nginx 설정 파일 수정
아래 글을 참고해서 Editplus로 Nginx 설정 파일을 수정한다.
참고: 오라클 클라우드 라이믹스&미디어위키 설치
www 도메인에서 non-www 도메인으로의 이동이 되지 않고 있기 때문에 그 부분부터 해결을 해줘야 한다.
우선 /etc/nginx/sites-available 폴더의 도메인-ssl.conf 파일을 열고 파일의 하단에 아래 내용을 붙여넣는다.
# HTTPS www. server configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.도메인.com;
ssl_certificate /etc/letsencrypt/도메인.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/도메인.com/도메인.com.key;
include /etc/nginx/snippets/ssl-params.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
그 후 같은 폴더의 도메인.conf 파일을 열어 전체 내용을 지우고 아래 내용을 입력해준다.
# Default server configuration
server {
listen 80;
listen [::]:80;
server_name 도메인.com;
include /etc/nginx/snippets/ssl-params.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
# HTTP - CNAME Connect www.도메인.com to 도메인.com
server {
listen 80;
listen [::]:80;
server_name www.도메인.com;
include /etc/nginx/snippets/ssl-params.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
nginx 상태를 확인해보고 정상 상태라면 재시작한다.
$ sudo nginx -t
$ sudo service nginx restart
$ sudo iptables -F
자동 인증서 관리 환경 구성
여기까지 진행을 했지만 여전히 www 도메인의 접속이 불가능하다.
이 문제를 해결하기 위해 SSL 인증서를 다시 적용해야 한다.
우선 자동 인증서 관리 환경부터 구성을 한다.
$ sudo chown -R ubuntu:ubuntu /var/www/
$ mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
$ sudo touch /etc/nginx/snippets/letsencrypt.conf
$ sudo chown root:ubuntu /etc/nginx/snippets/letsencrypt.conf
$ sudo chmod 775 /etc/nginx/snippets/letsencrypt.conf
$ sudo nano /etc/nginx/snippets/letsencrypt.conf
letsencrypt.conf 파일을 열어서 아래 내용을 넣어준다.
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}
EditPlus로 /etc/nginx/sites-available 폴더 안의 Ghost 설정 파일 2개를 열어서 'include /etc/nginx/snippets/ssl-params.conf;'를 'include /etc/nginx/snippets/letsencrypt.conf;'로 변경하고 저장한다.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name 도메인.com;
root /var/www/폴더이름/system/nginx-root; # Used for acme.sh SSL verification (https://acme.sh)
ssl_certificate /etc/letsencrypt/도메인.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/도메인.com/도메인.com.key;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2369;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
# HTTPS www. server configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.도메인.com;
ssl_certificate /etc/letsencrypt/도메인.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/도메인.com/도메인.com.key;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
# Default server configuration
server {
listen 80;
listen [::]:80;
server_name 도메인.com;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
# HTTP - CNAME Connect www.도메인.com to 도메인.com
server {
listen 80;
listen [::]:80;
server_name www.도메인.com;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
그 후 nginx 상태를 확인해보고 재시작한다.
$ sudo nginx -t
$ sudo service nginx restart
$ sudo iptables -F
Let's Encrypt SSL 인증서 적용
$ wget https://dl.eff.org/certbot-auto -P /home/ubuntu/
$ chmod a+x certbot-auto
$ export LC_ALL="C"
$ sudo reboot now
재부팅하고 잠시 후에 다시 들어가서 아래 명령어로 python과 certbot을 설치한다.
$ sudo iptables -F
$ sudo apt-get update && sudo apt-get install -y certbot
$ sudo apt install certbot python3-certbot-nginx
설치 후에 아래 명령어로 Let's Encrypt SSL 인증서를 다운로드한다.
nginx의 default 파일에 한글로 작성된 주석이 있으면 utf-8 관련 오류가 나니 다시 한번 확인해보고 진행하는 것이 좋다.
$ sudo certbot --nginx -d 도메인.com -d www.도메인.com
Please choose whether HTTPS access is required or optional.
-------------------------------------------------------------------------------
1: Easy - Allow both HTTP and HTTPS access to these sites
2: Secure - Make all requests redirect to secure HTTPS access
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
위와 같이 선택하는 화면이 나오면 2번의 secure 옵션을 선택한다.
secure로 선택할 경우 사이트의 모든 페이지가 https로 연결된다.
$ sudo iptables -F
$ sudo ls -al /etc/letsencrypt/live/도메인명
아래와 같이 나오면 인증서가 제대로 적용된 것이다.
drwxr-xr-x 2 root root 4096 Feb 28 20:30 .
drwx------ 3 root root 4096 Feb 28 20:30 ..
-rw-r--r-- 1 root root 692 Feb 28 20:30 README
lrwxrwxrwx 1 root root 31 Feb 28 20:30 cert.pem -> ../../archive/도메인/cert1.pem
lrwxrwxrwx 1 root root 32 Feb 28 20:30 chain.pem -> ../../archive/도메인/chain1.pem
lrwxrwxrwx 1 root root 36 Feb 28 20:30 fullchain.pem -> ../../archive/도메인/fullchain1.pem
lrwxrwxrwx 1 root root 34 Feb 28 20:30 privkey.pem -> ../../archive/도메인/privkey1.pem
Nginx에 SSL 인증서 적용
아래의 명령어로 OpenSSL을 사용하여 dhparam을 암호화한다.
20분 정도 걸린다고 하는데 금방 끝나는 경우도 있고 더 오래 걸리기도 한다.
$ sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
다 끝나면 ssl.conf 파일의 권한을 변경해준다.
$ sudo touch /etc/nginx/snippets/ssl.conf
$ sudo chmod 777 /etc/nginx/snippets/ssl.conf
$ sudo nano /etc/nginx/snippets/ssl.conf
ssl.conf 파일을 열어 아래와 같이 입력해준다.
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_dhparam /etc/nginx/dhparam.pem;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4;
add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options "SAMEORIGIN";
수정할 수 없도록 다시 권한을 변경해준다.
$ sudo chmod 644 /etc/nginx/snippets/ssl.conf
EditPlus로 /etc/nginx/sites-available/도메인-ssl.conf 파일을 열어서 아래의 내용을 그대로 붙여넣는다.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name 도메인.com;
root /var/www/폴더이름/system/nginx-root; # Used for acme.sh SSL verification (https://acme.sh)
ssl_certificate /etc/letsencrypt/live/도메인.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/도메인.com/privkey.pem; # managed by Certbot
ssl_trusted_certificate /etc/letsencrypt/live/도메인.com/fullchain.pem;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2369;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
# HTTPS www. server configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.도메인.com;
ssl_certificate /etc/letsencrypt/live/도메인.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/도메인.com/privkey.pem; # managed by Certbot
ssl_trusted_certificate /etc/letsencrypt/live/도메인.com/fullchain.pem;
include /etc/nginx/snippets/letsencrypt.conf;
location / {
return 301 https://도메인.com$request_uri;
}
}
바꾸기로 도메인.com을 다 수정하고 nginx를 재시작한다.
$ sudo nginx -t
$ sudo service nginx restart
$ sudo iptables -F
재시작 후에 도메인으로 접속이 되지 않는다면 Ghost가 설치된 폴더로 이동해서 시작 명령어를 입력한다.
$ cd /var/www/폴더이름
$ ghost start
이제 SSL 적용과 www 도메인에서 non-www 도메인으로의 redirect 설정이 완료됐다.
SSL 인증서 자동갱신
$ sudo su
$ cd /bin
$ nano letsencrypt.sh
나노 에디터에서 letsencrypt.sh 파일에 아래 내용을 입력한다.
#!/bin/bash
sudo certbot renew
sudo service nginx restart
입력 후 실행할 수 있게 권한을 변경해준다.
$ chmod +x letsencrypt.sh
그 뒤엔 인증서가 자동으로 갱신이 되게 해줘야 한다.
$ sudo crontab -e
선택창이 뜨는데 1번 나노 에디터를 선택하고 맨 아래 쪽에 아래의 내용을 입력한다.
*을 포함한 5개의 숫자는 분/시/일/월/요일을 뜻하므로 아래 내용은 매일 새벽 4시에 갱신을 한다는 것이다.
0 4 * * * /usr/bin/letsencrypt.sh
갱신할 필요가 없다면 갱신 시도는 자동으로 종료되지만 이어지는 명령어로 인해 nginx가 재시작한다.
설정을 마치면 crontab을 활성화해야 한다.
$ sudo service cron start
아래의 명령어로 자동 갱신 테스트를 해서 Congratulations가 나오면 앞으로 SSL이 자동으로 갱신된다.
$ sudo certbot renew --dry-run
아래의 사이트에 도메인을 입력하면 보안 점수를 알려주는데, SSL 인증서 설치가 제대로 완료됐다면 A+ 등급이 나온다.
이렇게 SSL 인증서가 자동으로 갱신되는 평생 무료 Ghost 블로그의 생성이 완료됐다.