Host website WordPress tĩnh tại BunnyCDN bằng WP2Static mà không mất bình luận, tìm kiếm và contact form 7 (phần 1)

Trước hết chúng ta hãy xem bảng so sánh giữa trang WordPress động truyền thống và trang WordPress tĩnh hoàn toàn (nhưng vẫn giữ được các yếu tố động quan trọng):

WordPress động truyền thốngWordPress tĩnh hoàn toàn
DNSTrỏ đến IP của máy chủ WordPressTrỏ đến CDN hostname liên kết với Storage tĩnh
Hiệu suất webTốn kém để có được TTFB dưới 200ms trên toàn cầuKhông tốn kém để có được TTFB dưới 200ms trên toàn cầu
Môi trườngLinux Ubuntu, PHP, MySQL, NGINX/ApacheStorage dạng đám mây cho hosting tĩnh và CDN
Bảo mậtDễ bị tấn công vét cạn (brute-force), SQL injection, XSSNhìn chung giảm được rất nhiều các kiểu tấn công
Thương mại điện tửBạn có thể sử dụng WooCommerceBạn có thể sử dụng Snipcart
Hỗ trợTìm kiếm, bình luận, contact form 7, users, WPMLTìm kiếm, bình luận, contact form 7, user, WPML

Tại thời điểm viết bài này người dịch có một số blog dạng tĩnh hoàn toàn xuất ra từ WordPress vì lý do hiệu suất, bảo mật & tiết kiệm chi phí.

Bình luận, tìm kiếm và form vẫn hoạt động bình thường.

Điều này hoạt động như thế nào?

  • Giả sử gulshankumar.net, www.gulshanlumar.net trỏ đến BunnyCDN hostname liên kết với storage của BunnyCSN:

Trước khi chúng ta tiến hành, cần có một vài điều kiện tiên quyết để đem lại trải nghiệm người dùng tốt nhất. Một khi môi trường tùy biến đã sẵn sàng, với việc kết hợp với plugin xuất trang tĩnh (ví dụ WP2Satic, Simply Static), chúng ta có thể triển khai trang WordPress tĩnh tại BunnyCDN.


1. Sử dụng Google tìm kiếm tùy chỉnh thay cho tìm kiếm mặc định của WordPress

  • Tính năng tìm kiếm mặc định của WordPress hoạt động tại địa chỉ dạng https://example.com/?s=truy+van+tim+kiem và nó không thể hoạt động với trang HTML tĩnh. Nó sẽ trả về trang chủ với bất kỳ truy vấn tìm kiếm nào;
  • Tính năng tìm kiếm mặc định của WordPress chậm, không được cache, thường hiển thị kết quả không liên quan. Trang tĩnh đem đến cho bạn khả năng chỉnh sửa điều này bằng cách sử dụng công cụ tìm kiếm tùy chỉnh của Google. Bạn có thể chủ động phục vụ trang “kết quả tìm kiếm” ở chế độ HIT (ý là đã được cache).

2. Thực hiện backup toàn bộ WordPress

Tôi gợi ý bạn có thể sử dụng plugin UpdraftPlus hoặc All in One Migration Premium để tiến hành backup. Hoặc, bạn có thể thực hiện backup thủ công.


3. Khôi phục WordPress tại máy chủ Đức dựa trên LEMP stack

Bạn có thể tham khảo thêm cách triển khai WordPress thông qua LEMP Stack trên mạng.

  • Điều quan trọng nhất là môi trường và LEMP là stack tốt nhất cho mục đích hiệu suất;
  • Máy chủ BunnyCDN Storage có vị trí ở Đức. Nó có tốc độ triển khai nhanh hơn, tốt hơn bạn nên có trang development trên cùng một vị trí, điều đó ngụ ý rằng nếu bạn có người dùng chủ yếu ở Việt Nam, triển khai tại Singapore sẽ là lựa chọn hợp lý hơn;

4. Liên kết subdomain tới WordPress để quản trị

  • Chúng ta cần giữ môi trường phát triển (dev) tại subdomain dev.ten-mien-cua-ban.com. Cái này sẽ được gia cố thêm bằng mật khẩu;
  • Trong WordPress, bạn cài và kích hoạt plugin multiple domains và cấu hình như bên dưới;
  • Sử dụng Cloudflare DNS, trỏ dev.ten-mien-cua-ban.com đến địa chỉ IP của máy chủ LEMP nơi WordPress cài đặt. Kết hợp nó với proxy của Cloudflare;

Plugin này sẽ lo liệu URL rewritung dựa trên Request Hostname.

Bạn đừng thay đổi trực tiếp tên miền chính thành dev.ten-mien-cua-ban.com. Điều này sẽ tạo ra rắc rối. Tôi sẽ giải thích điều này rõ ở cuối bài.


5. Mật khẩu bảo vệ máy chủ ngoại trừ contact form 7 & URL bình luận

Đường dẫn loại trừ:

  • dev.ten-mien-cua-ban.com/wp-json/contact-form-7/v1/contact-forms/1478/feedback

Nó sẽ trả về lỗi 404 với phàn hồi bên dưới:

{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}
  • dev.ten-mien-cua-ban.com/wp-comments-post.php

Lý tưởng nhất, nó sẽ trả về lỗi 405 với request GET.

Mật khẩu cho đường dẫn cần bảo vệ

  • dev.ten-mien-cua-ban.com
## Allowed path
dev.ten-mien-cua-ban.com/wp-json/contact-form-7/v1/contact-forms/1478/feedback
It should return error 404 with below response body
{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}

dev.ten-mien-cua-ban.com/wp-comments-post.php

It should return special error 405


##Blocked Path
dev.ten-mien-cua-ban.com/anything/
It should return 401 if credential not provided.

Tôi muốn gửi lời cám ơn CloudBooklet đã giúp tôi thiết lập HTTP Authentication.

Cài đặt các công cụ Apache để tạo .htpasswd

Truy cập vào server của bạn bằng SSH và gõ các dòng lệnh sau:

sudo -s
apt install apache2-utils -y

Tạo mật khẩu

htpasswd -c /var/www/.htpasswd gulshan

Trong ví dụ dưới đây username là user-ban-chon, sau đó bạn nhập mật khẩu, giờ bạn sẽ thấy thông tin xuất ra có dạng như thế này:

root@WordPress:~# htpasswd -c /var/www/.htpasswd user-ban-chon
New password: 
Re-type new password: 
Adding password for user user-ban-chon

Để lấy password bạn sử dụng cậu lệnh dưới đây và lưu nó tại vị trí bảo mật:

cat /var/www/.htpasswd

Cài đặt trang 401 tùy chỉnh

  • Thêm file custom_401.html tại vị trí thư mục /var/www/html theo cấu hình bên dưới.

Cấu hình mấy chủ NGINX Block cho việc xuất trang HTML tĩnh

  • Chỉnh sửa block máy chủ hiện có của bạn tại /etc/nginx/sites-available/ten-mien-cua-ban.com;
  • Bạn cần thay thế ten-mien-cua-ban.com bằng tên miền của bạn. Cái này là trong định dạng wildcard để khớp subdomain dev;

  • Lấy chính xác ID của contact form 7 để cấu hình chính xác trong NGINX;
  • Rule bên dưới sẽ cho phép bảo vệ bằng mật khẩu khi cần, cũng như thêm một số chỉnh sửa hữu dụng khác cho việc xuất HTML tĩnh (bạn nhớ thay gulshankumar.net bằng tên miền của bạn).
server {
root /var/www/html;
index index.php index.html index.htm;
server_name .gulshankumar.net;
client_max_body_size 0;
server_tokens off;

# Grace period for crawling and deployment
fastcgi_read_timeout 10800;

# Show Real IP for Comment Author instead showing BunnyCDN IP
set_real_ip_from 0.0.0.0/0;
set_real_ip_from ::/0;
real_ip_header X-Forwarded-For;

# Make sure to create Custom 401 page
        error_page 401 /custom_401.html;
        location = /custom_401.html {
                root /var/www/html;
                internal;
        }
# Allow access to Development site only over HTTPS requests
    listen [::]:443 ssl http2 ipv6only=on;
    listen 443 ssl http2;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_certificate /etc/letsencrypt/live/gulshankumar.net/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/gulshankumar.net/privkey.pem;
        ssl_session_cache   shared:SSL:20m;
        ssl_session_timeout 20m;
        ssl_ciphers 'TLS13+AESGCM+AES128:EECDH+AES128';
		ssl_prefer_server_ciphers off;
		ssl_early_data on;
				
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;

# Allow posting comments
location = /wp-comments-post.php {
  auth_basic off;
  fastcgi_pass unix:/run/php/php7.4-fpm.sock;
  include fastcgi_params;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

# Allow CF7. Please replace 1478 to own form ID.
location = /wp-json/contact-form-7/v1/contact-forms/1478/feedback {
  auth_basic off;
  try_files $uri $uri/ /index.php?q=$uri&$args;
}

location / {
# Whitelist
satisfy any;
allow 127.0.0.1;
deny all;
auth_basic           "Secure Area";
auth_basic_user_file /var/www/.htpasswd;
try_files $uri $uri/ /index.php?q=$uri&$args;
}

location ^~ /wp-login.php {
satisfy any;
allow 127.0.0.1;
deny all;
 auth_basic           "Secure Area";
 auth_basic_user_file /var/www/.htpasswd;
 fastcgi_pass unix:/run/php/php7.4-fpm.sock;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

location ~* \.php$ {
if ($uri !~ "^/uploads/") {
fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
}

location ~* .(ico|svg|css|js|txt|gif|webp|jpeg|jpg)$ {
satisfy any;
allow 127.0.0.1;
deny all;
auth_basic           "Secure Area";
auth_basic_user_file /var/www/.htpasswd;
expires 3d;
log_not_found off;
}
# Enable Gzip compression.
gzip on;
# Disable Gzip on IE6.
gzip_disable "msie6";
# Allow proxies to cache both compressed and regular version of file.
# Avoids clients that don't support Gzip outputting gibberish.
gzip_vary on;
# Compress data, even when the client connects through a proxy.
gzip_proxied any;
# The level of compression to apply to files. A higher compression level increases
# CPU usage. Level 5 is a happy medium resulting in roughly 75% compression.
gzip_comp_level 5;
# Compress the following MIME types.
gzip_types
        application/atom+xml
        application/javascript
        application/json
        application/ld+json
        application/manifest+json
        application/rss+xml
        application/vnd.geo+json
        application/vnd.ms-fontobject
        application/x-font-ttf
        application/x-web-app-manifest+json
        application/xhtml+xml
        application/xml
        font/opentype
        image/bmp
        image/svg+xml
        image/x-icon
        text/cache-manifest
        text/css
        text/plain
        text/vcard
        text/vnd.rim.location.xloc
        text/vtt
        text/x-component
        text/x-cross-domain-policy;
}
# End

Kiểm tra cấu hình:

nginx -t

Tải lại NGĨN:

service nginx reload

Bạn cứ thoải mái block TCP 80 trong Cloud Firewall của máy chủ của bạn nếu không cần request HTTP cho khu vực dev.

  • Thực sự không cần phải chấp nhận bất cứ yêu cầu không an toàn nào tại tên miền dev;
  • Nếu bạn vẫn muốn request http, bạn có thể thêm chuyển hướng tại phần đầu của server block;
server {
    listen 80;
    return 301 https://$host$request_uri;
}
...

Mời bạn đọc tiếp phần 2: https://kiencang.net/wp-static-bunnycdn-p2/

(Dịch từ bài viết: Host Static WordPress at BunnyCDN With WP2Static without Losing Comment, Search, Contact Form 7, tác giả: Gulshan Kumar)

Leave a Comment