What I had in mind

Introduction

Panduan ringkas bagaimana saya setup blog saya menggunakan Ghost. Ghost ialah sebuah blogging engine, alternatif kepada Wordpress. Sebab utama saya memilih Ghost ialah; Markdown walaupun platform yang lain guna support markdown. Ghost lebih mudah digunakan dan memang fokus purely untuk blogging.

Banyak tutorial di internet sana pasal Ghost blog ni, cuma post ni sebagai guideline/nota saya. Walaupun ada One-click apps untuk install Ghost ni tapi saya lebih suka jika faham step-by-step installation/config.

Requirements

  1. Domain Name
  2. VPS Hosting (DigitalOcean)
  3. Putty
  4. Cloudflare account

Untuk hosting, saya guna $5 droplet (Ubuntu 18.10). Dalam server ni saya perlu install;

  • Node.js
  • Nginx web server
  • MySQL database server
  • Ghost

1. Digital Ocean Droplet

Spin $5 droplet (1GB RAM/25GB SSD/Ubuntu 18.10/Singapore). Dapatkan IP droplet.

Buka connection Putty SSH, masukkan IP droplet, port 22.

Add SSH private key pair yang matching dengan public key kat DO. Klik Open

Login sebagai root

Update server

apt update && apt upgrade -y

2. Install Node.js

Dari terminal dan masih sebagai root, install Node.js.

apt install nodejs -y && apt install npm -y

Check node.js version.

node --version && npm --version

3. Install Nginx

Kenapa web server Nginx? Explaination:

  • Ghost listen 127.0.0.1:2368
  • Nginx serve port 80/443.

Nginx proxy port 80/443 ke port 2368. Lebih kurang.

Dalam Nginx config, proxy_pass http://127.0.0.1:2368;

server {
    listen 80;
    listen [::]:80;
    server_name arifhazwan.com;
    
    root /var/www/arifhazwan.com/system/nginx-root;

    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:2368;

    }

    location ~ /.well-known {
        allow all;
    }

    client_max_body_size 50m;
}

Boleh check guna command netstat -plntu

netstat -plntu
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      4837/mysqld
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      3566/nginx: master
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      585/systemd-resolve
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      929/sshd
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      3566/nginx: master
tcp        0      0 127.0.0.1:2368          0.0.0.0:*               LISTEN      17823/node
tcp6       0      0 :::80                   :::*                    LISTEN      3566/nginx: master
tcp6       0      0 :::22                   :::*                    LISTEN      929/sshd
tcp6       0      0 :::443                  :::*                    LISTEN      3566/nginx: master
udp        0      0 127.0.0.53:53           0.0.0.0:*                           585/systemd-resolve

Install Nginx web server.

apt install nginx -y
systemctl status nginx
ufw allow 22,80,443/tcp
ufw enable
  1. Install Nginx
  2. Check status Nginx
  3. Add firewall rule(s)
    Jangan miss port 22, kalau tak nanti tak boleh SSH server ?
  4. Enable firewall

Check kat browser boleh access web server.

4. Install MySQL

Server version: 5.7.23-2ubuntu1 (Ubuntu)

apt install mysql-server -y
mysql -u root
select user,host,plugin from mysql.user where user='root';
  1. Install MySQL
  2. Login sebagai root
  3. auth_socket ignore password. Ghost-cli perlu root password untuk initial installation/configuration.
mysql> select user,host,plugin from mysql.user where user='root';
+------+-----------+-------------+
| user | host      | plugin      |
+------+-----------+-------------+
| root | localhost | auth_socket |
+------+-----------+-------------+
1 row in set (0.00 sec)
  1. Untuk set password root, tukar auth_socket kepada mysql_native_password. Baca MySQL 5.7 Note
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<passwd>';
mysql> select user,host,plugin from mysql.user where user='root';
+------+-----------+-----------------------+
| user | host      | plugin                |
+------+-----------+-----------------------+
| root | localhost | mysql_native_password |
+------+-----------+-----------------------+
1 row in set (0.01 sec)
  1. Exit mysql. Dalam terminal masih sebagai root, untuk secure mysql installation (remove test db, disallow login etc), type in dan follow instruction;
mysql_secure_installation

5. Install Ghost

Tadi masih lagi sebagai root di dalam terminal. Untuk nak run ghost installation, tak boleh run sebagai user root. Create normal user, assign group dalam nginx www-data dan sudo group.

  1. Add user blog
  2. Assign group sudo
  3. Assign group www-data
  4. Verify group untuk user blog
adduser blog
usermod -aG sudo blog
usermod -aG www-data blog
groups blog
blog : blog sudo www-data

Install ghost-cli guna package manager npm

npm i -g ghost-cli

Tukar ke user blog

su -l blog

Install Ghost melalui ghost-cli, sebagai normal user blog

cd /var/www
sudo mkdir arifhazwan.com
sudo chown blog:blog arifhazwan.com/
sudo chmod 775 arifhazwan.com/
cd arifhazwan.com/
ghost install
  1. Tukar directory ke /var/www
  2. Buat folder untuk Ghost
  3. Tukar ownership folder blog
  4. Assign permission untuk blog
  5. Tukar directory ke folder Ghost akan diinstall.
  6. Install Ghost.

Enter your blog URL: http://arifhazwan.com
Enter your MySQL hostname: localhost
Enter your MySQL username: root
Enter your MySQL password: [hidden]
Enter your Ghost database name: blog_prod
Do you wish to set up "ghost" mysql user? Yes
Do you wish to set up Nginx? Yes
Do you wish to set up SSL? No
Do you wish to set up Systemd? Yes

Tak perlu setup SSL sebab akan guna TLS certificate dari Cloudflare untuk install dalam server.

6. Cloudflare

Sign up account baru, add site, point A record ke droplet IP.
Cloudflare akan bagi nameserver yang perlu ditukar di domain registrar.

AWS Amazon Route 53

Check Ghost blog yang baru di browser;

6.1 SSL

Generate TLS certificate untuk server. Dari Cloudflare Dashboard, pilih Crypto.

Tukar kepada Full (Strict)

Full SSL (Strict): A secure connection between your visitor and Cloudflare, plus a secure and authenticated connection between Cloudflare and your web server.

  • Authenticated Origin Pulls ON
  • Automatic HTTPS Rewrites ON

Blog dah ada SSL percuma. Issued to sni.cloudflaressl.com

Nginx configuration arifhazwan.com.conf.

add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options nosniff;
proxy_cache_path /home/blog/nginx/cache levels=1:2 keys_zone=blog_cache:10m max_size=2048m;

server {
        listen 80;                                   #Listen on IPv4
        listen [::]:80 ipv6only=on;                  #Listen on IPv6
        server_name www.arifhazwan.com arifhazwan.com;
        return 301 https://$host$request_uri; #Redirect HTTP to HTTPS
}

# HTTPS — redirects www to non-www
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name www.arifhazwan.com;

    ssl_certificate /home/blog/cert/arifhazwan.com.pem;
    ssl_certificate_key /home/blog/cert/arifhazwan.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    return 301 https://arifhazwan.com$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name arifhazwan.com www.arifhazwan.com;
    root /var/www/arifhazwan.com/system/nginx-root;

    # set max upload size
    fastcgi_buffers 64 4K;

    access_log /var/log/nginx/acess-blog.log combined;
    error_log /var/log/nginx/error-blog.log debug;

    ssl_certificate /home/blog/cert/arifhazwan.com.pem;
    ssl_certificate_key /home/blog/cert/arifhazwan.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;

    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_set_header    X-NginX-Proxy       true;
        proxy_pass http://127.0.0.1:2368;
        proxy_cache blog_cache;
        proxy_cache_revalidate on;
        proxy_cache_min_uses 3;
        proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
        proxy_pass_header   X-CSRF-TOKEN;
        proxy_buffering on;
        proxy_redirect off;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        proxy_cache_bypass $http_upgrade;
    }

    gzip on;
    gzip_types text/css image/jpg image/jpeg image/png image/gif image/svg;

     location ~ ^/\.well-known {
        root /var/www/arifhazwan.com;
        allow all;
    }
    client_max_body_size 10m;
}

7. Setup Ghost Admin

Akhir sekali, setup admin di https://arifhazwan.com/ghost

TLDR; One-click apps yang Digital Ocean sediakan untuk install Ghost.

img-1540183029.jpg