Cài Nginx, PHP, MariaDB trên Ubuntu 24.04 (LEMP) từng bước

Hướng dẫn cài nginx php mariadb trên Ubuntu 24.04 và Debian 12: tường lửa, PHP-FPM, server block, database, SSL Let's Encrypt và các lỗi bảo mật hay gặp.

Sơ đồ LEMP: nginx nhận request, PHP-FPM chạy PHP, MariaDB lưu dữ liệu

Ý chính

  • Ubuntu 24.04 có sẵn nginx 1.24, PHP 8.3 và MariaDB 10.11 trong kho chính thức.
  • nginx chuyển file PHP cho PHP-FPM qua Unix socket /run/php/php8.3-fpm.sock.
  • Mỗi website nên có user Linux và pool PHP-FPM riêng để một site bị hack không đọc được site khác.
  • Luôn mở cổng SSH trong UFW trước khi bật tường lửa.

Để cài nginx, PHP và MariaDB (LEMP) trên Ubuntu 24.04, bạn chỉ cần kho gói chính thức: apt install nginx mariadb-server php8.3-fpm php8.3-mysql, chạy mariadb-secure-installation, rồi tạo server block nginx chuyển file .php tới socket /run/php/php8.3-fpm.sock. Toàn bộ quá trình mất khoảng 20 phút trên một VPS mới, kể cả cấp SSL miễn phí.

Bài viết đi qua từng bước với lệnh đã kiểm tra trên Ubuntu 24.04 (và ghi chú khác biệt cho Debian 12), giải thích vì sao mỗi bước tồn tại, và chỉ ra những chỗ mà hướng dẫn ngắn thường bỏ qua: tường lửa, quyền file, pool PHP riêng cho từng website. Cuối bài là phần so sánh khi nào nên tự cài và khi nào nên dùng control panel.

Cài nginx, PHP, MariaDB trên Ubuntu: LEMP là gì, vì sao chọn nginx?

LEMP gồm Linux, Engine-X (nginx), MariaDB (hoặc MySQL) và PHP. Khác với LAMP dùng Apache với mod_php, nginx không chạy PHP bên trong tiến trình web server. Nó phục vụ file tĩnh rất nhanh và chuyển request PHP cho PHP-FPM, một dịch vụ riêng quản lý các worker PHP.

Cách tách này có hai lợi ích thực tế: nginx dùng ít RAM khi có nhiều kết nối đồng thời, và mỗi website có thể chạy PHP dưới user Linux riêng. Nhược điểm: nginx không đọc .htaccess, nên quy tắc rewrite phải viết trong cấu hình nginx.

Ubuntu 24.04 và Debian 12 có sẵn phiên bản nào?

Thành phần Ubuntu 24.04 Debian 12
nginx 1.24 1.22
PHP 8.3 8.2
MariaDB 10.11 10.11

Các nhánh phiên bản trên cố định trong suốt vòng đời bản phát hành; bản vá bảo mật được backport. Kiểm tra chính xác trên server bằng apt policy nginx mariadb-server php8.3-fpm. Nếu cần nhiều phiên bản PHP cùng lúc, bạn phải thêm kho ngoài (PPA của Ondřej Surý trên Ubuntu, packages.sury.org trên Debian); bài này chỉ dùng kho chính thức.

Trên Debian 12, thay mọi chỗ 8.3 trong bài bằng 8.2.

Bước 1: Cập nhật hệ thống và bật tường lửa

Đăng nhập VPS bằng user có sudo và chạy:

sudo apt update && sudo apt full-upgrade -y

Bật tường lửa UFW, mở SSH trước tiên:

sudo apt install ufw
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status

Nếu SSH của bạn chạy ở cổng khác 22, đổi số cho đúng. Bật UFW mà quên cổng SSH là cách nhanh nhất để tự khoá mình khỏi server; khi đó chỉ còn console của nhà cung cấp VPS cứu được. Với các bước bảo mật khác cho server mới, xem hướng dẫn bảo mật VPS Ubuntu.

Bước 2: Cài nginx

sudo apt install nginx
sudo systemctl enable --now nginx
curl -I http://localhost

Dòng HTTP/1.1 200 OK cho biết nginx đã chạy. Mở http://IP-của-VPS trên trình duyệt sẽ thấy trang chào mặc định.

Bước 3: Cài MariaDB và bảo mật ban đầu

sudo apt install mariadb-server
sudo mariadb-secure-installation

Trình hướng dẫn hỏi vài câu. Trên Ubuntu và Debian, user root của MariaDB mặc định xác thực bằng unix_socket, nghĩa là chỉ root của hệ điều hành (qua sudo mariadb) đăng nhập được, không cần mật khẩu. Đây là thiết lập an toàn, hãy giữ nguyên. Trả lời Y cho các câu xoá user ẩn danh, cấm root đăng nhập từ xa, xoá database test.

MariaDB mặc định chỉ lắng nghe trên 127.0.0.1. Đừng mở cổng 3306 ra internet; nếu cần kết nối từ xa, dùng SSH tunnel hoặc chỉ cho phép đúng IP của bạn.

Tạo database và user cho website (mỗi website một user riêng):

sudo mariadb -e "CREATE DATABASE example_wp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'example_wp'@'localhost' IDENTIFIED BY 'đổi-mật-khẩu-mạnh';
GRANT ALL PRIVILEGES ON example_wp.* TO 'example_wp'@'localhost';"

Bước 4: Cài PHP-FPM và extension cần thiết

sudo apt install php8.3-fpm php8.3-mysql php8.3-curl php8.3-gd \
  php8.3-mbstring php8.3-xml php8.3-zip php8.3-intl
sudo systemctl status php8.3-fpm

Danh sách extension trên đủ cho WordPress và phần lớn ứng dụng PHP phổ biến. OPcache được cài sẵn cùng PHP-FPM. Đừng cài gói php8.3 không kèm hậu tố: trên một số hệ thống nó kéo theo Apache và libapache2-mod-php, khiến Apache tranh cổng 80 với nginx.

Chỉnh vài giá trị trong /etc/php/8.3/fpm/php.ini nếu ứng dụng cần:

upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M

Rồi sudo systemctl reload php8.3-fpm.

Bước 5: Tạo server block nginx cho website

Tạo thư mục website và file cấu hình:

sudo mkdir -p /var/www/example.com/public
sudo nano /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

    location ~ /\.(?!well-known) {
        deny all;
    }
}

snippets/fastcgi-php.conf có sẵn trong gói nginx của Ubuntu/Debian và lo phần tham số FastCGI. Khối cuối chặn file ẩn như .env, .git nhưng vẫn cho Let's Encrypt dùng .well-known.

Kích hoạt và kiểm tra:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

Luôn chạy nginx -t trước khi reload. Một dấu chấm phẩy thiếu có thể làm nginx không khởi động lại được, kéo theo mọi website trên server. Tham khảo thêm tài liệu nginx.

Bước 6: Kiểm tra PHP chạy đúng

echo '<?php phpinfo();' | sudo tee /var/www/example.com/public/info.php
curl -s http://localhost/info.php -H 'Host: example.com' | grep -m1 'PHP Version'
sudo rm /var/www/example.com/public/info.php

Xoá info.php ngay sau khi kiểm tra: trang này để lộ cấu hình server cho bất kỳ ai.

Bước 7: Cài SSL miễn phí với Let's Encrypt

Trỏ bản ghi A của example.com và www.example.com về IP của VPS, rồi:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run

Certbot sửa server block để thêm HTTPS và chuyển hướng HTTP sang HTTPS, đồng thời tạo timer gia hạn tự động. Xem thêm hướng dẫn của Certbot và bài về SSL Let's Encrypt.

Bước 8: Tách quyền khi có nhiều website

Cấu hình mặc định ở trên chạy PHP của mọi website dưới cùng user www-data. Với một website thì ổn. Với nhiều website, đó là lỗ hổng lớn nhất của LEMP tự cài: một plugin bị hack trên site A đọc được wp-config.php của site B, vì cùng một user.

Cách khắc phục là mỗi website một user Linux và một pool PHP-FPM riêng:

sudo adduser --system --group --no-create-home --home /var/www/example.com example
sudo chown -R example:example /var/www/example.com/public
sudo cp /etc/php/8.3/fpm/pool.d/www.conf /etc/php/8.3/fpm/pool.d/example.conf

Trong example.conf, đổi [www] thành [example], user = example, group = example, listen = /run/php/php8.3-fpm-example.sock, giữ listen.owner = www-data và listen.group = www-data để nginx kết nối được. Sau đó trỏ fastcgi_pass của server block sang socket mới, reload PHP-FPM và nginx. Đặt quyền thư mục 750 và cân nhắc open_basedir cho từng pool.

Làm việc này cho mười website thì vẫn được. Làm cho một trăm website, cùng giới hạn CPU/RAM, quota đĩa, sao lưu và gia hạn SSL, thì đó chính là công việc của một control panel.

Tự cài LEMP hay dùng control panel?

Tiêu chí Tự cài LEMP Control panel (ví dụ ZoPanel)
Hiểu sâu hệ thống Rất tốt Ít phải đụng tới
Thời gian thêm một website 10–20 phút Khoảng 1 phút
Cách ly giữa các website Tự làm từng pool, từng user Có sẵn cho mọi tài khoản
Nhiều phiên bản PHP Tự thêm kho, tự quản lý Chọn trong danh sách
Sao lưu, SSL, giám sát Tự viết script, cron Có sẵn trong giao diện
Phù hợp 1–3 website, người thích tự kiểm soát Agency, nhà cung cấp hosting, nhiều website

ZoPanel cài chính bộ LEMP này: nginx, MariaDB, PHP từ kho của Ondřej Surý (PHP 7.4 đến 8.4), kèm UFW, Fail2ban và SFTP chroot. Bộ đệm InnoDB của MariaDB được đặt bằng 20% RAM. Mỗi tài khoản hosting là một user Linux riêng, với pool PHP-FPM riêng có open_basedir, và chạy trong slice systemd riêng có giới hạn CPU, RAM, số tiến trình lấy từ gói hosting. Pool của website không có truy cập tự ngủ để tiết kiệm RAM. Cài trên Ubuntu 22.04/24.04 hoặc Debian 12/13 bằng một lệnh:

curl -fsSL https://get.zopanel.net | sudo bash

Trình cài đặt yêu cầu server mới, chưa có web server hay panel khác, nên đừng chạy nó trên server bạn vừa tự cài LEMP. Xem hướng dẫn cài đặt, thành phần tuỳ chọn và cách tạo website và chọn phiên bản PHP.

Lỗi thường gặp khi cài LEMP

  • 502 Bad Gateway: nginx không kết nối được PHP-FPM. Kiểm tra fastcgi_pass có đúng tên socket không (ls /run/php/) và PHP-FPM có đang chạy.
  • Trình duyệt tải file .php về thay vì chạy: thiếu khối location ~ \.php$ hoặc chưa reload nginx.
  • 404 cho mọi trang trừ trang chủ (WordPress, Laravel): thiếu try_files ... /index.php?$args.
  • Access denied for user: sai mật khẩu database hoặc user được tạo với host khác localhost.
  • Apache chiếm cổng 80: đã lỡ cài gói php8.3. Gỡ Apache bằng sudo apt purge apache2 (kiểm tra trước là không có gì đang dùng nó).
  • Certbot báo lỗi xác thực: DNS chưa trỏ đúng, hoặc tường lửa của nhà cung cấp VPS chưa mở cổng 80.

Kết luận

Cài LEMP trên Ubuntu 24.04 không khó: kho chính thức đã có nginx 1.24, PHP 8.3 và MariaDB 10.11, đủ cho phần lớn ứng dụng PHP hiện nay. Phần đáng giá nhất của việc tự cài là hiểu cách nginx, PHP-FPM và MariaDB phối hợp với nhau. Phần tốn công nhất là giữ cho nhiều website cách ly, được sao lưu và luôn có SSL. Nếu bạn đến điểm đó, hãy thử gói Free của ZoPanel (3 tài khoản hosting, 10 website, 10 database, không giới hạn thời gian, chạy được nhiều phiên bản PHP) trên một VPS mới, và xem bảng giá khi cần nhiều hơn.

Câu hỏi thường gặp

Ubuntu 24.04 dùng PHP phiên bản mấy?

Kho chính thức của Ubuntu 24.04 có PHP 8.3, gói php8.3-fpm. Debian 12 có PHP 8.2. Nếu cần phiên bản khác, phải thêm kho ngoài như PPA của Ondřej Surý.

Nên dùng MariaDB hay MySQL cho LEMP?

Cả hai đều chạy tốt WordPress và phần lớn ứng dụng PHP. MariaDB có sẵn trong kho của Ubuntu và Debian và là lựa chọn mặc định của nhiều bản phân phối, nên cài và cập nhật đơn giản hơn. Chỉ chọn MySQL khi ứng dụng yêu cầu tính năng riêng của MySQL.

Vì sao nginx báo 502 Bad Gateway sau khi cài PHP?

Thường do fastcgi_pass trỏ sai socket hoặc PHP-FPM chưa chạy. Chạy ls /run/php/ để xem tên socket thật và systemctl status php8.3-fpm để kiểm tra dịch vụ, rồi sửa server block và reload nginx.

Có cần mở cổng 3306 của MariaDB không?

Không, nếu website và database nằm cùng server. Mở 3306 ra internet khiến database bị dò mật khẩu liên tục. Khi cần kết nối từ xa, dùng SSH tunnel hoặc chỉ cho phép đúng địa chỉ IP của bạn trong tường lửa.

Cài LEMP xong có cài thêm control panel được không?

Phần lớn control panel, gồm ZoPanel, yêu cầu server mới và từ chối cài khi đã có web server khác, vì sẽ xung đột cấu hình. Hãy cài panel trên VPS mới, rồi chuyển website sang.