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ấuEOF. Ở đâ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ậpnoi_dung_cf|| true: trong bash script cóset -ethì 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ấynulltrong 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).