# 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.

Source: https://zopanel.net/vi/blog/lemp-stack-ubuntu  
Updated: 2026-10-21

## Ý 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 **L**inux, **E**ngine-X (nginx), **M**ariaDB (hoặc MySQL) và **P**HP. 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:

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

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

```bash
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](/vi/blog/secure-ubuntu-vps).

## Bước 2: Cài nginx

```bash
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

```bash
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):

```bash
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

```bash
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:

```ini
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:

```bash
sudo mkdir -p /var/www/example.com/public
sudo nano /etc/nginx/sites-available/example.com
```

```nginx
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:

```bash
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](https://nginx.org/en/docs/).

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

```bash
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:

```bash
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](https://certbot.eff.org/) và [bài về SSL Let's Encrypt](/vi/blog/free-ssl-lets-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:

```bash
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:

```bash
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](/vi/docs/install), [thành phần tuỳ chọn](/vi/docs/components) và [cách tạo website và chọn phiên bản PHP](/vi/docs/hosting).

## 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á](/vi/pricing) 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.
