Bash script block 06: Chỉnh sửa file Caddyfile

Phần này thực hiện nhiệm vụ chỉnh sửa file Caddyfile, đây là file rất quan trọng trong Caddy Web Server, điểm mạnh nhất của nó so với các chức năng tương tự của các web server khác là đơn giản, dễ hiểu và ít phải gỡ lỗi hơn nhiều.

Tuy nhiên trong phần này, chúng ta sẽ chỉ bàn đến các nội dung chính của bash script, phân tích Caddyfile sẽ có một bài riêng.

# Phần 5: Chinh sua file Caddyfile
# 1. Khai báo biến đường dẫn và Marker
CADDY_FILE="/etc/caddy/Caddyfile"
MARKER="#wpSila_kiencang"

# 2. Định nghĩa nội dung bạn muốn thêm vào
# Lưu ý: Tôi thêm $MARKER vào nội dung để lần sau chạy nó sẽ nhận diện được
read -r -d '' CONTENT <<EOF || true
# 1. Chuyen huong www ve non-www 
www.$DOMAIN {
    redir https://$DOMAIN{uri} permanent
}

# 2. Cau hinh chinh
$DOMAIN {
    root * /var/www/$DOMAIN/public_html
    encode zstd gzip

    # Log: Tu dong xoay vong
    log {
        output file /var/www/$DOMAIN/logs/access.log {
            roll_size 10mb
            roll_keep 10
        }
    }

    # --- SECURITY HEADERS ---
    # Sau khi HTTPS da chay on dinh, hay bo comment dong Strict-Transport-Security
    header {
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        X-XSS-Protection "0"
        Referrer-Policy "strict-origin-when-cross-origin"
        Permissions-Policy "camera=(), microphone=(), geolocation=(), browsing-topics=()"
        # Strict-Transport-Security "max-age=31536000; includeSubDomains"
        -Server
        -X-Powered-By
    }

    # --- CACHE CODE (CSS/JS) ---
    # Khong dung immutable de tranh loi khi update code
    @code_assets {
        file
        path *.css *.js
    }
    header @code_assets Cache-Control "public, max-age=604800"

    # --- CACHE MEDIA (ANH/FONT) ---
    # Dung immutable vi file anh it khi sua noi dung ma giu nguyen ten
    @media_assets {
        file
        path *.ico *.gif *.jpg *.jpeg *.png *.svg *.woff *.woff2 *.webp *.avif
    }
    header @media_assets Cache-Control "public, max-age=31536000, immutable"

    # --- CHAN FILE NHAY CAM (SECURITY BLOCK) ---
    @forbidden {
        # 1. Block PHP Uploads (DUNG REGEX DE CHAN DE QUY)
        # ^ bắt đầu, .* khớp mọi thứ (kể cả /), \.php$ kết thúc bằng .php
        path_regexp bad_php ^/wp-content/uploads/.*\.php

        # 2. Block System Files & Directories
        path /wp-config.php
        path /.htaccess
        path /.git*     # Prefix match: Chặn folder .git và nội dung bên trong
        path *.env      # Suffix match: Chặn .env ở mọi nơi
        path /readme.html
        path /license.txt
		
		# 3. Trừ khi bạn dùng plugin Jetpack hoặc đăng nhập WordPress trên điện thoại, còn không thì nên chặn
		path /xmlrpc.php
        
        # 4. Block Backups & Logs
        path *.sql *.bak *.log *.old
        path *.zip *.rar *.tar *.7z
    }
    # Tra ve 404
    respond @forbidden 404
	
	# PHP FastCGI (Check lai duong dan socket neu dung OS khac Ubuntu/Debian)
    php_fastcgi unix//run/php/php8.3-fpm.sock

    file_server

    # Tang gioi han upload, can chinh them /etc/php/8.3/fpm/php.ini cho dong bo
    request_body {
        max_size 50MB
    }
}
    # Đánh dấu marker để nhận diện sau này
    $MARKER
EOF

# 3. Thực hiện Logic kiểm tra
# grep -q: Chế độ im lặng (quiet), chỉ trả về đúng (0) hoặc sai (1), không in ra màn hình
# 2>/dev/null: Ẩn lỗi nếu file không tồn tại
if grep -q "$MARKER" "$CADDY_FILE" 2>/dev/null; then
		
	echo "TIM THAY marker '$MARKER'. Dang noi noi dung vao cuoi file..."
		
	# Thay thế cho echo >> (Nối thêm)
	echo "$CONTENT" | sudo tee -a "$CADDY_FILE" > /dev/null

else
		
	echo "KHONG TIM THAY marker '$MARKER'. Dang xoa cu va tao file moi..."
		
	# Thay thế cho echo > (Ghi đè)
	echo "$CONTENT" | sudo tee "$CADDY_FILE" > /dev/null

fi

echo "Dang kiem tra va reload Caddy..."
# 4. Format
caddy fmt --overwrite "$CADDY_FILE" > /dev/null 2>&1

a. Khai báo đường dẫn và marker đánh dấu

CADDY_FILE="/etc/caddy/Caddyfile"
MARKER="#wpSila_kiencang"

Khai báo đường dẫn để bash biết được vị trí chỉnh sửa caddyfile, nó nằm ở địa chỉ /etc/caddy/Caddyfile

Còn biến MARKER không liên quan gì đến chức năng của Caddyfile, nó chẳng qua là thông tin đánh dấu để tôi biết bash này đã từng chỉnh sửa file Caddy. Mục đích là để nếu đây là chỉnh sửa đầu tiên của bash để tạo trang WordPress, nó sẽ xóa sạch nội dung cũ (nội dung mặc định do Caddy tạo). Nếu tìm thấy MARKER, nó sẽ không xóa sạch, mà chỉ nối tiếp nội dung vào cuối file, mặc dù bash này đang định hướng chỉ tạo một WordPress trên một VPS cho đơn giản, tuy nhiên khả năng nó chuyển thành tạo nhiều trang WordPress trên một VPS sẽ là một chuyển đổi có khả năng cao xảy ra, do vậy dự phòng trước không thừa, và dự phòng này cũng không khó để triển khai.

b. read -r -d '' CONTENT <<EOF || true

Dùng để gán nội dung văn bản nhiều dòng vào một biến. Cụ thể là biến $CONTENT.

  • read: đọc dữ liệu từ đầu vào.
  • -r: hiểu các ký tự theo nghĩa đen, không xử lý các ký tự như \ thành dấu thoát.
  • -d '': để read đọc toàn bộ nội dung cho đến khi kết thúc, thay vì chỉ đọc khi hết dòng đầu tiên.
  • <<EOF: để báo cho bash biết rằng, toàn bộ nội dung nó cần nhập nằm trong đánh dấu EOF. Ở đây EOF không phải là từ khóa của bash, nó chỉ là một nhãn đánh dấu tùy ý để bash biết điểm bắt đầu và kết thúc của nội dung nhập vào, điểm quan trọng là điểm đầu và cuối phải giống nhau, ví dụ ta có thể viết thế này cũng được <<noi_dung_cf văn bản cần nhập noi_dung_cf
  • || true: trong bash script có set -e thì phải bổ sung, vì read khi đọc xong sẽ thành 1 (do thiết lập -d '' nó sẽ không tìm thấy null trong văn bản), và bash bị dừng, khi chủ động để true ở đây, chúng ta báo với bash rằng kết quả này là thành công và do vậy bash chạy tiếp.

c. Logic kiểm tra

if grep -q "$MARKER" "$CADDY_FILE" 2>/dev/null; then
  • grep: từ khóa trong bash dùng để tìm kiếm văn bản, mục đích ở đây là tìm kiếm xem trong $CADDY_FILE có tồn tại $MARKER không?
  • -q: truy vấn sẽ hiển thị kết quả tìm thấy ra màn hình, nhưng đây không phải mục đích của ta (ta chỉ cần biết nó có tìm thấy hay không và xử lý logic tiếp), do vậy đặt -q (quiet/im lặng) để nó không cần báo.
  • 2>/dev/null: để chuyển hướng các thông báo lỗi vào /dev/null.

echo "$CONTENT" | sudo tee -a "$CADDY_FILE" > /dev/null

Dùng để nối nội dung $CONTENT vào cuối $CADDY_FILE, chỉ thị nối được dùng với từ khóa -a (append). Các dòng thông báo không cần thiết cũng được chuyển vào /dev/null

echo "$CONTENT" | sudo tee "$CADDY_FILE" > /dev/null

Dùng để ghi đè nội dung $CONTENT vào $CADDY_FILE, từ khóa tee trong bash mặc định sẽ ghi đè nội dung (nếu kèm thêm -a thì mới mang nghĩa nối thêm).

Viết một bình luận