Kiến thức Hữu ích 😍

Hướng dẫn cài đặt nhiều PHP trên CentOS 7 với Apache & PHP-FPM


Trong thế giới phát triển web hiện đại, việc quản lý một máy chủ có khả năng chạy nhiều ứng dụng khác nhau là vô cùng quan trọng. Mỗi ứng dụng có thể yêu cầu một phiên bản PHP cụ thể để hoạt động ổn định, từ những dự án cũ cần PHP 5.6 đến các nền tảng mới nhất chạy trên PHP 8.x. Việc chỉ sử dụng một phiên bản PHP duy nhất thường dẫn đến xung đột, không tương thích và làm giảm hiệu suất của toàn bộ hệ thống. Đây là một bài toán đau đầu đối với các nhà quản trị hệ thống và các đơn vị cung cấp dịch vụ hosting.

Để giải quyết vấn đề này, giải pháp kết hợp giữa máy chủ web Apache và PHP-FPM (FastCGI Process Manager) trên hệ điều hành CentOS 7 đã chứng tỏ được hiệu quả vượt trội. Phương pháp này cho phép bạn cài đặt và chạy song song nhiều phiên bản PHP, mỗi phiên bản phục vụ cho một hoặc nhiều website cụ thể một cách độc lập và an toàn. Bài viết này sẽ hướng dẫn bạn chi tiết từng bước, từ nhu cầu thực tế, tổng quan công nghệ, cách cài đặt, cấu hình, cho đến các lưu ý quan trọng để quản lý đa phiên bản PHP một cách chuyên nghiệp và tối ưu nhất.

Nhu cầu và tổng quan về Apache, PHP-FPM trong quản lý đa phiên bản PHP

Nhu cầu chạy nhiều phiên bản PHP trên một máy chủ

Tại sao chúng ta cần chạy nhiều phiên bản PHP trên cùng một máy chủ? Nhu cầu này xuất phát từ nhiều lý do thực tế trong môi trường phát triển và vận hành website.

Thứ nhất, đó là vấn đề về tương thích ứng dụng. Nhiều doanh nghiệp vẫn đang duy trì các website hoặc ứng dụng cũ được xây dựng trên các phiên bản PHP đã lỗi thời như PHP 5.6. Việc nâng cấp toàn bộ mã nguồn lên phiên bản mới hơn có thể tốn kém và mất nhiều thời gian. Song song đó, các dự án mới lại yêu cầu những tính năng và hiệu suất vượt trội của các phiên bản PHP mới nhất như PHP 7.4 hay PHP 8.0. Việc chạy đa phiên bản giúp cả ứng dụng cũ và mới cùng tồn tại hòa bình trên một hạ tầng duy nhất.

Thứ hai, sự đa dạng của các framework. Mỗi PHP framework có thể có yêu cầu phiên bản PHP khác nhau. Ví dụ, một dự án Laravel cũ có thể chạy tốt trên PHP 7.2, trong khi phiên bản Laravel mới nhất lại yêu cầu PHP 8.0. Đối với các công ty cung cấp dịch vụ hosting cho nhiều khách hàng, việc đáp ứng yêu cầu đa dạng này là yếu tố sống còn để giữ chân khách hàng. Mỗi khách hàng có thể sử dụng một mã nguồn mở hoặc framework khác nhau, và máy chủ cần đủ linh hoạt để phục vụ tất cả.

Hình minh họa

Tổng quan về Apache và PHP-FPM

Để hiểu cách chúng ta có thể chạy nhiều phiên bản PHP, hãy cùng tìm hiểu vai trò của hai công nghệ cốt lõi: Apache và PHP-FPM.

Apache (HTTP Server) là một trong những máy chủ web phổ biến nhất thế giới. Nhiệm vụ chính của nó là lắng nghe các yêu cầu từ trình duyệt của người dùng (HTTP requests) và trả về nội dung web tương ứng, chẳng hạn như file HTML, CSS, ảnh, hoặc thực thi các đoạn mã kịch bản phía máy chủ. Tuy nhiên, bản thân Apache không thể tự xử lý mã PHP. Nó cần một “thông dịch viên” để thực thi mã PHP và trả về kết quả.

Hình minh họa

PHP-FPM (FastCGI Process Manager) chính là “thông dịch viên” hiệu suất cao đó. Nó là một trình quản lý tiến trình FastCGI dành riêng cho PHP, được thiết kế để xử lý các yêu cầu PHP một cách hiệu quả. Ưu điểm lớn nhất của PHP-FPM là khả năng quản lý các “pool” (nhóm tiến trình) độc lập. Mỗi pool có thể được cấu hình để chạy với một phiên bản PHP khác nhau, với người dùng hệ thống (user) riêng và các thiết lập tài nguyên riêng biệt.

Mối liên hệ giữa chúng rất đơn giản: Khi Apache nhận một yêu cầu truy cập file `.php`, thay vì tự xử lý, nó sẽ chuyển tiếp (proxy) yêu cầu đó đến một pool PHP-FPM cụ thể đã được cấu hình trước. PHP-FPM sẽ thực thi mã PHP, sau đó gửi kết quả trở lại cho Apache, và cuối cùng Apache trả về nội dung cho người dùng. Bằng cách định tuyến yêu cầu đến các pool PHP-FPM khác nhau, chúng ta có thể điều khiển chính xác phiên bản PHP nào sẽ xử lý cho website nào.

Hình minh họa

Hướng dẫn cài đặt và cấu hình nhiều phiên bản PHP trên CentOS 7

Để bắt đầu, chúng ta cần chuẩn bị môi trường CentOS 7 và cài đặt các phiên bản PHP mong muốn. Quá trình này bao gồm việc thêm kho phần mềm (repository) và cấu hình PHP-FPM cho từng phiên bản.

Cài đặt các phiên bản PHP cần thiết trên CentOS 7

Hệ điều hành CentOS 7 mặc định chỉ cung cấp một phiên bản PHP khá cũ. Để cài đặt nhiều phiên bản mới hơn, chúng ta cần sử dụng kho phần mềm của bên thứ ba. Remi Repository là một lựa chọn phổ biến và đáng tin cậy.

Trước tiên, hãy cài đặt EPEL (Extra Packages for Enterprise Linux) và các công cụ cần thiết:

sudo yum install -y epel-release yum-utils

Tiếp theo, cài đặt Remi Repository:

sudo yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm

Sau khi cài đặt xong, chúng ta cần kích hoạt các kho chứa phiên bản PHP mong muốn. Ví dụ, để cài đặt PHP 5.6, 7.4 và 8.0, bạn chạy các lệnh sau để kích hoạt kho tương ứng:

sudo yum-config-manager --enable remi-php56
sudo yum-config-manager --enable remi-php74
sudo yum-config-manager --enable remi-php80

Bây giờ, bạn có thể tiến hành cài đặt các phiên bản PHP cùng với PHP-FPM và một số extension phổ biến. Tên gói sẽ có tiền tố tương ứng với phiên bản, ví dụ php56, php74.

Cài đặt PHP 5.6:

sudo yum install -y php56 php56-php-fpm php56-php-mysqlnd php56-php-gd php56-php-xml

Cài đặt PHP 7.4:

sudo yum install -y php74 php74-php-fpm php74-php-mysqlnd php74-php-gd php74-php-xml php74-php-mbstring

Cài đặt PHP 8.0:

sudo yum install -y php80 php80-php-fpm php80-php-mysqlnd php80-php-gd php80-php-xml php80-php-mbstring

Sau khi cài đặt, bạn cần khởi động và cho phép các dịch vụ PHP-FPM tự khởi chạy cùng hệ thống:

sudo systemctl enable php56-php-fpm && sudo systemctl start php56-php-fpm
sudo systemctl enable php74-php-fpm && sudo systemctl start php74-php-fpm
sudo systemctl enable php80-php-fpm && sudo systemctl start php80-php-fpm

Hình minh họa

Cấu hình PHP-FPM cho từng phiên bản PHP

Mỗi phiên bản PHP-FPM sẽ có một file cấu hình chính và các file cấu hình pool riêng. Nhiệm vụ của chúng ta là đảm bảo mỗi pool lắng nghe trên một cổng (port) hoặc một file socket khác nhau để tránh xung đột.

File cấu hình chính thường nằm tại /etc/opt/remi/phpXX/php-fpm.conf và các pool nằm trong thư mục /etc/opt/remi/phpXX/php-fpm.d/. Mặc định, mỗi phiên bản sẽ có một pool tên là www.conf.

Chúng ta sẽ chỉnh sửa file www.conf của từng phiên bản. Đối với PHP 5.6: Mở file /etc/opt/remi/php56/php-fpm.d/www.conf. Tìm dòng listen = 127.0.0.1:9000 và giữ nguyên hoặc đổi thành một cổng khác nếu cần. Đồng thời, bạn nên thay đổi user và group để tăng cường bảo mật.

; File: /etc/opt/remi/php56/php-fpm.d/www.conf
user = apache
group = apache
listen = 127.0.0.1:9056

Đối với PHP 7.4: Mở file /etc/opt/remi/php74/php-fpm.d/www.conf. Thay đổi cổng lắng nghe để không trùng với PHP 5.6.

; File: /etc/opt/remi/php74/php-fpm.d/www.conf
user = apache
group = apache
listen = 127.0.0.1:9074

Đối với PHP 8.0: Mở file /etc/opt/remi/php80/php-fpm.d/www.conf. Tiếp tục thay đổi cổng lắng nghe.

; File: /etc/opt/remi/php80/php-fpm.d/www.conf
user = apache
group = apache
listen = 127.0.0.1:9080

Sau khi chỉnh sửa, hãy khởi động lại tất cả các dịch vụ PHP-FPM để áp dụng thay đổi:

sudo systemctl restart php56-php-fpm
sudo systemctl restart php74-php-fpm
sudo systemctl restart php80-php-fpm

Đến đây, chúng ta đã có ba phiên bản PHP-FPM đang chạy song song, mỗi phiên bản lắng nghe trên một cổng TCP riêng biệt, sẵn sàng để Apache kết nối đến.

Hình minh họa

Thiết lập Apache để chạy đa phiên bản PHP qua PHP-FPM

Sau khi đã cài đặt và cấu hình các phiên bản PHP-FPM, bước tiếp theo là “chỉ đường” cho Apache biết phải gửi yêu cầu xử lý file PHP đến pool FPM nào. Chúng ta thực hiện việc này thông qua cấu hình Virtual Host.

Cấu hình Virtual Host Apache với PHP-FPM

Phương pháp phổ biến và hiệu quả nhất để kết nối Apache với PHP-FPM là sử dụng mod_proxy_fcgi thông qua chỉ thị ProxyPassMatch. Điều này cho phép chúng ta tạo ra các quy tắc linh hoạt để định tuyến yêu cầu dựa trên tên miền hoặc thư mục.

Giả sử chúng ta có hai website: site-php74.azweb.vn cần chạy PHP 7.4 và site-php80.azweb.vn cần chạy PHP 8.0. Chúng ta sẽ tạo hai file cấu hình Virtual Host tương ứng trong thư mục /etc/httpd/conf.d/.

Tạo Virtual Host cho site-php74.azweb.vn (sử dụng PHP 7.4):
Tạo file /etc/httpd/conf.d/site-php74.conf với nội dung sau:

<VirtualHost *:80>
    ServerName site-php74.azweb.vn
    DocumentRoot /var/www/site-php74

    <Directory /var/www/site-php74>
        AllowOverride All
        Require all granted
    </Directory>

    # Định tuyến file .php tới PHP-FPM 7.4 đang lắng nghe ở cổng 9074
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9074/var/www/site-php74/$1
</VirtualHost>

Đừng quên tạo thư mục chứa mã nguồn: sudo mkdir -p /var/www/site-php74.

Tạo Virtual Host cho site-php80.azweb.vn (sử dụng PHP 8.0):
Tạo file /etc/httpd/conf.d/site-php80.conf với nội dung sau:

<VirtualHost *:80>
    ServerName site-php80.azweb.vn
    DocumentRoot /var/www/site-php80

    <Directory /var/www/site-php80>
        AllowOverride All
        Require all granted
    </Directory>

    # Định tuyến file .php tới PHP-FPM 8.0 đang lắng nghe ở cổng 9080
    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9080/var/www/site-php80/$1
</VirtualHost>

Và tạo thư mục tương ứng: sudo mkdir -p /var/www/site-php80.

Sau khi tạo các file cấu hình, hãy kiểm tra cú pháp của Apache và khởi động lại dịch vụ:

sudo apachectl configtest
sudo systemctl restart httpd

Nếu configtest báo Syntax OK, bạn đã cấu hình thành công.

Hình minh họa

Kiểm tra, xác thực hoạt động song song của các phiên bản PHP

Để chắc chắn rằng mọi thứ hoạt động đúng như mong đợi, cách đơn giản nhất là tạo một file info.php trong thư mục gốc của mỗi website.

Tạo file /var/www/site-php74/info.php với nội dung:

<?php
phpinfo();
?>

Tạo file tương tự trong /var/www/site-php80/info.php.

Bây giờ, hãy truy cập vào hai địa chỉ sau từ trình duyệt của bạn (bạn cần trỏ domain về IP server hoặc chỉnh sửa file hosts trên máy tính cá nhân):

Nếu cấu hình chính xác, trang đầu tiên sẽ hiển thị thông tin chi tiết về PHP phiên bản 7.4, còn trang thứ hai sẽ hiển thị thông tin của PHP 8.0. Điều này xác nhận rằng Apache đã định tuyến yêu cầu thành công đến đúng pool PHP-FPM. Bạn cũng nên kiểm tra các file log của Apache (/var/log/httpd/error_log) và của từng phiên bản PHP-FPM để đảm bảo không có lỗi nào xảy ra trong quá trình hoạt động.

Hình minh họa

Các vấn đề thường gặp và cách xử lý

Khi triển khai một hệ thống phức tạp như chạy đa phiên bản PHP, việc gặp phải lỗi là điều khó tránh khỏi. Dưới đây là hai vấn đề phổ biến nhất và cách khắc phục chúng một cách hiệu quả.

Xung đột cổng hoặc socket PHP-FPM giữa các phiên bản

Đây là lỗi cơ bản nhưng rất hay gặp. Khi hai hoặc nhiều pool PHP-FPM được cấu hình để lắng nghe trên cùng một cổng TCP (ví dụ 127.0.0.1:9000) hoặc cùng một file socket (ví dụ /var/run/php-fpm/php-fpm.sock), dịch vụ khởi động sau sẽ báo lỗi và không thể chạy được.

Nguyên nhân: Mỗi cổng hoặc socket trên hệ thống chỉ có thể được “chiếm giữ” bởi một tiến trình tại một thời điểm.

Hướng giải quyết:

  1. Kiểm tra cấu hình: Mở tất cả các file cấu hình pool (ví dụ www.conf của các phiên bản PHP) và kiểm tra kỹ giá trị của chỉ thị listen.
  2. Đảm bảo tính duy nhất: Hãy chắc chắn rằng mỗi pool sử dụng một cổng hoặc một đường dẫn socket hoàn toàn khác nhau. Ví dụ: listen = 127.0.0.1:9056 cho PHP 5.6, listen = 127.0.0.1:9074 cho PHP 7.4, và cứ thế tiếp tục.
  3. Khởi động lại dịch vụ: Sau khi đã sửa cấu hình, hãy khởi động lại tất cả các dịch vụ PHP-FPM liên quan để áp dụng thay đổi.
sudo systemctl restart php56-php-fpm php74-php-fpm php80-php-fpm

Kiểm tra trạng thái của các dịch vụ (systemctl status phpXX-php-fpm) để đảm bảo chúng đều đang ở trạng thái active (running).

Hình minh họa

Lỗi khi Apache không giao tiếp đúng với pool PHP-FPM

Đôi khi, bạn sẽ gặp phải lỗi 503 Service Unavailable hoặc 500 Internal Server Error khi truy cập website, mặc dù các dịch vụ PHP-FPM đều đang chạy. Điều này thường cho thấy Apache đang gặp vấn đề khi cố gắng kết nối với pool PHP-FPM được chỉ định.

Biểu hiện lỗi: Log của Apache (/var/log/httpd/error_log) có thể chứa các thông báo như (111)Connection refused hoặc proxy: FCGI: failed to make connection to backend.

Cách debug và khắc phục:

  1. Kiểm tra cấu hình Apache: Mở file Virtual Host của website bị lỗi. Đảm bảo rằng giá trị trong ProxyPassMatch (ví dụ fcgi://127.0.0.1:9074) khớp chính xác với giá trị listen trong file cấu hình pool PHP-FPM tương ứng. Sai một con số trong cổng cũng đủ gây ra lỗi.
  2. Kiểm tra tường lửa và SELinux: Đôi khi, tường lửa (firewalld) hoặc SELinux có thể chặn kết nối từ Apache đến cổng của PHP-FPM.
    • Thử tạm thời vô hiệu hóa SELinux (sudo setenforce 0) để xem vấn đề có được giải quyết không. Nếu có, bạn cần cấu hình lại các quy tắc của SELinux cho phù hợp.
    • Kiểm tra quy tắc tường lửa để đảm bảo các cổng FPM (9056, 9074, 9080…) được phép kết nối từ localhost.
  3. Kiểm tra quyền truy cập socket: Nếu bạn sử dụng socket thay vì cổng TCP, hãy đảm bảo rằng user mà Apache đang chạy (thường là apache) có quyền đọc và ghi trên file socket đó. Bạn có thể cần điều chỉnh listen.ownerlisten.group trong cấu hình pool FPM.

Các lưu ý và thực hành tốt khi chạy nhiều phiên bản PHP trên server

Quản lý một môi trường đa phiên bản PHP đòi hỏi sự cẩn trọng và tuân thủ các quy tắc thực hành tốt để đảm bảo hệ thống luôn ổn định, an toàn và hiệu quả. Dưới đây là những lưu ý quan trọng bạn nên áp dụng.

Luôn backup cấu hình trước khi thay đổi: Đây là quy tắc vàng trong quản trị hệ thống. Trước khi chỉnh sửa bất kỳ file cấu hình nào của Apache hay PHP-FPM, hãy tạo một bản sao lưu. Một lệnh cp config.conf config.conf.bak đơn giản có thể cứu bạn khỏi nhiều giờ khắc phục sự cố.

Chỉ khởi chạy các phiên bản PHP cần thiết: Mỗi dịch vụ PHP-FPM chạy nền đều tiêu tốn một lượng tài nguyên RAM và CPU nhất định. Nếu bạn không còn sử dụng một phiên bản PHP nào đó (ví dụ PHP 5.6), hãy tắt và vô hiệu hóa dịch vụ đó (sudo systemctl stop php56-php-fpm && sudo systemctl disable php56-php-fpm) để giải phóng tài nguyên cho các tác vụ quan trọng hơn.

Giám sát hiệu suất và logs thường xuyên: Hãy thiết lập thói quen kiểm tra các file log của Apache và từng phiên bản PHP-FPM. Log giúp bạn phát hiện sớm các lỗi tiềm ẩn, các cảnh báo về hiệu suất hoặc các dấu hiệu tấn công. Sử dụng các công cụ giám sát như top, htop, hoặc các giải pháp chuyên nghiệp hơn để theo dõi việc sử dụng tài nguyên của từng pool FPM.

Không dùng chung file cấu hình giữa các phiên bản: Mỗi phiên bản PHP có thể có các chỉ thị cấu hình (php.ini) khác nhau. Việc cố gắng dùng chung một file cấu hình cho nhiều phiên bản có thể gây ra lỗi không mong muốn. Hãy duy trì các file php.ini riêng biệt cho từng phiên bản và tùy chỉnh chúng theo nhu cầu cụ thể của ứng dụng chạy trên phiên bản đó.

Cập nhật bảo mật kịp thời từng phiên bản PHP: Đây là yếu tố cực kỳ quan trọng. Mỗi phiên bản PHP đều có vòng đời riêng và sẽ nhận được các bản vá bảo mật từ nhà phát triển. Hãy thường xuyên chạy lệnh sudo yum update để đảm bảo tất cả các phiên bản PHP và các gói liên quan trên máy chủ của bạn luôn được cập nhật lên phiên bản vá lỗi mới nhất, giúp bảo vệ hệ thống khỏi các lỗ hổng đã biết.

Hình minh họa

Kết luận

Việc chạy nhiều phiên bản PHP trên cùng một máy chủ CentOS 7 bằng cách kết hợp Apache và PHP-FPM là một kỹ thuật mạnh mẽ và linh hoạt. Nó không chỉ giải quyết được bài toán tương thích cho các dự án cũ và mới mà còn giúp tối ưu hóa việc sử dụng tài nguyên, tăng cường bảo mật bằng cách cô lập môi trường cho từng website. Thông qua các bước cài đặt kho phần mềm Remi, cấu hình các pool PHP-FPM độc lập và thiết lập Virtual Host trong Apache, bạn có thể xây dựng một môi trường hosting đa năng, đáp ứng mọi yêu cầu khắt khe nhất của các dự án web hiện đại.

Mặc dù quá trình cài đặt có vẻ phức tạp, nhưng những lợi ích về khả năng quản lý và mở rộng mà nó mang lại là vô cùng xứng đáng. AZWEB hy vọng rằng với hướng dẫn chi tiết này, bạn có thể tự tin áp dụng giải pháp này để tối ưu hóa máy chủ của mình, dù là cho mục đích phát triển cá nhân hay cung cấp dịch vụ hosting chuyên nghiệp. Đừng ngần ngại bắt tay vào thực hiện và khám phá sức mạnh của việc quản lý đa phiên bản PHP. Hãy tiếp tục theo dõi chúng tôi để cập nhật thêm nhiều kiến thức chuyên sâu về tối ưu hiệu suất và bảo mật cho máy chủ web.

Đánh giá