#!/usr/bin/env bash
# optimize_apache.sh
# Kịch bản tự động tối ưu hóa Apache Web Server để chống nghẽn hàng đợi và Slowloris
# Hỗ trợ aaPanel/cPanel và các bản phân phối Linux tiêu chuẩn (CentOS, RHEL, Ubuntu)
# Usage: sudo ./optimize_apache.sh
set -euo pipefail
# Màu sắc hiển thị
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}==================================================================${NC}"
echo -e "${GREEN} TIẾN TRÌNH TỰ ĐỘNG TỐI ƯU HÓA APACHE WEB SERVER (HIGH PERFORMANCE)${NC}"
echo -e "${BLUE}==================================================================${NC}"
# 1. KIỂM TRA QUYỀN ROOT
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}LỖI: Vui lòng chạy script này dưới quyền root (sudo).${NC}"
exit 1
fi
# 2. XÁC ĐỊNH ĐƯỜNG DẪN CẤU HÌNH APACHE
APA_DIR=""
HTTPD_CONF=""
MPM_CONF=""
DEFAULT_CONF=""
SERVICE_CMD=""
if [ -d "/www/server/apache" ]; then
# aaPanel / BT.cn
APA_DIR="/www/server/apache"
HTTPD_CONF="$APA_DIR/conf/httpd.conf"
MPM_CONF="$APA_DIR/conf/extra/httpd-mpm.conf"
DEFAULT_CONF="$APA_DIR/conf/extra/httpd-default.conf"
SERVICE_CMD="/etc/init.d/httpd"
echo -e "${GREEN}--> Phát hiện môi trường: aaPanel / Baota Control Panel${NC}"
elif [ -f "/etc/httpd/conf/httpd.conf" ]; then
# CentOS / RHEL tiêu chuẩn
APA_DIR="/etc/httpd"
HTTPD_CONF="$APA_DIR/conf/httpd.conf"
MPM_CONF="$APA_DIR/conf.modules.d/00-mpm.conf"
SERVICE_CMD="systemctl restart httpd"
echo -e "${GREEN}--> Phát hiện môi trường: CentOS / RHEL (Standard)${NC}"
elif [ -d "/etc/apache2" ]; then
# Ubuntu / Debian tiêu chuẩn
APA_DIR="/etc/apache2"
HTTPD_CONF="$APA_DIR/apache2.conf"
SERVICE_CMD="systemctl restart apache2"
echo -e "${GREEN}--> Phát hiện môi trường: Ubuntu / Debian (Standard)${NC}"
else
echo -e "${RED}LỖI: Không tìm thấy thư mục cài đặt Apache tiêu chuẩn.${NC}"
exit 2
fi
echo -e "--> Thư mục Apache: ${YELLOW}$APA_DIR${NC}"
echo -e "--> File cấu hình chính: ${YELLOW}$HTTPD_CONF${NC}"
# Tạo thư mục sao lưu cấu hình
BACKUP_DIR="$APA_DIR/backup_optimize_$(date +%s)"
mkdir -p "$BACKUP_DIR"
echo -e "--> Đã tạo thư mục sao lưu tại: ${YELLOW}$BACKUP_DIR${NC}"
# Sao lưu file cấu hình hiện tại
[ -f "$HTTPD_CONF" ] && cp -a "$HTTPD_CONF" "$BACKUP_DIR/"
[ -n "$MPM_CONF" ] && [ -f "$MPM_CONF" ] && cp -a "$MPM_CONF" "$BACKUP_DIR/"
[ -n "$DEFAULT_CONF" ] && [ -f "$DEFAULT_CONF" ] && cp -a "$DEFAULT_CONF" "$BACKUP_DIR/"
# 3. TÍNH TOÁN CẤU HÌNH THEO TÀI NGUYÊN HỆ THỐNG
TOTAL_RAM_KB=$(grep MemTotal /proc/meminfo | awk '{print $2}')
TOTAL_RAM_GB=$((TOTAL_RAM_KB / 1024 / 1024))
echo -e "--> Tổng dung lượng RAM hệ thống: ${YELLOW}${TOTAL_RAM_GB} GB${NC}"
# Tính toán MaxRequestWorkers dựa trên RAM
# Trung bình 1 Thread của Event MPM chiếm ~5MB-10MB. 1 Worker Process chiếm ~30MB-50MB.
# Chúng ta sẽ cấu hình an toàn nhưng vẫn đủ lớn để tải luồng video tĩnh.
if [ "$TOTAL_RAM_GB" -le 1 ]; then
MAX_WORKERS=150
THREADS_PER_CHILD=25
elif [ "$TOTAL_RAM_GB" -le 2 ]; then
MAX_WORKERS=250
THREADS_PER_CHILD=25
elif [ "$TOTAL_RAM_GB" -le 4 ]; then
MAX_WORKERS=384
THREADS_PER_CHILD=32
else
MAX_WORKERS=800
THREADS_PER_CHILD=40
fi
echo -e "--> Cấu hình tự động đề xuất MaxRequestWorkers: ${GREEN}$MAX_WORKERS${NC} (ThreadsPerChild: ${GREEN}$THREADS_PER_CHILD${NC})"
# 4. CHUYỂN ĐỔI MPM SANG EVENT MPM (NẾU ĐANG CHẠY PREFORK)
echo -e "${BLUE}--> [Bước 1] Kiểm tra và cấu hình Event MPM...${NC}"
if [ -f "$MPM_CONF" ] && [ -d "/www/server/apache" ]; then
# Đối với aaPanel: Cấu hình Event MPM trong extra/httpd-mpm.conf
# Đảm bảo bật Include conf/extra/httpd-mpm.conf trong httpd.conf
sed -i 's/#Include conf\/extra\/httpd-mpm.conf/Include conf\/extra\/httpd-mpm.conf/g' "$HTTPD_CONF"
# Cập nhật thông số Event MPM trong httpd-mpm.conf
# Tạo đoạn cấu hình mới
NEW_MPM="
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit $THREADS_PER_CHILD
ThreadsPerChild $THREADS_PER_CHILD
MaxRequestWorkers $MAX_WORKERS
MaxConnectionsPerChild 10000
"
# Thay thế block mpm_event_module trong httpd-mpm.conf bằng thông số tối ưu
# Tìm vị trí và thay thế bằng cách truyền biến qua môi trường để tránh lỗi ký tự đặc biệt
NEW_MPM="$NEW_MPM" perl -i -0777 -pe 's/.*?<\/IfModule>/$ENV{NEW_MPM}/s' "$MPM_CONF"
echo -e "${GREEN} [OK] Đã cập nhật cấu hình Event MPM trong $MPM_CONF${NC}"
elif [ -f "/etc/httpd/conf.modules.d/00-mpm.conf" ]; then
# CentOS standard: kích hoạt event, tắt prefork/worker
sed -i 's/^LoadModule mpm_prefork_module/#LoadModule mpm_prefork_module/g' "$MPM_CONF"
sed -i 's/^LoadModule mpm_worker_module/#LoadModule mpm_worker_module/g' "$MPM_CONF"
sed -i 's/^#LoadModule mpm_event_module/LoadModule mpm_event_module/g' "$MPM_CONF"
# Thêm thông số Event MPM vào cuối file
cat >> "$MPM_CONF" <
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit $THREADS_PER_CHILD
ThreadsPerChild $THREADS_PER_CHILD
MaxRequestWorkers $MAX_WORKERS
MaxConnectionsPerChild 10000
EOF
echo -e "${GREEN} [OK] Đã kích hoạt và tối ưu Event MPM trong $MPM_CONF${NC}"
elif [ -d "/etc/apache2" ]; then
# Ubuntu standard
a2dismod mpm_prefork || true
a2dismod mpm_worker || true
a2enmod mpm_event || true
# Tối ưu cấu hình trong /etc/apache2/mods-available/mpm_event.conf
MPM_EVENT_DEB="/etc/apache2/mods-available/mpm_event.conf"
if [ -f "$MPM_EVENT_DEB" ]; then
cp -a "$MPM_EVENT_DEB" "$BACKUP_DIR/"
cat > "$MPM_EVENT_DEB" <
StartServers 3
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit $THREADS_PER_CHILD
ThreadsPerChild $THREADS_PER_CHILD
MaxRequestWorkers $MAX_WORKERS
MaxConnectionsPerChild 10000
EOF
fi
echo -e "${GREEN} [OK] Đã kích hoạt và tối ưu mpm_event trên Ubuntu${NC}"
fi
# 5. TỐI ƯU HÓA KEEPALIVE VÀ TIMEOUTS ĐỂ TRÁNH NGHẼN KẾT NỐI
echo -e "${BLUE}--> [Bước 2] Tối ưu hóa Timeout và Keep-Alive...${NC}"
# Thiết lập các giá trị tối ưu hóa trực tiếp vào httpd.conf
# Giảm Timeout từ 300s -> 60s
# Đảm bảo KeepAlive On, KeepAliveTimeout = 2s hoặc 3s (Tránh giữ kết nối rảnh quá lâu)
# MaxKeepAliveRequests lớn (500) để phục vụ nhiều file tĩnh nhanh trên cùng 1 kết nối
# Cập nhật trong httpd.conf hoặc các file default
if [ -f "$DEFAULT_CONF" ] && [ -d "/www/server/apache" ]; then
# aaPanel sử dụng conf/extra/httpd-default.conf
sed -i 's/#Include conf\/extra\/httpd-default.conf/Include conf\/extra\/httpd-default.conf/g' "$HTTPD_CONF"
# Sửa trong httpd-default.conf
sed -i 's/^Timeout .*/Timeout 60/g' "$DEFAULT_CONF"
sed -i 's/^KeepAlive .*/KeepAlive On/g' "$DEFAULT_CONF"
sed -i 's/^MaxKeepAliveRequests .*/MaxKeepAliveRequests 500/g' "$DEFAULT_CONF"
sed -i 's/^KeepAliveTimeout .*/KeepAliveTimeout 2/g' "$DEFAULT_CONF"
echo -e "${GREEN} [OK] Đã cập nhật Timeout & Keep-Alive trong $DEFAULT_CONF${NC}"
else
# Bản phân phối tiêu chuẩn hoặc không có file default tách biệt
# Xóa các dòng cũ nếu có trong httpd.conf
sed -i '/^Timeout /d' "$HTTPD_CONF"
sed -i '/^KeepAlive /d' "$HTTPD_CONF"
sed -i '/^MaxKeepAliveRequests /d' "$HTTPD_CONF"
sed -i '/^KeepAliveTimeout /d' "$HTTPD_CONF"
# Thêm cấu hình tối ưu vào cuối file httpd.conf
cat >> "$HTTPD_CONF" < [Bước 3] Kích hoạt và cấu hình mod_reqtimeout (Chống Slow Connection)...${NC}"
# Đảm bảo module mod_reqtimeout được nạp
if [ -d "/www/server/apache" ]; then
# Kích hoạt module trong httpd.conf của aaPanel
sed -i 's/#LoadModule reqtimeout_module/LoadModule reqtimeout_module/g' "$HTTPD_CONF"
fi
# Thêm block cấu hình bảo vệ vào httpd.conf nếu chưa có
if ! grep -q "mod_reqtimeout_module" "$HTTPD_CONF"; then
cat >> "$HTTPD_CONF" <
# Header: Cho phép tối đa 20s nhận Header, nếu tốc độ tối thiểu 500 bytes/s cho phép kéo dài đến tối đa 40s.
# Body: Cho phép tối đa 20s nhận Body, nếu tốc độ tối thiểu 500 bytes/s cho phép kéo dài thêm.
RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500
EOF
echo -e "${GREEN} [OK] Đã thêm cấu hình bảo vệ RequestReadTimeout vào $HTTPD_CONF${NC}"
else
echo -e "${YELLOW} [!] Cấu hình mod_reqtimeout đã tồn tại trước đó, giữ nguyên.${NC}"
fi
# 7. KIỂM TRA VÀ KHỞI ĐỘNG LẠI APACHE
echo -e "${BLUE}--> [Bước 4] Kiểm tra cú pháp cấu hình Apache...${NC}"
TEST_CMD=""
if [ -d "/www/server/apache" ]; then
TEST_CMD="/www/server/apache/bin/apachectl configtest"
elif command -v apache2ctl >/dev/null 2>&1; then
TEST_CMD="apache2ctl configtest"
else
TEST_CMD="apachectl configtest"
fi
if $TEST_CMD; then
echo -e "${GREEN}--> Cú pháp cấu hình hợp lệ! Đang khởi động lại dịch vụ Apache...${NC}"
if [ -x "$SERVICE_CMD" ]; then
$SERVICE_CMD restart || $SERVICE_CMD start
else
$SERVICE_CMD
fi
echo -e "${GREEN}=== TỐI ƯU HÓA APACHE THÀNH CÔNG ===${NC}"
echo -e "Hệ thống Apache hiện tại đã được cấu hình chạy ${YELLOW}Event MPM${NC} với các tham số kết nối ngắn để triệt tiêu tình trạng treo cổ chai."
else
echo -e "${RED}LỖI: Cú pháp cấu hình Apache không hợp lệ. Tiến hành khôi phục cấu hình ban đầu...${NC}"
cp -a "$BACKUP_DIR"/* "$APA_DIR/" || true
if [ -f "$BACKUP_DIR/httpd-mpm.conf" ] && [ -d "$APA_DIR/conf/extra" ]; then
cp -a "$BACKUP_DIR/httpd-mpm.conf" "$APA_DIR/conf/extra/" || true
fi
if [ -f "$BACKUP_DIR/httpd-default.conf" ] && [ -d "$APA_DIR/conf/extra" ]; then
cp -a "$BACKUP_DIR/httpd-default.conf" "$APA_DIR/conf/extra/" || true
fi
echo -e "${GREEN}--> Đã khôi phục trạng thái cũ. Vui lòng kiểm tra lại log lỗi Apache.${NC}"
$TEST_CMD || true
exit 3
fi