---
title: "Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) stack trên Ubuntu 20.04"
description: "Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) stack trên Ubuntu 20.04"
url: https://cloudfly.vn/techblog/cach-cai-dat-linux-apache-mysql-php-lamp-stack-tren-ubuntu-2004
image: https://media.cloudfly.vn/posts/cach-cai-dat-Linux-Apache-MySQL-PHP-LAMP-stack-tren-Ubuntu-20.04_KSDOj7T.png
---

# Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) stack trên Ubuntu 20.04

## Giới thiệu

“LAMP” stack là một nhóm phần mềm nguồn mở thường được cài đặt cùng nhau để cho phép máy chủ lưu trữ các trang web động và ứng dụng web được viết bằng PHP. Thuật ngữ này là từ viết tắt đại diện cho hệ điều hành **L**inux, với máy chủ web **A**pache. Dữ liệu trang web được lưu trữ trong cơ sở dữ liệu **M**ySQL và nội dung động (dynamic content) được xử lý bởi **P**HP.

Trong hướng dẫn này, bạn sẽ thiết lập LAMP stack trên máy chủ Ubuntu 20.04.

## Điều kiện tiên quyết

Để hoàn thành hướng dẫn này, bạn cần có máy chủ Ubuntu 20.04 với tài khoản non-root `sudo`-enabled user và tường lửa cơ bản. Điều này có thể được thiết lập cấu hình bằng hướng dẫn thiết lập máy chủ ban đầu của chúng tôi cho Ubuntu 20.04.

## Bước 1 — Cài đặt Apache và cập nhật tường lửa

Máy chủ web Apache là một trong những máy chủ web phổ biến nhất trên thế giới. Nó có nhiều tài liệu, có một cộng đồng người dùng tích cực và đã được sử dụng rộng rãi trong phần lớn lịch sử của web, điều này làm cho nó trở thành một lựa chọn tuyệt vời để lưu trữ một trang web.

Bắt đầu bằng cách cập nhật bộ đệm của trình quản lý gói (package manager cache). Nếu đây là lần đầu tiên bạn sử dụng `sudo` trong phiên này, bạn sẽ được nhắc cung cấp mật khẩu người dùng của mình để xác nhận rằng bạn có quyền quản lý các gói hệ thống với `apt`.
```command
sudo apt update
```

Sau đó, cài đặt Apache với:
```command
sudo apt install apache2
```

Bạn cũng sẽ được nhắc xác nhận cài đặt của Apache bằng cách nhấn `Y`, sau đó nhấn `ENTER`.

Sau khi cài đặt xong, bạn sẽ cần điều chỉnh cài đặt tường lửa của mình để cho phép lưu lượng HTTP. UFW có các cấu hình ứng dụng khác nhau mà bạn có thể tận dụng để đạt được điều đó. Để liệt kê tất cả các cấu hình ứng dụng UFW hiện có, bạn có thể chạy:
```command
sudo ufw app list
```

Bạn sẽ thấy đầu ra như thế này:
```
[secondary_label Output]
Available applications:
  <^>Apache<^>
  <^>Apache Full<^>
  <^>Apache Secure<^>
  OpenSSH
```

Đây là ý nghĩa của từng cấu hình này:

* **Apache**: Cấu hình này chỉ mở cổng `80` (lưu lượng truy cập web bình thường, không được mã hóa).
* **Apache Full**: Cấu hình này mở cả cổng 80 (lưu lượng truy cập web bình thường, không được mã hóa) và cổng 443 (lưu lượng được mã hóa TLS/SSL).
* **Apache Secure**: Cấu hình này chỉ mở cổng `443` (lưu lượng được mã hóa TLS/SSL).

Hiện tại, tốt nhất là chỉ cho phép kết nối trên cổng `8`0, vì đây là bản cài đặt Apache mới và bạn vẫn chưa có chứng chỉ TLS/SSL được thiết lập cấu hình để cho phép lưu lượng HTTPS trên máy chủ của mình.

Để chỉ cho phép lưu lượng truy cập trên cổng `80`, hãy sử dụng cấu hình `Apache`:
```command
sudo ufw allow in "Apache"
```

Bạn có thể xác minh thay đổi bằng:
```command
sudo ufw status
```

```
[secondary_label Output]
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                                
<^>Apache                     ALLOW       Anywhere<^>                  
OpenSSH (v6)               ALLOW       Anywhere (v6)                    
<^>Apache (v6)                ALLOW       Anywhere (v6)<^>
```

Lưu lượng truy cập trên cổng `80` hiện được phép thông qua tường lửa.

Bạn có thể thực hiện kiểm tra tại chỗ ngay lập tức để xác minh rằng mọi thứ diễn ra theo đúng kế hoạch bằng cách truy cập địa chỉ IP công cộng của máy chủ trong trình duyệt web của bạn (xem ghi chú dưới tiêu đề tiếp theo để biết địa chỉ IP công cộng của bạn là gì nếu bạn không có thông tin này đã sẵn sàng):
```custom_prefix()
http://<^>your_server_ip<^>
```

Bạn sẽ thấy trang web Apache Ubuntu 20.04 mặc định, trang này dành cho mục đích thử nghiệm và thông tin. Nó sẽ trông giống như thế này:

![description image](https://media.cloudfly.vn/posts/small_apache_default_1804.png)

Nếu bạn thấy trang này, thì máy chủ web của bạn hiện đã được cài đặt đúng cách và có thể truy cập thông qua tường lửa của bạn.

### Cách tìm địa chỉ IP công cộng của máy chủ của bạn

Nếu bạn không biết địa chỉ IP công cộng của máy chủ của mình là gì, bạn có thể tìm thấy địa chỉ đó bằng một số cách. Thông thường, đây là địa chỉ bạn sử dụng để kết nối với máy chủ của mình thông qua SSH.

Có một vài cách khác nhau để làm điều này từ dòng lệnh. Trước tiên, bạn có thể sử dụng các công cụ `iproute2` để lấy địa chỉ IP của mình bằng cách nhập:
```command
ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'
```

Điều này sẽ cung cấp cho bạn hai hoặc ba dòng trở lại. Tất cả chúng đều là địa chỉ chính xác, nhưng máy tính của bạn có thể chỉ sử dụng được một trong số chúng, vì vậy hãy thử từng địa chỉ.

Một phương pháp thay thế là sử dụng tiện ích `curl` để liên hệ với bên ngoài để cho bạn biết họ thấy máy chủ của bạn như thế nào. Điều này được thực hiện bằng cách hỏi một máy chủ cụ thể địa chỉ IP của bạn là gì:
```command
curl http://icanhazip.com
```

Bất kể bạn sử dụng phương pháp nào để lấy địa chỉ IP, hãy nhập địa chỉ đó vào thanh địa chỉ của trình duyệt web để xem trang Apache mặc định.

## Bước 2 — Cài đặt MySQL

Bây giờ bạn đã có một máy chủ web đang hoạt động, bạn cần cài đặt hệ thống cơ sở dữ liệu để có thể lưu trữ và quản lý dữ liệu cho trang web của mình. MySQL là một hệ thống quản lý cơ sở dữ liệu phổ biến được sử dụng trong môi trường PHP.

Một lần nữa, sử dụng `apt` để tải và cài đặt phần mềm này:
```command
sudo apt install mysql-server
```

Khi được nhắc, hãy xác nhận cài đặt bằng cách nhập `Y`, rồi `ENTER`.

Khi quá trình cài đặt kết thúc, bạn nên chạy tập lệnh bảo mật được cài đặt sẵn với MySQL. Tập lệnh này sẽ xóa một số cài đặt mặc định không an toàn và khóa quyền truy cập vào hệ thống cơ sở dữ liệu của bạn. Bắt đầu tập lệnh tương tác bằng cách chạy:
```command
sudo mysql_secure_installation
```

Thao tác này sẽ hỏi bạn có muốn thiết lập cấu hình `VALIDATE PASSWORD PLUGIN` không.

<$>[note]
**Lưu ý:** Kích hoạt tính năng này là một cuộc gọi phán xét. Nếu được bật, mật khẩu không phù hợp với tiêu chí đã chỉ định sẽ bị MySQL từ chối kèm theo lỗi. Việc tắt tính năng xác thực là an toàn, nhưng bạn phải luôn sử dụng mật khẩu mạnh, duy nhất cho thông tin đăng nhập cơ sở dữ liệu.
<$>

Trả lời `Y` nếu có hoặc bất kỳ điều gì khác để tiếp tục mà không cần bật.
```custom_prefix()
VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No:
```

Nếu bạn trả lời “có”, bạn sẽ được yêu cầu chọn mức độ xác thực mật khẩu. Hãy nhớ rằng nếu bạn nhập `2` cho mức mạnh nhất, bạn sẽ gặp lỗi khi cố gắng đặt bất kỳ mật khẩu nào không chứa số, chữ hoa và chữ thường, ký tự đặc biệt hoặc dựa trên các từ thông dụng trong từ điển.
```
[secondary_label Output]
There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary              file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: <^>1<^>
```

Bất kể bạn có chọn thiết lập `VALIDATE PASSWORD PLUGIN` hay không, máy chủ của bạn tiếp theo sẽ yêu cầu bạn chọn và xác nhận mật khẩu cho MySQL **root** user. Điều này không được nhầm lẫn với **system root**. **Database root** user là người dùng quản trị có đầy đủ đặc quyền đối với hệ thống cơ sở dữ liệu. Mặc dù phương thức xác thực mặc định cho MySQL root user không sử dụng mật khẩu, **ngay cả khi mật khẩu được đặt**, bạn nên xác định một mật khẩu mạnh tại đây như một biện pháp an toàn bổ sung. Chúng ta sẽ nói về điều này trong giây lát.

Nếu bạn đã bật xác thực mật khẩu, bạn sẽ được hiển thị độ mạnh của mật khẩu cho mật khẩu gốc mà bạn vừa nhập và máy chủ của bạn sẽ hỏi bạn có muốn tiếp tục với mật khẩu đó không. Nếu bạn hài lòng với mật khẩu hiện tại của mình, hãy nhập `Y` cho “có” tại dấu nhắc:
```custom_prefix()
Estimated strength of the password: <^>100<^> 
Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : <^>y<^>
```

Đối với các câu hỏi còn lại, nhấn `Y` và nhấn phím `ENTER` tại mỗi dấu nhắc. Thao tác này sẽ xóa một số người dùng ẩn danh và cơ sở dữ liệu thử nghiệm, vô hiệu hóa đăng nhập gốc từ xa và tải các quy tắc mới này để MySQL ngay lập tức tôn trọng những thay đổi bạn đã thực hiện.

Khi bạn hoàn tất, hãy kiểm tra xem bạn có thể đăng nhập vào bảng điều khiển MySQL hay không bằng cách nhập:
```command
sudo mysql
```

Điều này sẽ kết nối với máy chủ MySQL với tư cách là administrative database user **root**, điều này được suy ra bằng cách sử dụng `sudo` khi chạy lệnh này. Bạn sẽ thấy đầu ra như thế này:
```
[secondary_label Output]
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 22
Server version: 8.0.19-0ubuntu5 (Ubuntu)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```

Để thoát khỏi bảng điều khiển MySQL, hãy nhập:
```custom_prefix(mysql>)
exit
```

Lưu ý rằng bạn không cần cung cấp mật khẩu để kết nối với tư cách **root** user, mặc dù bạn đã xác định mật khẩu khi chạy tập lệnh `mysql_secure_installation`. Đó là vì phương thức xác thực mặc định cho administrative MySQL user là `unix_socket` thay vì `password`. Mặc dù ban đầu điều này có vẻ giống như một vấn đề bảo mật, nhưng nó làm cho máy chủ cơ sở dữ liệu an toàn hơn vì những người dùng duy nhất được phép đăng nhập với tư cách là **root** MySQL user là những người dùng hệ thống có đặc quyền sudo kết nối từ bảng điều khiển hoặc thông qua một ứng dụng đang chạy với cùng đặc quyền. Về mặt thực tế, điều đó có nghĩa là bạn sẽ không thể sử dụng administrative database **root** user để kết nối từ ứng dụng PHP của mình. Đặt mật khẩu cho tài khoản **root** MySQL hoạt động như một biện pháp bảo vệ, trong trường hợp phương thức xác thực mặc định được thay đổi từ `unix_socket` thành `password`.

Để tăng cường bảo mật, tốt nhất bạn nên thiết lập tài khoản người dùng chuyên dụng với các đặc quyền ít mở rộng hơn cho mọi cơ sở dữ liệu, đặc biệt nếu bạn dự định có nhiều cơ sở dữ liệu được lưu trữ trên máy chủ của mình.

<$>[note]
**Lưu ý:** Tại thời điểm viết bài này, thư viện MySQL PHP gốc `mysqlnd` không hỗ trợ `caching_sha2_authentication`, phương thức xác thực mặc định cho MySQL 8. Vì lý do đó, khi tạo người dùng cơ sở dữ liệu cho các ứng dụng PHP trên MySQL 8, bạn sẽ cần thực hiện chắc chắn rằng chúng được thiết lập cấu hình để sử dụng `mysql_native_password` thay thế. Chúng tôi sẽ trình bày cách thực hiện điều đó trong Bước 6.
<$>

Máy chủ MySQL của bạn hiện đã được cài đặt và bảo mật. Tiếp theo, chúng ta sẽ cài đặt PHP, thành phần cuối cùng trong LAMP stack.

## Bước 3 — Cài đặt PHP

Bạn đã cài đặt Apache để phục vụ nội dung của mình và cài đặt MySQL để lưu trữ và quản lý dữ liệu của bạn. PHP là thành phần thiết lập của chúng ta sẽ xử lý mã để hiển thị nội dung động cho người dùng cuối cùng. Ngoài gói `php`, bạn sẽ cần `php-mysql`, một mô-đun PHP cho phép PHP giao tiếp với cơ sở dữ liệu dựa trên MySQL. Bạn cũng sẽ cần `libapache2-mod-php` để cho phép Apache xử lý các tệp PHP. Các gói PHP lõi sẽ tự động được cài đặt dưới dạng phụ thuộc.

Để cài đặt các gói này, hãy chạy:
```command
sudo apt install php libapache2-mod-php php-mysql
```

Sau khi cài đặt xong, bạn có thể chạy lệnh sau để xác nhận phiên bản PHP của mình:
```command
php -v
```

```
[secondary_label Output]
PHP 7.4.3 (cli) (built: Jul  5 2021 15:13:35) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies
```

Tại thời điểm này, LAMP stack của bạn đã hoạt động đầy đủ, nhưng trước khi bạn có thể kiểm tra thiết lập của mình bằng tập lệnh PHP, tốt nhất bạn nên thiết lập Máy chủ ảo Apache thích hợp để chứa các tệp và thư mục trên trang web của mình. Chúng tôi sẽ làm điều đó trong bước tiếp theo.

## Bước 4 — Tạo máy chủ ảo cho trang web của bạn

Khi sử dụng máy chủ web Apache, bạn có thể tạo các máy chủ ảo (tương tự như các khối máy chủ trong Nginx) để đóng gói các chi tiết cấu hình và lưu trữ nhiều miền từ một máy chủ. Trong hướng dẫn này, chúng tôi sẽ thiết lập một miền gọi là **your_domain**, nhưng bạn nên **thay thế miền này bằng tên miền của riêng bạn**.

Apache trên Ubuntu 20.04 có một khối máy chủ được bật theo mặc định, khối này được thiết lập cấu hình để phục vụ tài liệu từ thư mục `/var/www/html`. Mặc dù điều này hoạt động tốt cho một trang web, nhưng nó có thể trở nên khó sử dụng nếu bạn đang lưu trữ nhiều trang web. Thay vì sửa đổi `/var/www/html`, chúng ta sẽ tạo cấu trúc thư mục trong `/var/www` cho trang web **your_domain**, để lại `/var/www/html` làm thư mục mặc định sẽ được phục vụ nếu yêu cầu của khách hàng không phù hợp với bất kỳ trang web khác.

Tạo thư mục cho **your_domain** như sau:
```command
sudo mkdir /var/www/<^>your_domain<^>
```

Tiếp theo, chỉ định quyền sở hữu thư mục với biến môi trường `$USER`, sẽ tham chiếu người dùng hệ thống hiện tại của bạn:
```command
sudo chown -R $USER:$USER /var/www/<^>your_domain<^>
```

Sau đó, mở một tệp cấu hình mới trong thư mục `sites-available` của Apache bằng trình chỉnh sửa dòng lệnh ưa thích của bạn. Ở đây, chúng tôi sẽ sử dụng `nano`:
```command
sudo nano /etc/apache2/sites-available/<^>your_domain<^>.conf
```

Thao tác này sẽ tạo một tệp trống mới. Dán vào cấu hình cơ bản sau:
```nginx
[label /etc/apache2/sites-available/your_domain.conf]
<VirtualHost *:80>
    ServerName <^>your_domain<^>
    ServerAlias www.<^>our_domain<^>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/<^>your_domain<^>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```

Lưu và đóng tệp khi bạn hoàn tất. Nếu bạn đang sử dụng `nano`, bạn có thể làm điều đó bằng cách nhấn `CTRL+X`, sau đó nhấn `Y` và `ENTER`.

Với cấu hình `VirtualHost` này, chúng tôi yêu cầu Apache phục vụ `<^>your_domain<^>` bằng cách sử dụng `/var/www/<^>your_domain<^>` làm thư mục gốc của web. Nếu bạn muốn kiểm tra Apache mà không có tên miền, bạn có thể xóa hoặc nhận xét các tùy chọn `ServerName` và `ServerAlias` bằng cách thêm ký tự `#` vào đầu mỗi dòng của tùy chọn.

Bây giờ bạn có thể sử dụng `a2ensite` để kích hoạt máy chủ ảo mới:
```command
sudo a2ensite <^>your_domain<^>
```

Bạn có thể muốn tắt trang web mặc định được cài đặt với Apache. Điều này là bắt buộc nếu bạn không sử dụng tên miền tùy chỉnh, vì trong trường hợp này, cấu hình mặc định của Apache sẽ ghi đè lên máy chủ ảo của bạn. Để tắt trang web mặc định của Apache, hãy nhập:
```command
sudo a2dissite 000-default
```

Để đảm bảo tệp cấu hình của bạn không chứa lỗi cú pháp, hãy chạy:
```command
sudo apache2ctl configtest
```

Cuối cùng, tải lại Apache để những thay đổi này có hiệu lực:
```command
sudo systemctl reload apache2
```

Trang web mới của bạn hiện đang hoạt động nhưng gốc web `/var/www/<^>your_domain<^>` vẫn trống. Tạo tệp `index.html` ở vị trí đó để chúng tôi có thể kiểm tra xem máy chủ ảo có hoạt động như mong đợi không:
```command
nano /var/www/<^>your_domain<^>/index.html
```

Bao gồm nội dung sau trong tệp này:
```nginx
[label /var/www/your_domain/index.html]
<html>
  <head>
    <title><^>your_domain<^> website</title>
  </head>
  <body>
    <h1>Hello World!</h1>

    <p>This is the landing page of <strong><^>your_domain<^></strong>.</p>
  </body>
</html>
```

Bây giờ, hãy truy cập trình duyệt của bạn và truy cập lại tên miền hoặc địa chỉ IP của máy chủ của bạn:
```custom_prefix()
http://<^>server_domain_or_IP<^>
```

Bạn sẽ thấy một trang như thế này:

![description image](https://media.cloudfly.vn/posts/landing_page.png)

Nếu bạn thấy trang này, điều đó có nghĩa là máy chủ ảo Apache của bạn đang hoạt động như mong đợi.

Bạn có thể để nguyên tệp này làm landing page tạm thời cho ứng dụng của mình cho đến khi bạn thiết lập tệp `index.php` để thay thế nó. Khi bạn thực hiện điều đó, hãy nhớ xóa hoặc đổi tên tệp `index.html` khỏi thư mục gốc của tài liệu, vì nó sẽ được ưu tiên hơn tệp `index.php` theo mặc định.

### Lưu ý về `DirectoryIndex` trên Apache

Với cài đặt `DirectoryIndex` mặc định trên Apache, tệp có tên `index.html` sẽ luôn được ưu tiên hơn tệp `ndex.php`. Điều này hữu ích cho việc thiết lập các trang bảo trì trong các ứng dụng PHP, bằng cách tạo một tệp `index.html` tạm thời chứa thông báo cung cấp thông tin cho khách truy cập. Bởi vì trang này sẽ được ưu tiên hơn trang `index.php`, sau đó nó sẽ trở thành landing page cho ứng dụng. Sau khi quá trình bảo trì kết thúc, `index.html` được đổi tên hoặc xóa khỏi thư mục gốc của tài liệu, mang lại trang ứng dụng thông thường.

Trong trường hợp bạn muốn thay đổi hành vi này, bạn sẽ cần chỉnh sửa tệp `/etc/apache2/mods-enabled/dir.conf` và sửa đổi thứ tự liệt kê tệp `index.php` trong chỉ thị `DirectoryIndex`:
```command
sudo nano /etc/apache2/mods-enabled/dir.conf
```

```nginx
[label /etc/apache2/mods-enabled/dir.conf]
<IfModule mod_dir.c>
        DirectoryIndex <^>index.php<^> index.html index.cgi index.pl index.xhtml index.htm
</IfModule>
```

Sau khi lưu và đóng tệp, bạn sẽ cần tải lại Apache để các thay đổi có hiệu lực:
```command
sudo systemctl reload apache2
```

Trong bước tiếp theo, chúng ta sẽ tạo tập lệnh PHP để kiểm tra xem PHP có được cài đặt và thiết lập cấu hình đúng trên máy chủ của bạn không.

## Bước 5 — Kiểm tra PHP Processing trên Máy chủ Web của bạn

Bây giờ bạn đã có một vị trí tùy chỉnh để lưu trữ các tệp và thư mục trên trang web của mình, chúng ta sẽ tạo một tập lệnh kiểm tra PHP để xác nhận rằng Apache có thể xử lý và xử lý các yêu cầu đối với các tệp PHP.

Tạo một tệp mới có tên `info.php` bên trong thư mục gốc web tùy chỉnh của bạn:
```command
nano /var/www/<^>your_domain<^>/info.php
```

Điều này sẽ mở một tập tin trống. Thêm văn bản sau, đây là mã PHP hợp lệ, bên trong tệp:
```nginx
[label /var/www/your_domain/info.php]
<?php
phpinfo();
```

Khi bạn hoàn tất, hãy lưu và đóng tệp.

Để kiểm tra tập lệnh này, hãy truy cập trình duyệt web của bạn và truy cập tên miền hoặc địa chỉ IP của máy chủ, theo sau là tên tập lệnh, trong trường hợp này là `info.php`:
```custom_prefix()
http://<^>server_domain_or_IP<^>/info.php
```

Bạn sẽ thấy một trang tương tự như thế này:

![description image](https://media.cloudfly.vn/posts/phpinfo.png)

Trang này cung cấp thông tin về máy chủ của bạn từ quan điểm của PHP. Nó hữu ích cho việc gỡ lỗi và để đảm bảo rằng cài đặt của bạn đang được áp dụng chính xác.

Nếu bạn có thể thấy trang này trong trình duyệt của mình, thì cài đặt PHP của bạn đang hoạt động như mong đợi.

Sau khi kiểm tra thông tin liên quan về máy chủ PHP của bạn thông qua trang đó, tốt nhất bạn nên xóa tệp bạn đã tạo vì tệp này chứa thông tin nhạy cảm về môi trường PHP và máy chủ Ubuntu của bạn. Bạn có thể sử dụng `rm` để làm như vậy:
```command
sudo rm /var/www/<^>your_domain<^>/info.php
```

Bạn luôn có thể tạo lại trang này nếu sau này bạn cần truy cập lại thông tin.

## Bước 6 — Kiểm tra kết nối cơ sở dữ liệu từ PHP (Tùy chọn)

Nếu bạn muốn kiểm tra xem PHP có thể kết nối với MySQL và thực hiện các truy vấn cơ sở dữ liệu hay không, bạn có thể tạo một bảng kiểm tra với dữ liệu giả và truy vấn nội dung của nó từ tập lệnh PHP. Trước khi có thể làm điều đó, chúng ta cần tạo một cơ sở dữ liệu thử nghiệm và một MySQL user mới được cấu hình đúng cách để truy cập nó.

Tại thời điểm viết bài này, thư viện MySQL PHP gốc `mysqlnd` không hỗ trợ `caching_sha2_authentication`, phương thức xác thực mặc định cho MySQL 8. Chúng ta sẽ cần tạo một người dùng mới với phương thức xác thực `mysql_native_password` để có thể kết nối với Cơ sở dữ liệu MySQL từ PHP.

Chúng tôi sẽ tạo một cơ sở dữ liệu có tên là **example_database** và một người dùng có tên là **example_user**, nhưng bạn có thể thay thế những tên này bằng các giá trị khác.

Đầu tiên, kết nối với bảng điều khiển MySQL bằng tài khoản **root**:
```command
sudo mysql
```

Để tạo cơ sở dữ liệu mới, hãy chạy lệnh sau từ bảng điều khiển MySQL của bạn:
```custom_prefix(mysql>)
CREATE DATABASE <^>example_database<^>;
```

Giờ đây, bạn có thể tạo người dùng mới và cấp cho họ đầy đủ đặc quyền trên cơ sở dữ liệu tùy chỉnh mà bạn vừa tạo.

Lệnh sau tạo một người dùng mới có tên `<^>example_user<^>`, sử dụng `mysql_native_password`làm phương thức xác thực mặc định. Chúng ta đang xác định mật khẩu của người dùng này là `<^>password<^>`, nhưng bạn nên thay thế giá trị này bằng mật khẩu an toàn do chính bạn chọn.
```custom_prefix(mysql>)
CREATE USER '<^>example_user<^>'@'%' IDENTIFIED WITH mysql_native_password BY '<^>password<^>';
```

Bây giờ chúng ta cần cấp quyền cho người dùng này đối với cơ sở dữ liệu `example_database`:
```custom_prefix(mysql>)
GRANT ALL ON example_database.* TO 'example_user'@'%';
```

Điều này sẽ cung cấp cho người dùng **example_user** toàn quyền đối với cơ sở dữ liệu **example_database**, đồng thời ngăn người dùng này tạo hoặc sửa đổi các cơ sở dữ liệu khác trên máy chủ của bạn.

Bây giờ hãy thoát khỏi MySQL shell bằng:
```custom_prefix(mysql>)
exit
```

Bạn có thể kiểm tra xem người dùng mới có quyền phù hợp hay không bằng cách đăng nhập lại vào bảng điều khiển MySQL, lần này bằng thông tin xác thực người dùng tùy chỉnh:
```custom_prefix(mysql>)
-u <^>example_user<^> -p
```

Lưu ý cờ `-p` trong lệnh này, nó sẽ nhắc bạn nhập mật khẩu được sử dụng khi tạo người dùng **example_user**. Sau khi đăng nhập vào bảng điều khiển MySQL, hãy xác nhận rằng bạn có quyền truy cập vào cơ sở dữ liệu **example_database**:
```custom_prefix(mysql>)
SHOW DATABASES;
```

Điều này sẽ cung cấp cho bạn đầu ra sau:
```
[secondary_label Output]
+--------------------+
| Database           |
+--------------------+
| <^>example_database<^>   |
| information_schema |
+--------------------+
2 rows in set (0.000 sec)
```

Tiếp theo, chúng ta sẽ tạo một bảng thử nghiệm có tên **todo_list**. Từ bảng điều khiển MySQL, hãy chạy câu lệnh sau:
```custom_prefix(mysql>)
CREATE TABLE <^>example_database<^>.<^>todo_list<^> (
	item_id INT AUTO_INCREMENT,
	content VARCHAR(255),
	PRIMARY KEY(item_id)
);
```

Chèn một vài hàng nội dung vào bảng kiểm tra. Bạn có thể muốn lặp lại lệnh tiếp theo một vài lần, sử dụng các giá trị khác nhau:
```custom_prefix(mysql>)
INSERT INTO <^>example_database<^>.<^>todo_list<^> (content) VALUES ("<^>My first important item<^>");
```

Để xác nhận rằng dữ liệu đã được lưu thành công vào bảng của bạn, hãy chạy:
```custom_prefix(mysql>)
SELECT * FROM <^>example_database<^>.<^>todo_list<^>;
```

Bạn sẽ thấy đầu ra sau:
```
[secondary_label Output]
+---------+--------------------------+
| item_id | content                  |
+---------+--------------------------+
|       1 | My first important item  |
|       2 | My second important item |
|       3 | My third important item  |
|       4 | and this one more thing  |
+---------+--------------------------+
4 rows in set (0.000 sec)
```

Sau khi xác nhận rằng bạn có dữ liệu hợp lệ trong bảng thử nghiệm của mình, bạn có thể thoát khỏi bảng điều khiển MySQL:
```custom_prefix(mysql>)
exit
```

Bây giờ bạn có thể tạo tập lệnh PHP sẽ kết nối với MySQL và truy vấn nội dung của bạn. Tạo một tệp PHP mới trong thư mục gốc web tùy chỉnh của bạn bằng trình chỉnh sửa ưa thích của bạn. Chúng tôi sẽ sử dụng `nano` cho điều đó:
```command
nano /var/www/<^>your_domain<^>/<^>todo_list.php<^>
```

Tập lệnh PHP sau đây kết nối với cơ sở dữ liệu MySQL và truy vấn nội dung của bảng **todo_list**, hiển thị kết quả trong một danh sách. Nếu có vấn đề với kết nối cơ sở dữ liệu, nó sẽ đưa ra một ngoại lệ. Sao chép nội dung này vào tập lệnh `todo_list.php` của bạn:
```nginx
[label /var/www/your_domain/todo_list.php]
<?php
$user = "<^>example_user<^>";
$password = "<^>password<^>";
$database = "<^>example_database<^>";
$table = "<^>todo_list<^>";

try {
  $db = new PDO("mysql:host=localhost;dbname=$database", $user, $password);
  echo "<h2>TODO</h2><ol>"; 
  foreach($db->query("SELECT content FROM $table") as $row) {
    echo "<li>" . $row['content'] . "</li>";
  }
  echo "</ol>";
} catch (PDOException $e) {
    print "Error!: " . $e->getMessage() . "<br/>";
    die();
}
```

Lưu và đóng tệp khi bạn chỉnh sửa xong.

Bây giờ bạn có thể truy cập trang này trong trình duyệt web của mình bằng cách truy cập tên miền hoặc địa chỉ IP công cộng được thiết lập cấu hình cho trang web của bạn, theo sau là `/todo_list.php`:
```custom_prefix()
http://<^>your_domain_or_IP<^>/todo_list.php
```

Bạn sẽ thấy một trang như thế này, hiển thị nội dung bạn đã chèn vào bảng kiểm tra của mình:

![description image](https://media.cloudfly.vn/posts/todo_list.png)

Điều đó có nghĩa là môi trường PHP của bạn đã sẵn sàng để kết nối và tương tác với máy chủ MySQL của bạn.

## Kết luận

Trong hướng dẫn này, chúng ta đã xây dựng một nền tảng linh hoạt để phục vụ các trang web và ứng dụng PHP cho khách truy cập của bạn, sử dụng Apache làm máy chủ web và MySQL làm hệ thống cơ sở dữ liệu.

Bước tiếp theo ngay lập tức, bạn nên đảm bảo rằng các kết nối đến máy chủ web của mình được bảo mật bằng cách cung cấp chúng qua HTTPS. Để thực hiện điều đó, bạn có thể sử dụng Let's Encrypt để bảo mật trang web của mình bằng chứng chỉ TLS/SSL miễn phí.
