Hướng dẫn cài đặt và cấu hình Apache2 trên Ubuntu 22.04 từ A đến Z

Development tutorial - IT technology blog
Development tutorial - IT technology blog

Vấn đề mình gặp khi deploy web lần đầu

Hồi mới bắt đầu với Linux server, mình từng deploy một project PHP lên VPS Ubuntu rồi ngồi thắc mắc tại sao truy cập IP lại ra trang mặc định của Apache, còn project của mình thì không thấy đâu. Mất gần nửa ngày mới vỡ ra: cài Apache xong là chưa đủ — còn phải cấu hình virtual host, phân quyền thư mục, và mở đúng port trên firewall.

Khoảng 6 tháng chạy Apache2 trên production — gồm một web app của team 5 developer — mình đã qua đủ kiểu lỗi “ngớ ngẩn” mà docs chính thức không đề cập. Bài này là quy trình mình đang thực sự dùng, không phải copy-paste từ manual.

Tại sao Apache2 lại gây rắc rối ngay từ đầu?

Vấn đề không phải Apache phức tạp. Ubuntu 22.04 có một vài thay đổi so với các bản cũ mà nhiều tutorial chưa kịp cập nhật:

  • UFW mặc định chặn port 80/443 — cài xong Apache nhưng firewall vẫn block traffic.
  • Cấu trúc thư mục /etc/apache2/ dùng hệ thống sites-available / sites-enabled — khác hoàn toàn với cách ghi trong nhiều tài liệu cũ.
  • PHP-FPM vs mod_php — từ PHP 7.4 trở đi, Ubuntu khuyến khích PHP-FPM nhưng cần cấu hình thêm, không tự động như trước.

Hiểu được 3 điểm này là hiểu được 80% lý do tại sao Apache “hoạt động mà không hoạt động” trên máy bạn.

Cài đặt Apache2

Update package list rồi cài:

sudo apt update
sudo apt install apache2 -y

Kiểm tra Apache đã chạy chưa:

sudo systemctl status apache2

Thấy active (running) là ổn. Nếu ra failed, chạy sudo journalctl -xe để xem lý do cụ thể. Enable auto-start khi reboot:

sudo systemctl enable apache2

Mở firewall đúng cách với UFW

Đây là bước hay bị bỏ qua nhất. Apache cài sẵn profile cho UFW:

# Xem các profile có sẵn
sudo ufw app list

# Cho phép HTTP và HTTPS
sudo ufw allow 'Apache Full'

# Nếu chỉ cần HTTP trước
sudo ufw allow 'Apache'

# Bật UFW nếu chưa bật
sudo ufw enable
sudo ufw status

Sau bước này, gõ IP server vào trình duyệt sẽ thấy trang “Apache2 Ubuntu Default Page” — xác nhận mọi thứ đang chạy đúng.

Cấu hình Virtual Host — theo chuẩn Ubuntu

Mình thấy nhiều người hay chỉnh thẳng vào /etc/apache2/apache2.conf, đây là cách làm sai. Trên Ubuntu, mỗi website nên có một file cấu hình riêng trong /etc/apache2/sites-available/.

Tạo thư mục cho website

sudo mkdir -p /var/www/mywebsite.com/public
sudo chown -R $USER:$USER /var/www/mywebsite.com
sudo chmod -R 755 /var/www/mywebsite.com

Tạo file cấu hình virtual host

sudo nano /etc/apache2/sites-available/mywebsite.com.conf

Nội dung file:

<VirtualHost *:80>
    ServerName mywebsite.com
    ServerAlias www.mywebsite.com
    ServerAdmin [email protected]
    DocumentRoot /var/www/mywebsite.com/public

    <Directory /var/www/mywebsite.com/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/mywebsite.com-error.log
    CustomLog ${APACHE_LOG_DIR}/mywebsite.com-access.log combined
</VirtualHost>

Kích hoạt site và reload Apache

# Enable site mới
sudo a2ensite mywebsite.com.conf

# Disable site mặc định nếu không cần
sudo a2dissite 000-default.conf

# Kiểm tra cú pháp config
sudo apache2ctl configtest

# Reload Apache
sudo systemctl reload apache2

Lệnh apache2ctl configtest là bước mình luôn chạy trước khi reload — tránh tình huống Apache crash vì config sai cú pháp.

Bật module cần thiết

Apache2 trên Ubuntu dùng lệnh a2enmod để bật module. Một số module hay dùng:

# Bắt buộc nếu dùng .htaccess với WordPress/Laravel
sudo a2enmod rewrite

# SSL
sudo a2enmod ssl

# Nén gzip cho tĩnh
sudo a2enmod deflate

# Header security
sudo a2enmod headers

sudo systemctl restart apache2

Với dự án team 5 developer, mình gộp 4 lệnh này vào script bootstrap server. Chạy một lần là xong — không còn cảnh dev và production lệch module rồi ngồi debug cả buổi.

Cài đặt SSL với Let’s Encrypt

Domain đã trỏ về server rồi thì Certbot là nhanh nhất:

sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d mywebsite.com -d www.mywebsite.com

Certbot tự sửa file .conf của bạn, thêm cấu hình SSL port 443, và tạo redirect từ HTTP sang HTTPS. Chứng chỉ có hạn 90 ngày nhưng auto-renew đã được set sẵn qua systemd timer:

# Kiểm tra timer auto-renew
sudo systemctl status certbot.timer

# Test thử renewal
sudo certbot renew --dry-run

Tổ chức nhiều website trên 1 VPS

Sau khi chạy nhiều project trên cùng VPS, mình đúc kết ra cấu trúc này:

/var/www/
├── site1.com/
│   └── public/         # DocumentRoot
├── site2.com/
│   └── public/
└── site3.com/
    └── public/

/etc/apache2/
├── sites-available/
│   ├── site1.com.conf
│   ├── site2.com.conf
│   └── site3.com.conf
└── sites-enabled/      # Chỉ chứa symlink, đừng tạo file ở đây

Nguyên tắc: mỗi domain một file conf riêng, dùng a2ensite/a2dissite để bật tắt — không bao giờ sửa thẳng sites-enabled.

Đọc log khi có lỗi

9/10 lần gặp lỗi Apache, câu trả lời nằm ngay trong error log:

# Xem lỗi real-time
sudo tail -f /var/log/apache2/error.log

# Xem log theo domain (nếu đã cấu hình custom log)
sudo tail -f /var/log/apache2/mywebsite.com-error.log

# Xem access log
sudo tail -f /var/log/apache2/mywebsite.com-access.log

Lỗi 403 Forbidden? Thường là phân quyền thư mục sai hoặc thiếu AllowOverride All trong config. Lỗi 500? Error log sẽ chỉ ra ngay dòng lỗi cụ thể — không cần đoán mò.

Tóm tắt quy trình chuẩn

  1. Cài Apache2 → enable service
  2. Mở firewall với UFW (Apache Full)
  3. Tạo thư mục website với đúng permission
  4. Tạo file .conf trong sites-available
  5. Enable site bằng a2ensite, test config, reload
  6. Bật các module cần thiết (rewrite, ssl, …)
  7. Cài SSL với Certbot

Thực ra Apache2 không đáng sợ như nhiều người nghĩ. Phần lớn trường hợp server “không vào được”, nguyên nhân chỉ là UFW chưa mở port hoặc virtual host chưa enable. Kiểm tra 2 thứ đó trước — rồi mới bắt đầu tìm nguyên nhân phức tạp hơn.

Share: