Tôi cài đặt WordPress

Bài viết này mô tả chính xác cách mà blog này được cài đặt và cấu hình.

Docker Service

Instance được deploy bằng một docker stack:

version: '3.1'
services:
  app:
    image: wordpress
    restart: unless-stopped
    depends_on:
      - db
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: $DB_USER
      WORDPRESS_DB_PASSWORD: $DB_PASSWORD
      WORDPRESS_DB_NAME: $DB_NAME
      ACCESS_KEY: $AWS_ACCESS_KEY
      SECRET_KEY: $AWS_SECRET_KEY
    ports:
      - $WEB_SOCK:80
    volumes:
      - app:/var/www/html
  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: $DB_NAME
      MYSQL_USER: $DB_USER
      MYSQL_PASSWORD: $DB_PASSWORD
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql
volumes:
  app: {}
  db: {}

Environment:

// Địa chỉ localhost, sẽ public bằng https://caddyserver.com/
WEB_SOCK=127.0.0.1:10101
// Cặp key để xác thực AWS IAM User, dùng để truy cập S3
ACCESS_KEY=bi-mat
SECRET_KEY=bi-mat
// DB Specs, vừa dùng để khởi tạo MYSQL Instance, vừa dùng để cấu hình truy cập cho WP Instance
DB_USER=wordpress
DB_PASSWORD=tat-nhien-cung-bi-mat
DB_NAME=wordpress

Caddy

Caddy là lựa chọn số một để tôi proxy nhiều service dưới một tên miền duy nhất:

nguyenbinhson.com {
  reverse_proxy 127.0.0.1:10101
}
// cac dich vu khac
// ...

Phân quyền cho thư mục WordPress Content

Ảnh docker wordpress có một vấn đề được biết tới phổ biến đó là user www-data mất quyền thao túng thư mục wp-content. Việc này vô hình trung làm mất khả năng cài đặt và cập nhật các phần mở rộng WP bằng chính WordPress. Tôi phục hồi lại khả năng này bằng cách truy cập vào container và thực hiện:

chown -R www-data wp-content
chmod -R 755 wp-content

Cấu hình khả năng cài đặt phần mở rộng qua giao diện web:

define('FS_METHOD', 'direct');

Offload các media bằng AWS S3

Tôi không muốn sử dụng docker volume để lưu trữ các media, hiệu quả không cao. Thay vào đó giải pháp sử dụng CDN được ưu tiên hơn. S3 là bước thực hiện đầu tiên.

Cấu hình cho WordPress sử dụng S3 để offload media nói chung gồm các bước như sau:

  1. Khởi tạo AWS S3 buckets với khả năng truy cập public.
  2. Khởi tạo AWS IAM User với khả năng thao túng S3 bucket.
  3. Cài đặt một WordPress Plugin có khả năng sử dụng S3 bucket để offload media.
  4. Kết nối S3 bucket với AWS Cloudfront để có một CDN.
  5. Tạo một AWS SSL Certificate cho tên miền, điều này là bắt buộc để thực hiện bước tiếp theo.
  6. Cấu hình tên miền tùy chỉnh cho CDN.
  7. Cấu hình CDN cho offload plugin.

Khởi tạo AWS S3 bucket

AWS S3 bucket có thể tạo đơn giản tại AWS S3 Console. Các tài nguyên trong bucket sẽ có URL theo dạng https://$BUCKET_NAME.s3-$AWS_ZONE.amazonaws.com/**, nên căn cứ vào pattern này để đặt tên hợp lý cho bucket.

Bucket cần được mở khả năng truy cập public, điều này cần thực hiện ở cả account level lẫn bucket level:

Khởi tạo IAM User

IAM User là các user được tạo ra và quản lý bởi chủ nhân của account AWS, nhằm mục đích quản lý quyền hạn truy cập. Tôi sẽ tạo ra một IAM user có khả năng thao túng S3 bucket ở trên, và trao user này cho offload plugin. Tính chất có khả năng thao túng S3 buckets cho trước được cấu hình bằng cách tạo ra một IAM Policy.

IAM User cũng như Policy có thể dễ dàng tạo ra tại AWS IAM Management Console. Khi tạo Policy tôi sử dụng Visual Editor nhưng thật ra toàn bộ cấu hình có thể được tóm gọn lại bằng một chuỗi JSON:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:PutBucketAcl",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetBucketAcl",
                "s3:GetBucketLocation",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::$BUCKET_NAME",
                "arn:aws:s3:::$BUCKET_NAME/*"
            ]
        }
    ]
}

Trong đó $BUCKET_NAME là tên của S3 bucket.

Khi tạo ra một IAM User thì lưu ý đặt loại hình truy cập là Programatialy:

…và đặt policy đã tạo ở trên cho user:

Sau khi IAM user được tạo ra thành công, AWS sẽ cung cấp access keysecret key một lần duy nhất, tôi sẽ lưu giữ cặp key này lại để phục vụ bước cấu hình về sau.

Cài đặt offload plugin

Có nhiều plugin phù hợp, search dễ dàng với từ khóa S3, tôi đơn giản chọn plugin được sử dụng phổ biến nhất.

Sau khi cài đặt và kích hoạt, offload plugin sẽ hướng dẫn chèn một đoạn mã vào file wp-config.php, tôi đã cải biến một chút để có script này nhận cặp key truy cập từ biến môi trường:

define( 'AS3CF_SETTINGS', serialize( array(
    'provider' => 'aws',
    'access-key-id' => getenv('ACCESS_KEY'),
    'secret-access-key' => getenv('SECRET_KEY'),
) ) );

Tôi sẽ đặt cặp key truy cập vào file .env:

AWS_ACCESS_KEY=bi-mat
AWS_SECRET_KEY=bi-mat

…và đưa vào biến môi trường của container thông qua cấu hình docker stack:

version: '3.1'
services:
  app:
    // ...
    environment:
      ACCESS_KEY: $AWS_ACCESS_KEY
      SECRET_KEY: $AWS_SECRET_KEY
      //...

Sau khi cấu hình xong và restart WordPress instance thì plugin đã có khả năng truy cập và thao túng S3 bucket. Thường thì tôi sẽ upload thử một tập tin media bất kỳ để kiểm tra.

CDN

Như một best practice, tôi sẽ tạo ra khả năng truy cập S3 bucket thông qua đám mây phân tán bằng CDN. Dịch vụ CDN mà tôi sử dụng dễ dàng nhất trong trường hợp này là AWS CloudFront. Việc thiết lập CloudFront khá đơn giản, tôi chỉ cần tạo một Web Distribution, kết nối nó tới S3 bucket, và để nguyên tất cả các thiết lập mặc định. Sau khi distribution được deploy thành công thì tôi đã có một đường dẫn CDN dạng $RANDOM.cloudfront.net để sẵn sàng sử dụng.

Việc còn lại đơn giản là khai báo đường dẫn CDN cho offload plugin:

Tên miền tùy biến cho CDN

Một best practice khác là thay thế đường dẫn CDN từ cloudfront.net sang tên miền trùng với tên miền dùng cho WordPress instance. Tiên miền tùy biến có thể được cấu hình tại Distribution Settings, nhưng trước hết tôi phải tạo ra một SSL Certificate cho tên miền tùy biến đã.

Tại AWS Certificate Manager, tôi nhập domain name với wildcard *, và sau đó chọn validation method là DNS. Tôi sẽ phải cấu hình DNS mà ACM yêu cầu vào cấu hình domain tùy biến của tôi.

Sau khi certificate được tạo lập thành công thì CDN của tôi đã sẵn sàng để truy cập bằng tên miền tùy biến, tôi sẽ thay thế tên miền này vào cấu hình cũ của offload plugin.

Bạn có thể quan sát kết quả của bước này bằng cách inspect và quan sát src của bất kỳ image nào trong bài viết này.

Theme

Không có theme hiện hữu nào là chính xác cái tôi muốn, do đó tôi tự làm lấy một cái.

Syntax Highlighter

Có nhiều giải pháp để có được syntax highlighter cho cho một WordPress. Tôi yêu cầu giải pháp phải không yêu cầu phải tạo ra một Gutenberg block mới. Thay vào đó là hack/hook vào tiến trình render của Gutenberg Code Block.

Tôi muốn dùng bảng màu Colorful của Pyment. Muốn thế thì toàn vẹn nhất là bật một Pyment microservice để chuyên trị highlight các khối Code. Do chưa biết chút nào về PHP cũng như API của WordPress nên tôi chọn giải pháp rẻ hơn là highlight tại client.

Kế hoạch là sử dụng prismjs để highlight. Một lần nữa vấn đề mù mờ toàn diện về WordPress API biến thành trở ngại. May mắn là tôi tìm được một plugin làm gần đúng chuyện mình muốn là Code Syntax Block. Vẫn phải tweak lại một chút, nên Syntaxism Code Block ra đời.

Cuối cùng, Prism không có bảng màu tôi muốn, kết quả là Prism Colorful được tạo ra.

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *