LEMP Stack là tập hợp các phần mềm mạnh mẽ, được thiết kế để phục vụ các trang web động và ứng dụng PHP. Tên “LEMP” là viết tắt của Linux, Nginx (phát âm “Engine-X”), MySQL – hệ quản trị cơ sở dữ liệu, và PHP – ngôn ngữ lập trình kịch bản. Trong bộ stack này, Ubuntu đảm nhận vai trò hệ điều hành Linux. DataOnline sẽ chỉ cho bạn cách cài đặt các thành phần còn lại, đảm bảo bộ LEMP hoạt động trơn tru trên server Ubuntu của bạn.
Yêu cầu tiên quyết
Bạn cần có quyền truy cập vào một server Ubuntu với một tài khoản sudo (không phải root). Firewall đã được kích hoạt trên server. Nếu cần, hãy tham khảo hướng dẫn cài đặt ban đầu cho Ubuntu để thiết lập server.
Bước 1 – Cài đặt Nginx
Để hiển thị trang web cho khách truy cập, bạn sẽ cài đặt Nginx – một máy chủ web hiệu năng cao – thông qua trình quản lý gói APT.
Giờ đây, khi bạn đã có máy chủ web hoạt động, bạn cần cài đặt hệ thống cơ sở dữ liệu để lưu trữ và quản lý dữ liệu cho trang web của bạn. MySQL là hệ quản trị cơ sở dữ liệu phổ biến được sử dụng trong môi trường PHP.
Lại một lần nữa, hãy sử dụng apt
để lấy và cài đặt phần mềm này:
sudo apt install mysql-server
Khi được nhắc, hãy xác nhận cài đặt bằng cách nhấn Y
và ENTER
.
Sau khi cài đặt hoàn tất, bạn nên chạy một script bảo mật đã được cài sẵn với MySQL. Script này sẽ loại bỏ 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. Hãy khởi động script tương tác bằng cách chạy lệnh sau:
sudo mysql_secure_installation
Bạn sẽ được hỏi một câu hỏi xem có muốn cấu hình VALIDATE PASSWORD PLUGIN
không.
Lưu ý: Việc kích hoạt tính năng này phụ thuộc vào quyết định của bạn. Nếu bật, các mật khẩu không thỏa mãn các tiêu chí quy định sẽ bị MySQL từ chối với thông báo lỗi. Bạn có thể để tính năng xác thực mật khẩu bị tắt, nhưng luôn nên sử dụng mật khẩu mạnh và duy nhất cho thông tin đăng nhập cơ sở dữ liệu.
Trả lời Y
cho có, hoặc bất kỳ phím nào khác để tiếp tục mà không bật tính năng này.
Output VALIDATE PASSWORD COMPONENT 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 component? Press y|Y for Yes, any other key for No:
Nếu bạn trả lời “yes”, 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ẽ nhận được lỗi khi cố gắng đặt bất kỳ mật khẩu nào không chứa số, chữ cái in hoa và in thường, cũng như ký tự đặc biệt.
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
Dù bạn có chọn cài đặt VALIDATE PASSWORD PLUGIN
hay không, server của bạn sẽ yêu cầu bạn chọn và xác nhận một mật khẩu cho người dùng root của MySQL. Lưu ý rằng đây không phải là tài khoản root của hệ thống. Người dùng root của cơ sở dữ liệu là một người dùng quản trị có toàn quyền trên hệ thống cơ sở dữ liệu. Mặc dù phương thức xác thực mặc định cho người dùng root của MySQL không yêu cầu mật khẩu ngay cả khi đã thiết lập, bạn nên định nghĩa một mật khẩu mạnh như một biện pháp an toàn bổ sung. Chúng ta sẽ nói về điều này ngay sau đây.
Nếu bạn đã bật xác thực mật khẩu, bạn sẽ thấy độ mạnh của mật khẩu root mà bạn đã nhập và server 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, hãy nhấn Y để xác nhận:
Output 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, hãy nhấn Y
và nhấn ENTER
mỗi khi được nhắc. Điều này sẽ xóa một số người dùng ẩn và cơ sở dữ liệu test, vô hiệu hóa đăng nhập root từ xa, và nạp các quy tắc mới để MySQL ngay lập tức áp dụ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 MySQL console không:
sudo mysql
Để thoát khỏi MySQL console, hãy gõ:
exit
Lưu ý rằng bạn không cần cung cấp mật khẩu để kết nối với người dùng root, mặc dù bạn đã định nghĩa một mật khẩu khi chạy script mysql_secure_installation. Điều này là vì khi cài đặt trên Ubuntu, phương thức xác thực mặc định cho người dùng quản trị MySQL là auth_socket
, thay vì sử dụng phương thức yêu cầu mật khẩu. Điều này có vẻ như một vấn đề an ninh ban đầu, nhưng thực ra nó làm cho server cơ sở dữ liệu an toàn hơn vì chỉ những người dùng hệ thống có quyền sudo mới được phép đăng nhập dưới tư cách người dùng root của MySQL, thông qua console hoặc ứng dụng chạy với quyền tương tự. Nói một cách đơn giản, điều này có nghĩa là bạn sẽ không thể sử dụng người dùng quản trị root của cơ sở dữ liệu để kết nối từ ứng dụng PHP của bạn.
Để tăng cường bảo mật, tốt nhất là nên thiết lập các tài khoản người dùng riêng với quyền hạn hạn chế cho mỗi cơ sở dữ liệu, đặc biệt nếu bạn dự định lưu trữ nhiều cơ sở dữ liệu trên server.
Lưu ý: Một số phiên bản cũ của thư viện PHP MySQL gốc (mysqlnd) không hỗ trợ
caching_sha2_authentication
– phương thức xác thực mặc định cho người dùng MySQL 8 được tạo mới. Vì lý do đó, khi tạo người dùng cơ sở dữ liệu cho ứng dụng PHP trên MySQL 8, bạn có thể cần đảm bảo rằng họ được cấu hình sử dụngmysql_native_password
thay thế. Chúng tôi sẽ trình bày cách thực hiện điều này ở Bước 6.
MySQL server của bạn hiện đã được cài đặt và bảo mật. Tiếp theo, bạn sẽ cài đặt PHP – thành phần cuối cùng trong bộ LEMP.
Bước 3 – Cài đặt PHP
Bạn đã cài đặt Nginx để phục vụ nội dung của mình và MySQL để lưu trữ, quản lý dữ liệu. Giờ đây, bạn có thể cài đặt PHP để xử lý mã và tạo nội dung động cho máy chủ web.
Trong khi Apache tích hợp bộ thông dịch PHP trong mỗi yêu cầu, Nginx lại yêu cầu một chương trình bên ngoài để xử lý các tác vụ PHP và hoạt động như cầu nối giữa bộ thông dịch PHP và máy chủ web. Điều này mang lại hiệu năng tổng thể tốt hơn cho hầu hết các trang web dựa trên PHP, nhưng cũng đòi hỏi cấu hình bổ sung. Bạn sẽ cần cài đặt php8.1-fpm (viết tắt của “PHP fastCGI process manager” và sử dụng phiên bản PHP hiện tại tại thời điểm viết bài) để chỉ thị cho Nginx chuyển các yêu cầu PHP tới phần mềm này xử lý. Ngoài ra, bạn cũng cần cài đặt php-mysql – một module PHP cho phép PHP giao tiếp với các cơ sở dữ liệu MySQL. Các gói PHP cốt lõi sẽ tự động được cài đặt như các phụ thuộc.
Để cài đặt các gói php8.1-fpm và php-mysql, hãy chạy:
sudo apt install php8.1-fpm php-mysql
Khi được nhắc, nhấn Y
và ENTER
để xác nhận cài đặt.
Giờ đây, các thành phần PHP của bạn đã được cài đặt. Tiếp theo, bạn sẽ cấu hình Nginx để sử dụng chúng.
Bước 4 – Cấu hình Nginx sử dụng PHP
Khi sử dụng máy chủ web Nginx, bạn có thể tạo các server block (tương tự như virtual hosts trong Apache) để bao gói chi tiết cấu hình và phục vụ nhiều tên miền trên một server duy nhất. Trong hướng dẫn này, chúng ta sẽ sử dụng your_domain làm tên miền ví dụ.
Lưu ý: Để tìm hiểu thêm về cách thiết lập tên miền với DataOnline, hãy đọc phần giới thiệu về DataOnline DNS.
Trên Ubuntu, Nginx có sẵn một server block được kích hoạt mặc định và được cấu hình để phục vụ tài liệu từ thư mục /var/www/html
. Mặc dù cấu hình này phù hợp với một trang web đơn, nhưng nó có thể trở nên khó quản lý nếu bạn đang host nhiều trang web. Thay vì sửa đổi /var/www/html
, chúng ta sẽ tạo một cấu trúc thư mục trong /var/www
cho website your_domain, giữ nguyên /var/www/html
như thư mục mặc định phục vụ khi yêu cầu của client không khớp với trang nào khác.
Tạo thư mục gốc cho trang web your_domain như sau:
sudo mkdir /var/www/your_domain
Tiếp theo, gán quyền sở hữu cho thư mục này cho người dùng hiện tại thông qua biến môi trường $USER
:
sudo mkdir /var/www/your_domain
Sau đó, mở một file cấu hình mới trong thư mục sites-available
của Nginx bằng trình soạn thảo dòng lệnh ưa thích của bạn (ở đây, chúng ta sử dụng nano):
sudo nano /etc/nginx/sites-available/your_domain
File này sẽ được tạo dưới dạng trống. Chèn nội dung cấu hình cơ bản sau:
/etc/nginx/sites-available/your_domain server { listen 80; server_name your_domain www.your_domain; root /var/www/your_domain; index index.html index.htm index.php; location / { try_files $uri $uri/ =404; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; } location ~ /\.ht { deny all; } }
Giải thích các chỉ thị và khối location:
- listen — Xác định cổng mà Nginx sẽ lắng nghe. Ở đây, Nginx lắng nghe trên cổng 80, cổng mặc định cho HTTP.
- root — Xác định thư mục chứa các tập tin được phục vụ bởi trang web.
- index — Xác định thứ tự ưu tiên các file index cho trang web. Thông thường, file index.html được ưu tiên hơn index.php để dễ dàng thiết lập một trang bảo trì cho các ứng dụng PHP.
- server_name — Xác định tên miền và/hoặc địa chỉ IP mà server block này sẽ phản hồi. Chỉ định tên miền hoặc địa chỉ IP công cộng của server.
- location / — Khối location đầu tiên chứa chỉ thị
try_files
, dùng để kiểm tra sự tồn tại của tập tin hoặc thư mục khớp với yêu cầu URL. Nếu Nginx không tìm thấy tài nguyên phù hợp, nó sẽ trả về lỗi 404. - location ~ .php$ — Khối location này xử lý việc xử lý file PHP bằng cách chỉ thị Nginx sử dụng file cấu hình
fastcgi-php.conf
và chuyển tiếp yêu cầu đến socketphp8.1-fpm.sock
, nơi xử lý các yêu cầu PHP. - location ~ /.ht — Khối location cuối cùng xử lý các file .htaccess, vốn Nginx không xử lý. Với chỉ thị
deny all
, nếu có file .htaccess xuất hiện trong thư mục gốc, chúng sẽ không được phục vụ cho khách truy cập.
Sau khi chỉnh sửa xong, lưu và đóng file. (Nếu bạn sử dụng nano
, nhấn CTRL+X
, sau đó nhấn Y
và ENTER
để xác nhận.)
Kích hoạt cấu hình vừa tạo bằng cách tạo một liên kết tượng trưng đến file cấu hình trong thư mục sites-enabled
:
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
Sau đó, gỡ liên kết file cấu hình mặc định khỏi thư mục sites-enabled
:
sudo unlink /etc/nginx/sites-enabled/default
Lưu ý: Nếu bạn cần khôi phục lại cấu hình mặc định, bạn có thể tạo lại liên kết tượng trưng như sau:
sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/
Lệnh này sẽ thông báo cho Nginx sử dụng cấu hình đó trong lần tải lại tiếp theo. Bạn có thể kiểm tra lỗi cú pháp của cấu hình bằng cách chạy:
sudo nginx -t
Nếu có bất kỳ lỗi nào được báo cáo, hãy quay lại file cấu hình để kiểm tra và chỉnh sửa trước khi tiếp tục.
Khi đã sẵn sàng, tải lại Nginx để áp dụng các thay đổi:
sudo systemctl reload nginx
Website mới của bạn bây giờ đã được kích hoạt, tuy nhiên thư mục gốc /var/www/your_domain
vẫn còn trống. Tạo một file index.html
trong thư mục đó để kiểm tra xem server block mới có hoạt động đúng không:
nano /var/www/your_domain/index.html
Chèn nội dung sau vào file:
/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>
Lưu file lại, sau đó mở trình duyệt và truy cập tên miền hoặc địa chỉ IP công cộng của server, như được chỉ định trong chỉ thị server_name
trong file cấu hình:
http://server_domain_or_IP
Bạn sẽ nhận được một trang hiển thị như hình minh họa cho server block Nginx.
Nếu trang này hiện ra, nghĩa là server block Nginx của bạn đang hoạt động chính xác.
Bạn có thể để lại file này làm trang landing tạm thời cho ứng dụng của bạn cho đến khi bạn thiết lập file index.php
thay thế. Khi làm như vậy, nhớ xóa hoặc đổi tên file index.html
trong thư mục gốc, vì nó sẽ được ưu tiên hiển thị trước file index.php
theo mặc định.
LEMP stack của bạn giờ đã được cấu hình đầy đủ. Trong bước tiếp theo, bạn sẽ tạo một script PHP để kiểm tra xem Nginx có thể xử lý các file .php
trên website vừa cấu hình hay không.
Bước 5 – Kiểm tra PHP với Nginx
LEMP stack của bạn giờ đã được cài đặt hoàn chỉnh. Bạn có thể kiểm tra xem Nginx có chuyển các file .php đúng cách đến bộ xử lý PHP hay không.
Để làm điều này, hãy tạo một file PHP test trong thư mục gốc của website. Mở một file mới có tên là info.php trong thư mục gốc bằng trình soạn thảo ưa thích của bạn:
nano /var/www/your_domain/info.php
Thêm các dòng sau vào file mới này. Đây là đoạn mã PHP hợp lệ, sẽ trả về thông tin về server của bạn:
/var/www/your_domain/info.php <?php phpinfo();
Sau khi hoàn tất, lưu và đóng file.
Bây giờ, bạn có thể truy cập trang này trong trình duyệt bằng cách nhập tên miền hoặc địa chỉ IP công cộng của server (như đã thiết lập trong file cấu hình Nginx) kèm theo /info.php:
http://server_domain_or_IP/info.php
Bạn sẽ nhận được một trang web chứa thông tin chi tiết về server PHP của bạn.
Sau khi kiểm tra thông tin liên quan đến server PHP, tốt nhất là nên xóa file vừa tạo vì nó chứa thông tin nhạy cảm về môi trường PHP và server Ubuntu của bạn. Bạn có thể xóa file bằng lệnh:
sudo rm /var/www/your_domain/info.php
Bạn luôn có thể tạo lại file này nếu cần thiết.
Bước 6 – Kiểm tra kết nối cơ sở dữ liệu từ PHP (Tuỳ chọn)
Nếu bạn muốn kiểm tra xem PHP có thể kết nối đến 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 test chứa dữ liệu mẫu và thực hiện truy vấn lấy nội dung của bảng đó từ một script PHP. Trước khi làm điều này, bạn cần tạo một cơ sở dữ liệu test và một người dùng MySQL mới được cấu hình đúng để truy cập vào cơ sở dữ liệu đó.
Lưu ý: Một số phiên bản cũ của 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 của MySQL 8. Vì vậy, bạn cần đảm bảo rằng các người dùng được tạo sẽ được cấu hình sử dụngmysql_native_password
thay thế.
Chúng ta 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 (bạn có thể thay thế các tên này bằng tên khác nếu cần).
Kết nối vào MySQL console với tài khoản root:
sudo mysql
Tạo cơ sở dữ liệu mới bằng lệnh sau trong MySQL console:
CREATE DATABASE example_database;
Tạo người dùng mới và cấp quyền toàn bộ cho cơ sở dữ liệu vừa tạo.
Lệnh dưới đây 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. Mật khẩu được đặt là password
(hãy thay thế bằng mật khẩu an toàn của riêng bạn):
CREATE USER 'example_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
Cấp quyền cho người dùng trên cơ sở dữ liệu example_database
:
GRANT ALL ON example_database.* TO 'example_user'@'%';
Lệnh này sẽ cấp cho người dùng example_user toàn quyền trên cơ sở dữ liệu example_database, đồng thời ngăn không cho người dùng này tạo hoặc sửa đổi các cơ sở dữ liệu khác trên server.
Thoát khỏi MySQL shell:
exit
Kiểm tra quyền của người dùng mới:
Đăng nhập lại vào MySQL console với tài khoản người dùng tùy chỉnh, lưu ý sử dụng cờ -p
để được nhắc nhập mật khẩu:
mysql -u example_user -p
Sau khi đăng nhập, kiểm tra xem bạn có thể truy cập được cơ sở dữ liệu example_database hay không bằng lệnh:
SHOW DATABASES;
Kết quả trả về sẽ như sau:
Output +--------------------+ | Database | +--------------------+ | example_database | | information_schema | +--------------------+ 2 rows in set (0.000 sec)
Tạo một bảng test có tên todo_list
:
Trong MySQL console, chạy lệnh sau:
CREATE TABLE example_database.todo_list ( item_id INT AUTO_INCREMENT, content VARCHAR(255), PRIMARY KEY(item_id) );
Chèn một vài dòng dữ liệu vào bảng test:
Bạn có thể chạy lệnh sau nhiều lần với các giá trị khác nhau:
INSERT INTO example_database.todo_list (content) VALUES ("My first important item");
Kiểm tra dữ liệu đã được lưu vào bảng thành công hay chưa:
SELECT * FROM example_database.todo_list;
Kết quả mong đợi:
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)
Thoát khỏi MySQL console:
exit
Tạo một script PHP để kết nối đến MySQL và thực hiện truy vấn lấy dữ liệu:
Tạo một file PHP mới trong thư mục gốc của website bằng trình soạn thảo bạn ưa thích (ở đây chúng ta sử dụng nano):
nano /var/www/your_domain/todo_list.php
Thêm nội dung sau vào file 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(); }
Sau khi chỉnh sửa xong, lưu và đóng file.
Truy cập script PHP qua trình duyệt:
Mở trình duyệt và truy cập theo địa chỉ tên miền hoặc IP công cộng đã được cấu hình cho website của bạn, kèm theo /todo_list.php
:
http://server_domain_or_IP/todo_list.php
Bạn sẽ nhận được một trang hiển thị danh sách các nội dung đã được chèn vào bảng todo_list
.
Nếu trang hiển thị danh sách các mục như trong ví dụ (ví dụ: “My first important item”, “My second important item”, …), đ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 MySQL server.
Kết luận
Trong bài hướng dẫn này, bạn đã tạo dựng một nền tảng ổn định để phục vụ các trang web và ứng dụng PHP, sử dụng Nginx làm máy chủ web và MySQL làm hệ quản trị cơ sở dữ liệu. Nếu cần thêm thông tin, bạn cũng có thể tham khảo cách cài đặt LAMP Stack (Linux, Apache, MySQL, PHP) trên Ubuntu hoặc hướng dẫn bảo mật website với Let’s Encrypt để có chứng chỉ SSL miễn phí, được tin cậy.