Tôi đã setup blog này thế nào?
6 min read

Tôi đã setup blog này thế nào?

Today is a good day to be a ghostwriter

Chuẩn bị

  • Digital Oceans
  • Cloudflare
  • Docker, docker-compose
  • Một chút Linux knowledge

Trong bài viết này mình sẽ trình bày cách setup 1 blog nhỏ dựa trên nền mã nguồn mở Ghost với chi phí chỉ 5$/tháng. Giới thiệu thêm về Ghost: đây là một hệ thống CMS được phát triển bằng NodeJS từ năm 2013. Ghost đã được cộng đồng đánh giá cao về độ tiện dụng cũng như thiết kế hiện đại. Điều đặc biệt, Ghost có tốc độ nhanh hơn, bảo mật hơn, thiết kế phù hợp để SEO, marketing qua hệ thống Subscription, Membership... Tham khảo thêm về dự án nếu các bạn cảm thấy hứng thú: https://github.com/TryGhost/Ghost

Dưới đây mình sẽ chia sẻ quá trình 5 bước để có thể dựng thành công 1 ghost blog hoàn toàn bằng Docker.

Bước 1: Chuẩn bị Digital Oceans và CloudFlare Account

Để cài đặt được ghost blog đầu tiên chúng ta phải có hosting, domain. Mình sử dụng Digital Oceans(DO) làm hosting cho blog này vì mình cũng khá quen với việc setup dễ dàng, đơn giản cũng như giá cả phải chăng. Với domain, các bạn có thể mua ở bất kì trang nào(nhắm rẻ thì mua :D)

Mình cũng sử dụng dịch vụ CloudFlare để làm cache và security cho blog giúp cải thiện tốc độ load của trang, cũng như dễ quản lý về bảo mật hơn(chống DDOS chẳng hạn) và hơn hết, với CloudFlare mình không cần phải sử dụng SSL phải mua từ nhà cung cấp domain mà có thể tự setup cho blog 1 SSL Cert xịn xò.

Chi tiết về đăng ký:
- https://www.digitalocean.com/
- https://www.cloudflare.com/

Bước 2: Tạo và Cài đặt Droplet

Với DO, chúng ta chỉ cần tạo 1 Droplet - 1 server được cung cấp bởi DO. Ở đây mình chọn gói 5$/month với cài đặt ban đầu là Ubuntu 20.04 và datacenter được đặt ở Singapore để có đường truyền tốt nhất về VN.

Bước 3: Dựng Ghost CMS và MySQL

Để dựng 1 trang ghost blog, thay vì cài đặt trực tiếp lên server ta có thể sử dụng Docker.

Cách cài đặt Docker, Docker Compose lên DO có thể tham khảo ở link:
- https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04
- https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-compose-on-ubuntu-20-04

Tạo 1 thư mục blog-docker, sau đó tạo file docker-compose.yml nằm trong blog-docker. Ở đây chúng ta sẽ khai báo 2 service là ghost và mysql:

version: '3.3'

services:
  ghost:
    image: ghost:latest
    container_name: ghost
    hostname: ghost
    volumes:
      - $PWD/ghost/config.production.json:/var/lib/ghost/config.production.json:z
      - ./ghost/content:/var/lib/ghost/content:z
      - ./ghost/content/themes/Dawn:/var/lib/ghost/content/themes/casper:z
    expose:
    - "3306"
    environment:
      - NODE_ENV=production
    restart: on-failure
    depends_on:
      - mysql

  mysql:
    image: mysql:latest
    container_name: mysql
    volumes:
      - ./mysql/config/shangblog.cnf:/etc/mysql/conf.d/shangblog.cnf:z
      - ./dbdata:/var/lib/mysql:z
    expose:
      - "3306"
    environment:
      - MYSQL_ROOT_PASSWORD=<your_password>
      - MYSQL_DATABASE=ghostdata
      - MYSQL_USER=<your_username>
      - MYSQL_PASSWORD=<your_password>
    restart: always

Tiếp theo, tạo thư mục ghost, tiếp tục tạo file config.production.json trong thư mục này. File này sẽ khai báo url blog, cấu hình mysql, cấu hình email,...

{
    "url": <your_domain>,
    "server": {
        "port": 2368,
        "host": "0.0.0.0"
    },
    "database": {
        "client": "mysql",
        "connection": {
            "host": "mysql",
            "port": 3306,
            "user": <your_username>,
            "password": <your_password>,
            "database": "ghostdata",
            "charset": "utf8mb4"
        }
    },
    "mail": {
        "from": "'Custom Name' <[email protected]>", 
        "transport": "SMTP",
        "logger": true,
        "options": {
            "host": "",
            "secureConnection": false,
            "auth": {
                "user": "",
                "pass": ""
            }
        }
    },
    "logging": {
        "transports": [
            "file",
            "stdout"
        ]
    },
    "process": "systemd",
    "paths": {
        "contentPath": "/var/lib/ghost/content"
    }
}

Bước 4: Cài đặt Nginx với SSL từ CloudFlare

Nginx là 1 reverse-proxy, giúp chúng ta có thể điều hướng các request tới trang của mình, với những request tới port 443/https chúng ta có thể hoàn toàn tự tạo cho mình 1 SSL Certificate được cung cấp bởi CloudFlare.

Trước tiên, ta đổi nameserver từ nhà cung cấp về DNS của CloudFlare nhé. Bạn có thể tham khảo các cách đổi nameserver từ nhà cung cấp dịch vụ tên miền của mình đển CloudFlare theo link sau: https://developers.cloudflare.com/automatic-platform-optimization/get-started/change-nameservers/

Tạo Origin CA TLS Certificate từ CloudFlare: Đăng nhập vào CloudFlare, tìm tới tab SSL/TLS. Sau đó vào tab Origin Certificates và nhấn vào Create Certificate

Click Create và chúng ta sẽ có 1 cặp key,

Lưu 2 key này với tên <domain_name>.pem đối với Certificate và <domain_name>.key vào thư mục nginx/conf(đặt chung thư mục với file docker-compose.yml). Ở ví dụ này mình sẽ lưu thành shangblog.com.pem và shangblog.com.key tương ứng.

Sau đó ta create file ghost.conf để Nginx có thể điều hướng tới ghost blog.

server {
    listen 80;
    listen [::]:80;
    server_name shangblog.com www.shangblog.com;
    return 302 https://$server_name$request_uri;
}

server {
  listen 443 ssl http2 default_server;
  listen [::]:443 http2 ssl;
  server_name shangblog.com www.shangblog.com;
  ssl on;
  ssl_certificate /etc/nginx/shangblog.com.pem;
  ssl_certificate_key /etc/nginx/shangblog.com.key;
  ssl_protocols TLSv1.3;

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  X-Forwarded-Proto   $scheme;
    proxy_connect_timeout                 90;
    proxy_send_timeout                    90;
    proxy_read_timeout                    90;
    proxy_buffering off;
    proxy_cache_valid 200 30m;
    proxy_cache_valid 404 1m;
    
    client_max_body_size                  10m;
    client_body_buffer_size               128k;

    proxy_pass http://ghost:2368;
  }
}

Để cài đặt Nginx từ Docker, chúng ta sẽ update vào cuối file docker-compose.yml như sau:

version: '3.3'

services:
  ...
  
  nginx:
    image: nginx:latest
    container_name: nginx
    hostname: ghost-nginx
    ports:
      - 443:443
    volumes:
      - ./nginx/ssl/shangblog.com.pem:/etc/nginx/shangblog.com.pem:ro
      - ./nginx/ssl/shangblog.com.key:/etc/nginx/shangblog.com.key:ro
      - ./nginx/conf/ghost.conf:/etc/nginx/conf.d/ghost.conf:z
    restart: always
    depends_on:
      - ghost

Bước 5: Tinh chỉnh và Gopro

Sau khi hoàn thành các bước trên, bạn có thể start blog bằng cách SSH vào DO Droplet, copy thư mục blog-docker lên, vào thư mục và gõ command:

docker-compose up -d

Bây giờ chúng ta có thể test thử trang blog rồi!

Một số tinh chỉnh để blog chạy mượt hơn:

  • Tăng swapfile: vì blog đang chạy trên server chỉ có 1GB RAM nên đôi khi sẽ quá tải. Để hạn chế tình trạng blog bị treo, bạn có thể nâng swapfile để blog có thể chia tải sang ổ cứng:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
echo "vm.swappiness=10\nvm.vfs_cache_pressure=50" >> /etc/sysctl.conf
sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50
  • Tắt autoupdate của Ubuntu 20.04: vì là shared server nên CPU của Droplet khá hẻo, với tác vụ update cần build source sẽ làm blog bị timeout
sudo apt remove unattended-upgrades
  • Tinh chỉnh cho MySQL: Ta có thể khai báo file mysql/config/shangblog.conf trong thư mục
[mysqld]
default-time-zone = "+07:00"
innodb_buffer_pool_size = 50M
max_connections = 400
innodb_lock_wait_timeout = 100
table_definition_cache = 400

Kết bài

Trên đây là những bước mình đã tự setup 1 blog với chi phí chỉ 5$/tháng cho server. Cảm ơn các bạn đã theo dõi. Nhấn Subcription để nhận thêm nhiều bài viết mới đến từ shangblog.com nhé.

Enjoying these posts? Subscribe for more