SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-07

Cài LAMP trên Ubuntu 24.04 với PHP-FPM

Hướng dẫn cài Apache, MariaDB, PHP 8.3 và PHP-FPM trên Ubuntu 24.04, tạo virtual host theo hostname, phân quyền database tối thiểu và bật HTTPS miễn phí bằng Certbot.

Bạn đang xây dựng gì

LAMP stack gồm 4 thành phần chạy trên một máy chủ Ubuntu 24.04: Linux làm nền, Apache xử lý HTTP, MariaDB lưu dữ liệu và PHP 8.3 chạy mã nguồn. Khi hoàn tất, bạn sẽ có một virtual host dựa trên hostname phục vụ một thư mục ứng dụng thực, một database với user riêng có quyền tối thiểu, PHP được kết nối với Apache thông qua PHP-FPM và certificate miễn phí của Let’s Encrypt.

Quá trình cài đặt chỉ gồm 4 lệnh apt. Hầu hết nội dung trong hướng dẫn này là cấu hình kết nối giữa các thành phần và xử lý một số lỗi thường khiến stack mới cài hiển thị trang trắng, gửi mã nguồn cho browser dưới dạng file tải xuống hoặc từ chối cho bạn truy cập database vừa cài. Mỗi lỗi đều có dấu hiệu nhận biết riêng. Bên dưới sẽ ghi rõ từng lỗi cùng chính xác nội dung bạn sẽ thấy.

Điều kiện cần và những điểm cần lưu ý

Giả sử bạn có một Ubuntu 24.04 mới cài trên KVM VPS, tài khoản sudo hoặc root, và một địa chỉ IPv4 public. Một stack tối thiểu chạy được với 1 GB RAM; hãy nâng lên 2 GB trước khi triển khai ứng dụng thực tế có database, vì các buffer mặc định của MariaDB cùng một số worker PHP-FPM sẽ nhanh chóng dùng hết 1 GB đầu tiên.

Trước khi Certbot ở phần cuối hoạt động, cần đáp ứng hai điều. Hãy chuẩn bị chúng ngay từ bây giờ. Bạn cần một domain name có bản ghi A trỏ đến public IP của VPS. Let's Encrypt xác thực qua HTTP tới domain name đó, và một địa chỉ IP thuần không bao giờ được cấp certificate. Ngoài ra, các cổng 80 và 443 phải truy cập được từ Internet. Với nhiều nhà cung cấp, bạn phải mở các cổng này trong network firewall trên control panel đồng thời mở trong ufw trên máy chủ. Thay đổi DNS có thể mất tối đa một giờ để propagate, nên hãy tạo bản ghi A trước để bản ghi hoạt động khi bạn cần dùng.

Bước 1 - Cài đặt Apache và xác nhận trang mặc định

sudo apt update
sudo apt install -y apache2

apt tự khởi động và bật service cho bạn. Hãy kiểm tra:

systemctl status apache2

Bạn cần thấy một dòng có nội dung active (running). Bây giờ mở http://YOUR_SERVER_IP/ trong trình duyệt. Apache2 Ubuntu Default Page với banner lớn "It works!" là kết quả chính xác. Đây là bằng chứng Apache đang phục vụ nội dung, không phải lỗi. Trang này nằm tại /var/www/html/index.html và được phục vụ bởi virtual host mặc định đi kèm là 000-default.conf. Sau này bạn sẽ tắt cả hai; hiện tại, việc chúng xuất hiện chính là điều cần kiểm tra.

Nếu trang hoàn toàn không tải được nhưng systemctl cho biết tiến trình vẫn đang chạy, firewall đang chặn kết nối. Đó là bước tiếp theo.

Bước 2 - Mở firewall cho HTTP và HTTPS

Gói apache2 đăng ký ba profile ứng dụng ufw. Liệt kê chúng:

sudo ufw app list

Bạn sẽ thấy Apache, Apache FullApache Secure. Apache chỉ dùng cổng 80, Apache Secure chỉ dùng cổng 443, còn Apache Full dùng cả hai. Đây là profile bạn cần vì bạn sẽ thêm TLS ở bước cuối.

sudo ufw allow OpenSSH
sudo ufw allow "Apache Full"
sudo ufw enable

Cho phép OpenSSH trước khi chạy ufw enable. ufw mặc định từ chối toàn bộ traffic đến. Nếu bật nó mà chưa có rule cho SSH, kết nối hiện tại của bạn sẽ bị cắt ngay khi firewall kích hoạt và bạn sẽ không thể kết nối lại. Xác nhận bằng sudo ufw status. Bạn cần thấy OpenSSH, Apache Full và các mục tương ứng cho v6 đều có trạng thái ALLOW.

Bước 3 - Cài đặt MariaDB và bảo mật

sudo apt install -y mariadb-server
systemctl status mariadb

Ubuntu 24.04 phát hành MariaDB 10.11, một bản phát hành hỗ trợ dài hạn, nên bạn không cần repository bên ngoài. Khi service đang chạy, hãy tăng cường bảo mật:

sudo mysql_secure_installation

Bạn nên đọc các prompt thay vì cứ nhấn Enter. Khi được hỏi mật khẩu root hiện tại, hãy nhấn Enter vì hiện chưa có mật khẩu. Khi được hỏi "Switch to unix_socket authentication?", câu trả lời không thay đổi gì vì tùy chọn này đã được bật trong package này, nên hãy nhấn n. Trả lời n cho câu hỏi "Change the root password?" vì lý do nêu ở đoạn tiếp theo, rồi trả lời Y cho các câu hỏi còn lại: xóa user ẩn danh, không cho phép root đăng nhập từ xa, xóa database test và nạp lại các bảng quyền.

Đây là phần khiến nhiều người nhầm lẫn. Trên MariaDB của Ubuntu, tài khoản database root dùng cơ chế xác thực unix_socket, không dùng mật khẩu. Nghĩa là database tin cậy user của hệ điều hành mà bạn đã xác thực. Vì vậy, lệnh sau chạy được từ shell root:

sudo mysql

...và đưa bạn vào prompt MariaDB [(none)]> mà không yêu cầu mật khẩu. Chạy cùng lệnh bằng user không có quyền sẽ bị từ chối. Đây chính là mục đích của cơ chế này: quyền truy cập vào root của database gắn với sudo trên máy chủ, và không có mật khẩu để bị đánh cắp, phishing hoặc brute-force. Cách này an toàn hơn dùng mật khẩu, nên hãy giữ nguyên. Quy tắc rút ra là: không bao giờ cấu hình ứng dụng sử dụng tài khoản root. Hãy tạo một user riêng cho từng ứng dụng (Bước 7), vì ứng dụng kết nối qua TCP bằng username và mật khẩu không thể dùng socket auth. Đồng thời, mỗi ứng dụng chỉ nên được cấp quyền trên database của chính nó.

Bước 4 - Cài đặt PHP 8.3 với PHP-FPM

PHP mặc định của Ubuntu 24.04 là 8.3. Cài process manager FPM và các extension mà ứng dụng thông thường cần:

sudo apt install -y php8.3-fpm php8.3-mysql php8.3-cli \
  php8.3-curl php8.3-xml php8.3-mbstring php8.3-zip

Lưu ý những gì không có trong danh sách đó: libapache2-mod-php. Gói cũ này nhúng PHP interpreter vào từng process Apache. Cách này đơn giản, nhưng mỗi worker đều mang theo một bản sao PHP, dù đang phục vụ script hay ảnh tĩnh. Hai thành phần này cũng dùng chung lifecycle. Ngoài ra, cách này chỉ hoạt động với MPM prefork của Apache, vốn kém hiệu quả nhất. PHP-FPM chạy PHP dưới dạng pool process riêng, để Apache giao tiếp qua socket. Khi đó, Apache có thể dùng MPM event dạng threaded cho file tĩnh và chỉ chuyển các request PHP sang pool. Pool có thể được tinh chỉnh độc lập với web server. Sau này, chính cấu hình FPM đó cũng hoạt động nếu bạn đặt nginx ở phía trước. Đây là cấu hình mặc định hiện nay vì những lý do chính đáng.

Apache truy cập FPM thông qua module proxy_fcgi. Hãy enable module này, enable config mà gói FPM đã cài vào, rồi restart:

sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl restart apache2

a2enconf php8.3-fpm kích hoạt /etc/apache2/conf-available/php8.3-fpm.conf. File này chứa rule định tuyến các file PHP đến socket FPM. Phần chính của rule này khớp mọi file .php và chuyển request đến socket tại /run/php/php8.3-fpm.sock:

<FilesMatch ".+\.ph(ar|p|tml)$">
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>

Bạn không cần chỉnh sửa file đó; gói đã cài sẵn cấu hình đúng. Tuy nhiên, biết đường dẫn socket giúp bạn chẩn đoán các lỗi “PHP được tải xuống thay vì chạy” và “Primary script unknown” về sau. Cả hai lỗi này đều xảy ra khi Apache và FPM không thống nhất về socket hoặc file đứng sau socket đó.

Bước 5 - Virtual host dựa trên tên cho ứng dụng của bạn

Virtual hosting dựa trên tên cho phép một IP phục vụ nhiều website; Apache chọn website dựa trên header Host: trong request. Tạo một thư mục cho ứng dụng, cách xa /var/www/html mặc định:

sudo mkdir -p /var/www/testapp
sudo chown -R www-data:www-data /var/www/testapp
sudo chmod -R 755 /var/www/testapp

Quyền sở hữu rất quan trọng. Apache và PHP-FPM đều chạy bằng user www-data trên Ubuntu, vì vậy các file mà web server cần đọc và các thư mục mà ứng dụng cần ghi, chẳng hạn thư mục uploads, nên thuộc sở hữu của www-data. Nếu bạn cũng chỉnh sửa file bằng user đăng nhập của mình, cách thường dùng là tự sở hữu các file và thêm user của bạn vào group www-data; với một lần deploy đơn giản, www-data:www-data là lựa chọn ít gây bất ngờ nhất.

Tạo virtual host tại /etc/apache2/sites-available/testapp.conf:

<VirtualHost *:80>
    ServerName app.example.com
    DocumentRoot /var/www/testapp

    <Directory /var/www/testapp>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

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

Đặt ServerName thành domain thực của bạn. Options -Indexes ngăn Apache liệt kê thư mục khi không có file index; nếu không, visitor có thể duyệt cây mã nguồn của bạn. AllowOverride All cho phép file .htaccess hoạt động, đây là điều hầu hết ứng dụng PHP cần để dùng pretty URL; đổi thành None để tăng tốc một chút nếu ứng dụng của bạn không cần tính năng này. Enable site này, disable site mặc định, kiểm tra config rồi reload:

sudo a2ensite testapp
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2

apache2ctl configtest phải in ra Syntax OK. Dòng a2dissite 000-default là dòng mọi người thường quên, và đó là lý do trang mặc định về sau vẫn xuất hiện, như mô tả trong phần lỗi.

Bước 6 - Xác nhận PHP chạy, sau đó xóa file kiểm tra

Tạo một file PHP một dòng trong thư mục gốc của ứng dụng:

echo "<?php phpinfo();" | sudo tee /var/www/testapp/info.php

Truy cập http://app.example.com/info.php. Kết quả đúng là bảng PHP Version 8.3.x dài, màu tím và xám, liệt kê các module đã nạp; dòng Server API phải có giá trị FPM/FastCGI. Dòng cuối này xác nhận các request đang đi qua PHP-FPM, không phải mod_php.

Xóa file ngay sau đó:

sudo rm /var/www/testapp/info.php

phpinfo() để lộ chính xác phiên bản PHP, mọi extension đã nạp, đường dẫn file và thông tin môi trường. Đây là dữ liệu hữu ích cho bất kỳ ai đang dò server để tìm phiên bản có lỗ hổng đã biết. Đây chỉ là file kiểm tra, không phải một tính năng. Xóa file ngay khi bạn đã xem xong trang. Nếu trình duyệt đề nghị tải xuống info.php thay vì hiển thị bảng, PHP chưa được kết nối với Apache; hãy chuyển đến phần xử lý lỗi trước khi làm bất kỳ việc gì khác.

Bước 7 - Tạo database cho ứng dụng và user có quyền tối thiểu

Mở database bằng root được xác thực qua socket:

sudo mysql

Sau đó tạo một database và một user chỉ có quyền trên đúng database đó:

CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Có 3 lựa chọn có chủ đích ở đây. utf8mb4 là UTF-8 bốn byte thực sự; alias cũ utf8 sẽ âm thầm cắt ngắn emoji và một số ký tự CJK, vì vậy luôn dùng utf8mb4. Cấp quyền trên appdb.*, không phải *.*: user này chỉ có thể truy cập database của mình, không thể truy cập bất kỳ database nào khác. Vì vậy, nếu app có lỗ hổng SQL injection, kẻ tấn công không thể đọc bảng của các site khác. Và 'appuser'@'localhost' giới hạn account này chỉ nhận kết nối phát sinh ngay trên máy chủ.

Kiểm tra bằng user đó:

mysql -u appuser -p appdb

Lệnh sẽ yêu cầu mật khẩu rồi đưa bạn vào prompt MariaDB [appdb]>. Lưu ý rằng không có flag -h. Hãy bỏ flag này; khi đó client sẽ kết nối qua Unix socket cục bộ, đúng với cách MariaDB xác định localhost. Có một điểm dễ nhầm: với MySQL và MariaDB, localhost có nghĩa là Unix socket, còn 127.0.0.1 có nghĩa là kết nối TCP. Trên MariaDB Ubuntu 24.04 mặc định, server vẫn ánh xạ kết nối TCP từ 127.0.0.1 về localhost, nên cả hai đều khớp với account này. Nhưng trên các server đã bật skip-name-resolve (một tối ưu hiệu năng phổ biến và là mặc định trong nhiều container image), hai loại kết nối được đối chiếu với các host khác nhau. Khi đó, app kết nối đến 127.0.0.1 sẽ bị từ chối với lỗi ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' (using password: YES) ngay cả khi mật khẩu đúng.

Vì vậy, hãy cấu hình ứng dụng dùng host localhost, user appuser và database appdb, tuyệt đối không dùng root. Cả mysqli của PHP và PDO đều chuyển sang Unix socket khi host là chuỗi literal localhost, nên sẽ khớp với account vừa tạo. Nếu framework bắt buộc phải dùng host TCP dạng số, hãy tạo user phù hợp với cách framework thực sự kết nối: 'appuser'@'127.0.0.1' hoặc @'%' (kết hợp với firewall rule) chỉ khi database bắt buộc phải nhận kết nối từ máy khác.

Bước 8 - Thêm HTTPS bằng Certbot

Phục vụ biểu mẫu đăng nhập qua HTTP thuần sẽ gửi mật khẩu dưới dạng văn bản rõ, và mọi trình duyệt hiện đại đều đánh dấu trang này là "Không an toàn". Certbot xử lý việc đó bằng một lệnh. Cài đặt Certbot cùng với plugin Apache:

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache

Ở đây Certbot sử dụng 2 plugin. apache authenticator xác minh bạn kiểm soát domain bằng cách tạm thời phục vụ một file challenge thông qua Apache đang chạy. Sau đó, apache installer sửa virtual host để thêm block 443, trỏ block này đến certificate mới và mặc định redirect toàn bộ traffic HTTP sang HTTPS. Từ Certbot 2.0, Certbot không còn hỏi về việc redirect; truyền --no-redirect nếu bạn vẫn cần phục vụ HTTP thuần. Vì bạn đã đặt một ServerName hợp lệ ở Bước 5, Certbot tự động phát hiện domain. Certificate có hiệu lực 90 ngày và package sẽ cài một systemd timer để gia hạn. Xác minh timer bằng sudo certbot renew --dry-run; kết quả phải kết thúc bằng Congratulations, all simulated renewals succeeded.

Để xem hướng dẫn đầy đủ về challenge, renewal timer, cũng như các yêu cầu về DNS và firewall, hãy xem guide đi kèm cấp certificate TLS Let's Encrypt miễn phí bằng Certbot trên Apache.

Sao lưu, nâng cấp và tăng cường bảo mật

Hãy sao lưu 2 thành phần lưu giữ trạng thái của hệ thống: database và web root. Logical dump chạy hằng đêm là cách đơn giản và đáng tin cậy nhất, sudo sh -c 'mysqldump --all-databases --single-transaction | gzip > /root/db-$(date +%F).sql.gz', sau đó sao chép file dump ra khỏi máy chủ. Việc bọc toàn bộ pipeline trong sudo sh -c rất quan trọng: nếu không, shell sẽ chạy lệnh redirect > /root/... bằng user của bạn và thất bại với Permission denied, vì chỉ mysqldump được kế thừa sudo. --single-transaction tạo snapshot nhất quán của các bảng InnoDB mà không khóa chúng. Kết hợp snapshot này với tar của /var/www/etc/apache2/sites-available, bạn có thể dựng lại toàn bộ stack trên một VPS mới từ các file đó.

Nâng cấp là một sudo apt update && sudo apt upgrade thông thường. Trường hợp dễ gây lỗi là nâng phiên bản PHP, khi một bản Ubuntu trong tương lai chuyển mặc định sang PHP 8.4, apt có thể cài php8.4-fpm song song với 8.3, socket trở thành /run/php/php8.4-fpm.sock, còn cấu hình Apache vẫn trỏ đến socket của 8.3. Hãy bật conf mới (sudo a2enconf php8.4-fpm) và tắt conf cũ, nếu không website sẽ bắt đầu trả về Primary script unknown sau một lần nâng cấp vốn thông thường. Vì PHP phát hành phiên bản nhanh hơn distro LTS, hãy kiểm tra release notes hiện tại của PHP thay vì cố định một patch version.

Có 2 bước tăng cường bảo mật nên thực hiện ngay từ ngày đầu. Thứ nhất, hãy cài Fail2Ban để monitor SSH trên máy chủ. Một VPS public sẽ nhận các lần thử đăng nhập tự động chỉ sau vài phút, và một jail nhỏ có thể giảm hàng nghìn lần thử xuống còn vài lần trước khi ban. Thứ hai, nếu muốn quản lý virtual host của Apache, database MariaDB và user bằng trình duyệt thay vì sửa file thủ công, control panel dựa trên nền web Webmin chạy trên đúng stack này và thao tác trên chính các file cấu hình bạn vừa tạo. Cả hai công cụ đều không thay thế việc hiểu từng thành phần, nhưng giúp giảm đáng kể công việc hằng ngày.

Các tình huống lỗi và chuỗi thông báo bạn sẽ thấy

Trang mặc định không biến mất. Bạn đã sửa virtual host và reload, nhưng trình duyệt vẫn hiển thị "Apache2 Ubuntu Default Page" cùng banner "It works!". Apache phục vụ virtual host khớp đầu tiên. Khi không có ServerName nào khớp với request, cấu hình đứng đầu theo thứ tự alphabet sẽ được chọn; 000-default.conf đứng trước testapp.conf. Tên host trong request có thể không khớp với ServerName, hoặc bạn chưa chạy sudo a2dissite 000-default. Hãy disable cấu hình mặc định bằng sudo systemctl reload apache2, rồi xác nhận bằng apache2ctl -S. Lệnh này in ra sơ đồ vhost và cho biết cấu hình nào đang sở hữu vhost mặc định. Đồng thời xóa cache của trình duyệt; mã trạng thái 200 từ trang cũ trong cache có thể vẫn được hiển thị.

File .php được tải xuống thay vì được thực thi. Bạn mở info.php, nhưng trình duyệt tải xuống file chứa mã nguồn <?php thô hoặc hiển thị file dưới dạng plain text thay vì thực thi. Apache đang phục vụ file này như static asset vì PHP handler chưa được gắn, bạn đã bỏ qua sudo a2enmod proxy_fcgi hoặc sudo a2enconf php8.3-fpm, hoặc chưa restart Apache sau đó. Hãy chạy cả 3 lệnh (Bước 4), rồi reload. Xác nhận module đã được load bằng apache2ctl -M | grep fcgi; kết quả phải liệt kê proxy_fcgi_module. Đây là lỗi làm lộ mã nguồn, không phải lỗi hiển thị, vì vậy phải sửa trước khi đưa bất kỳ ứng dụng thực tế nào lên server.

ERROR 1698 (28000): Access denied for user 'root'@'localhost'. Bạn đã chạy mysql -u root hoặc mariadb -u root mà không có sudo. Account root dùng cơ chế xác thực unix_socket, nên chỉ chấp nhận kết nối khi user của hệ điều hành thực sự là root. Cách sửa là dùng sudo mysql, không có -u root và không cần password. Thông báo này là hành vi đúng của cơ chế xác thực bằng socket, không phải lỗi cài đặt.

ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' từ ứng dụng dù password đúng. Account tồn tại dưới tên 'appuser'@'localhost', nhưng ứng dụng đang kết nối qua TCP đến 127.0.0.1 trên server đã tắt phân giải host name (skip-name-resolve). Vì vậy MariaDB xem hai host này là khác nhau: localhost là Unix socket, còn 127.0.0.1 là TCP. Trỏ ứng dụng đến host localhost để dùng socket và khớp với account, hoặc tạo account thứ hai là 'appuser'@'127.0.0.1' nếu framework chỉ hỗ trợ TCP.

AH01071: Got error 'Primary script unknown' trong /var/log/apache2/testapp-error.log, trong khi trình duyệt hiển thị File not found.. Apache đã chuyển request cho PHP-FPM, nhưng FPM không tìm thấy script tại đường dẫn Apache cung cấp. Có 2 nguyên nhân thường gặp: FPM socket trong cấu hình trỏ đến một phiên bản PHP chưa được cài (ví dụ socket php8.4 còn tồn tại sau khi upgrade, trong khi chỉ có 8.3 đang chạy), hoặc file thực sự không tồn tại vì DocumentRoot và thư mục thực tế không khớp. Kiểm tra socket có tồn tại bằng ls -l /run/php/, xác nhận DocumentRoot khớp với vị trí file, rồi restart cả php8.3-fpmapache2.

AH00558: apache2: Could not reliably determine the server's fully qualified domain name mỗi khi restart. Đây là warning không gây hại, không phải error. Apache đang báo rằng chưa đặt ServerName trên toàn hệ thống. Để ẩn cảnh báo, ghi ServerName your.domain vào /etc/apache2/conf-available/servername.conf rồi chạy sudo a2enconf servername.

(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80 khi Apache khởi động. Một web server khác đang chiếm port 80, thường là một nginx còn sót lại từ lần thử trước. Tìm tiến trình đó bằng sudo ss -ltnp | grep :80, sau đó stop và disable service kia trước khi khởi động Apache.

FAQ

mod_php hay PHP-FPM - tôi nên dùng cái nào?

Hãy dùng PHP-FPM. mod_php nhúng trình thông dịch vào mọi tiến trình Apache và buộc dùng MPM prefork chậm, nên Apache vẫn phải chịu overhead của PHP ngay cả khi chỉ phục vụ một ảnh tĩnh. PHP-FPM chạy PHP trong một pool riêng có thể tinh chỉnh độc lập. Apache kết nối đến pool này qua socket. PHP-FPM hoạt động với MPM event dạng threaded nhanh hơn và sau này có thể chuyển sang nginx mà không phải thay đổi cách triển khai. Đây là lựa chọn mặc định hiện nay. mod_php chỉ phù hợp với ứng dụng cũ phụ thuộc vào một số hành vi trong cùng tiến trình.

Tại sao trình duyệt tải file PHP xuống thay vì chạy file?

Apache đang xử lý file .php như một file tĩnh để tải xuống vì chưa gắn PHP handler cho file đó. Trên Ubuntu 24.04 dùng FPM, điều này có nghĩa là bạn đã bỏ sót một trong các bước sudo a2enmod proxy_fcgi, sudo a2enconf php8.3-fpm hoặc chưa restart Apache sau đó. Hãy chạy cả ba bước rồi reload. Sau đó dùng apache2ctl -M | grep fcgi để xác nhận proxy_fcgi_module được liệt kê. Trong thời gian chưa khắc phục, server đang để lộ source code, nên hãy xử lý ngay.

Tại sao MariaDB từ chối quyền truy cập root dù tôi nhập đúng password?

Vì không có password, MariaDB trên Ubuntu xác thực account root bằng unix_socket và liên kết account này với root user của hệ điều hành. Chạy mysql -u root từ một shell thông thường sẽ trả về ERROR 1698 (28000): Access denied for user 'root'@'localhost' theo đúng thiết kế. Thay vào đó, hãy kết nối bằng sudo mysql. Với mỗi ứng dụng, hãy tạo một user riêng có xác thực bằng password thay vì dùng lại root.

Làm thế nào để thêm HTTPS cho site LAMP?

Cài đặt certbotpython3-certbot-apache, trỏ bản ghi A của domain về server, rồi chạy sudo certbot --apache. Apache authenticator xác minh quyền kiểm soát domain thông qua Apache đang chạy. Trình cài đặt sẽ sửa virtual host cho cổng 443 và thiết lập tự động gia hạn. Hướng dẫn đầy đủ về Certbot và Apache trình bày challenge, timer gia hạn và các nguyên nhân lỗi thường gặp.

#lamp#apache#mariadb#php-fpm#ubuntu