Cài đặt LAMP Stack trên Ubuntu 22.04 — Hướng dẫn từng bước cho người mới

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

LAMP Stack là gì và khi nào bạn cần nó?

Nếu bạn mới bắt đầu học lập trình web backend hoặc vừa nhận task deploy một ứng dụng PHP lên server, khả năng cao bạn sẽ cần LAMP Stack. Đây là bộ tứ gồm Linux + Apache + MySQL + PHP — nền tảng chạy WordPress, Laravel, Drupal và hàng trăm ứng dụng PHP khác. Apache một mình chiếm khoảng 30% thị phần web server toàn cầu, nên biết cách dựng LAMP là kỹ năng khá thiết thực.

Mình đã dùng LAMP trên môi trường staging của công ty (Ubuntu 22.04) để test config trước khi đẩy lên production. Bài học nhớ đời: cài đúng thứ tự, cấu hình đúng ngay từ đầu. Làm ngược lại thì mất cả buổi chiều debug những thứ lẽ ra không đáng mất thời gian.

Bài này chọn Apache thay vì Nginx vì nhiều dự án legacy PHP vẫn cần module mod_rewrite.htaccess. Nếu bạn đang tìm cách cài Nginx, blog đã có bài riêng.

Cài đặt từng thành phần

1. Cập nhật hệ thống

Trước khi cài bất cứ thứ gì, luôn cập nhật package list — bỏ qua bước này thì hay gặp conflict phiên bản về sau:

sudo apt update && sudo apt upgrade -y

2. Cài Apache

sudo apt install apache2 -y

Xong rồi, khởi động và bật auto-start:

sudo systemctl start apache2
sudo systemctl enable apache2

Nếu đang dùng UFW, mở port 80:

sudo ufw allow 'Apache'
sudo ufw reload

Truy cập http://<IP-server> trên trình duyệt. Thấy trang “Apache2 Ubuntu Default Page” là ổn.

3. Cài MySQL

sudo apt install mysql-server -y

Chạy script bảo mật — cái này quan trọng, đừng bỏ qua:

sudo mysql_secure_installation

Script hỏi bạn một loạt câu hỏi. Với môi trường production, mình luôn chọn như sau:

  • VALIDATE PASSWORD component: Y (bật kiểm tra độ mạnh mật khẩu)
  • Remove anonymous users: Y
  • Disallow root login remotely: Y
  • Remove test database: Y
  • Reload privilege tables: Y

Đăng nhập MySQL để xác nhận mọi thứ ổn:

sudo mysql -u root -p

4. Cài PHP

Ubuntu 22.04 ship PHP 8.1 trong repo mặc định. Cài luôn các extension hay dùng:

sudo apt install php libapache2-mod-php php-mysql php-cli php-curl php-gd php-mbstring php-xml php-zip -y

Vì sao cần những extension này? Tóm tắt nhanh:

  • php-mysql — kết nối PHP với MySQL/MariaDB
  • php-mbstring — xử lý chuỗi đa byte (cần cho tiếng Việt, tiếng Nhật…)
  • php-xml — xử lý XML, nhiều framework PHP không chạy được nếu thiếu cái này
  • php-zip — WordPress dùng khi cài hoặc update plugin

Kiểm tra phiên bản:

php -v

Cấu hình chi tiết

Tạo Virtual Host cho ứng dụng của bạn

Để code trong /var/www/html mặc định chỉ ổn khi test nhanh. Mình luôn tạo Virtual Host riêng cho mỗi dự án — cách này giúp chạy song song nhiều website trên cùng một server mà không đụng nhau.

Tạo thư mục dự án và phân quyền:

sudo mkdir -p /var/www/myapp/public
sudo chown -R $USER:$USER /var/www/myapp/public
sudo chmod -R 755 /var/www/myapp

Mở file config Virtual Host mới:

sudo nano /etc/apache2/sites-available/myapp.conf

Điền nội dung sau vào:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName myapp.local
    DocumentRoot /var/www/myapp/public

    <Directory /var/www/myapp/public>
        AllowOverride All
        Require all granted
    </Directory>

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

Bật site và module mod_rewrite — Laravel và WordPress đều cần cái này:

sudo a2ensite myapp.conf
sudo a2enmod rewrite
sudo systemctl restart apache2

Tạo database và user MySQL cho ứng dụng

Không bao giờ dùng root để kết nối từ ứng dụng — tạo user riêng với quyền hạn tối thiểu:

sudo mysql -u root -p

CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Lưu ý: Dùng utf8mb4 thay vì utf8 để hỗ trợ đầy đủ Unicode, kể cả emoji. WordPress từng có bug lưu emoji bị lỗi chính vì charset utf8 chỉ hỗ trợ 3 byte, trong khi emoji cần 4 byte.

Điều chỉnh cấu hình PHP cho production

File config PHP cho Apache ở /etc/php/8.1/apache2/php.ini. Mình hay chỉnh ngay mấy tham số này sau khi cài xong:

sudo nano /etc/php/8.1/apache2/php.ini

Dùng Ctrl+W trong nano để tìm nhanh từng dòng, rồi sửa theo:

; Giới hạn upload file (tùy nhu cầu)
upload_max_filesize = 64M
post_max_size = 64M

; Tăng memory limit nếu ứng dụng nặng
memory_limit = 256M

; Thời gian chạy tối đa (giây)
max_execution_time = 60

; Tắt hiển thị lỗi trên production (bật khi dev)
display_errors = Off
log_errors = On
error_log = /var/log/php_errors.log

Lưu lại, sau đó restart Apache để áp dụng:

sudo systemctl restart apache2

Kiểm tra và Monitoring

Test PHP hoạt động đúng

Tạo file phpinfo.php để kiểm tra:

sudo nano /var/www/myapp/public/phpinfo.php
<?php
phpinfo();
?>

Truy cập http://<IP-server>/phpinfo.php — bạn sẽ thấy trang thông tin PHP đầy đủ. Kiểm tra xem các extension đã cài (mysql, mbstring, xml…) có xuất hiện không.

Xóa ngay sau khi xem xong — để file này public là lỗ hổng bảo mật nghiêm trọng. Hacker nhìn vào đây là biết toàn bộ cấu hình server của bạn:

sudo rm /var/www/myapp/public/phpinfo.php

Kiểm tra kết nối PHP → MySQL

Tạo file test kết nối database:

<?php
$conn = new mysqli('localhost', 'myapp_user', 'StrongPassword123!', 'myapp_db');

if ($conn->connect_error) {
    die('Lỗi kết nối: ' . $conn->connect_error);
}

echo 'Kết nối MySQL thành công! Server version: ' . $conn->server_info;
$conn->close();
?>

Thấy “Kết nối MySQL thành công” là LAMP Stack đã hoạt động end-to-end. Nhớ xóa file test này sau khi confirm.

Ba lệnh kiểm tra service cần bookmark

Trước khi thông báo “deploy xong” với team, mình thường chạy nhanh mấy cái này:

# Kiểm tra Apache
sudo systemctl status apache2

# Kiểm tra MySQL
sudo systemctl status mysql

# Xem log Apache realtime
sudo tail -f /var/log/apache2/error.log

# Xem log MySQL
sudo tail -f /var/log/mysql/error.log

Hoặc dùng one-liner gọn hơn:

for svc in apache2 mysql; do
  echo -n "$svc: "
  systemctl is-active $svc
done

Cả hai in ra active là ổn.

Kiểm tra port đang lắng nghe

sudo ss -tlnp | grep -E '(:80|:443|:3306)'

Apache trên port 80, MySQL trên 3306. Lưu ý MySQL chỉ bind 127.0.0.1 — đây là cấu hình an toàn mặc định, không expose ra ngoài internet.

Các lỗi thường gặp

  • Apache không start: Chạy sudo apachectl configtest trước. Nguyên nhân số một thường là lỗi syntax config — thiếu dấu ngoặc, hoặc port 80 bị process khác chiếm mất.
  • PHP không load được extension: Nhìn vào /etc/php/8.1/apache2/conf.d/ — mỗi extension có file .ini riêng. Xác nhận nhanh bằng php -m | grep mysql.
  • MySQL từ chối kết nối: Hay bị nhầm ở đây — 'user'@'localhost''user'@'127.0.0.1' là hai user khác nhau trong MySQL. Kiểm tra lại host khi tạo user.

Share: