PHP+nginx setup tricks

General notes:

  • The trial follows the way I’ve discovered the solutions of the problem. Following it directly reproduces most of my mistakes and quests. If the final solution is necessary, it’s recommended to pre-read the article before you begin
  • All the shell commands consider root user is active (sudo runuser) or sudo execution is performed (sudo ...)

The general task is to prepare LEMP stack to proceed with webserver with some PHP-driven CMS (Content management system) onboard.

E.g. actual WordPress state demands PHP 7.4 installed, so go on with it on Oracle Cloud Infrastructure powered server.

Now I have a new configuration, it’s ARM64 Ampere A1 shape with 2 cores and 12 Gb RAM (it’s a half of what can be allowed in the frame of Always Free Eligible performance). The OS image is standard Oracle Linux 8.

PHP 7.4

Installing the PHP directly from OL8 AppStream (default Oracle Linux repository) by default provides us with version 7.2, which is lower than expected.

The googling leads to: init epel (an additional package repository that provides easy access to install packages for commonly used software) and remi (free and stable YUM/DNF repository mainly for the PHP stack) repositories; install the latest versions from there.

dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
dnf install https://rpms.remirepo.net/enterprise/remi-release-8.rpm

BUT: if some ARM64 (aarch64) is in use, the remi repository is not our way, it has no build for aarch64. The solution appears to be simplier: OL8 AppStream (aarch64) already contains modules of PHP up to 7.4, just enable 7.4 instead of 7.2 by default.

If some of php is already installed the try to enable a different version causes error message.

Remove previous installation if any persists, reset PHP module and enable a new one. And after install PHP and its the most common frameworks.

dnf remove php
dnf module reset php
dnf module enable php:7.4
dnf install php php-cli php-fpm php-gd php-ldap php-mysqlnd php-odbc php-pdo php-opcache php-pear php-json php-xml php-xmlrpc php-mbstring php-snmp php-soap php-zip

Talking ahead, I’ve lost 3 days fighting with WordPress error 404 and trying to trace along the bunch of PHP-modules, until nginx logs (/var/log/nginx/) display the multiple records with json_decode() funtion, which is undefined: missed php-json during php installation.

The common advice, which may be found on every LEMP/LAMP stacks or PHP installation manuals: to restrict the try of find a proper action from the side of PHP-processing module if requested file is not found – it may lead to the vulnerability against the script injection attacks, which I have a blured understanding about, but sounds nasty. So, protect yourself:

nano /etc/php.ini

Find and correct the parameter (‘1’ to ‘0’)

cgi.fix_pathinfo=0

nginx

The easiest in the present trial is to install the nginx itself:

dnf install nginx

Open firewall for http traffic:

firewall-cmd --permanent --add-service=http

Check if http service is succesfully registered:

firewall-cmd --permanent --list-all | grep http

Register nginx as a permanent runnung service:

systemctl enable --now nginx

Check the nginx is running:

systemctl status nginx

Open a browser on a remote PC or on GUI and type in your server address (try ip addres show shell command on the server if to display network interfaces with addresses). The nginx dummy page appears in the browser window:

nginx test page

Setup

Now, get to PHP and configure PHP to work with nginx: here is the php-fpm responsibility.

nano /etc/php-fpm.d/www.conf

The nginx runs under its own user ‘nginx’ by default. So set the same for php-fpm.

In [www] section find and replace user and group designations:
user = nginx
group = nginx

It’s time to check how it works. Create the test php-module :

cd /usr/share/nginx/html/

echo '<?php phpinfo();>' >> info.php

Then use the chown command to assign the new file to the nginx user:

chown nginx.nginx /usr/share/nginx/html/info.php

Enable php-fpm and restart nginx:

systemctl enable --now php-fpm

systemctl restart nginx

Check if it all run:

ps -efl | grep nginx

The output has to have a look a kind of:

5 S nginx 1517785 1517784 0 80 0 - 889 ep_pol 07:19 ? 00:00:00 nginx: worker process
5 S nginx 1517786 1517784 0 80 0 - 889 ep_pol 07:19 ? 00:00:00 nginx: worker process
5 S nginx 1530145 1530144 0 80 0 - 3468 skb_wa 08:09 ? 00:00:00 php-fpm: pool www
5 S nginx 1530146 1530144 0 80 0 - 3468 skb_wa 08:09 ? 00:00:00 php-fpm: pool www
5 S nginx 1530147 1530144 0 80 0 - 3468 skb_wa 08:09 ? 00:00:00 php-fpm: pool www
5 S nginx 1530148 1530144 0 80 0 - 3468 skb_wa 08:09 ? 00:00:00 php-fpm: pool www
5 S nginx 1530149 1530144 0 80 0 - 3468 skb_wa 08:09 ? 00:00:00 php-fpm: pool www

Finally, open the web browser and enter server address (IP or domain) with test file after:

<server address>/info.php

The following PHP-info page has to be displayed in browser window:

PHP info page

In many manuals and advices it’s recommended not to use the default users to run web-engine and PHP process manager, therefore let’s create a new one (add -M to prevent the creation of home-directory):

sudo useradd -M web

This user is supposed to be pointed in nginx and php-fpm config files (actually it can be a different users, doesn’t matter, but for this example we use the same for both modules):

sudo nano /etc/nginx/nginx.conf

Find and set the parameter:

user web;

Then fix php-fpm config a little:

nano /etc/php-fpm.d/www.conf

In [www] section find and replace user and group designations:
user = web
group = web

Now, restart php-fpm nginx:

systemctl restart php-fpm

systemctl restart nginx

Check if it all works: sudo ps -efl | grep web

Enter the test address into the browser address field…

… and…

It’s a traditional thing for most of IT trials and Stackoverflow threads – it doesn’t work. If the user of nginx is changed to anything else than ‘nginx’, the php-fpm loses the bind with nginx and the error 503 (‘Service temporarily unavailable’) appears instead of php-info page.

This is a thing, which broke my mind completely (it appears to be quite easy to do): direct googling requests led to common installation and setup manuals and simple forum debates, but no mention of the sympthom, mostly, reckon, because it’s hardly possible to formulate the problem itself clearly to make the search engine understand, which trouble is actually meant.

Most of example configs have the following parameters inside /etc/php-fpm.d/www.conf active:

listen.owner = web

listen.group = web

listen.mode = 0660

If the different users set for nginx and php-fpm, the listen.owner and listen.group have to be equal to nginx config values.

OK, set them up and restart php-fpm and check the status of the service:

systemctl status php-fpm

Something is not so good, we have the warnings:

WARNING: [pool www] ACL set, listen.owner = 'webserver' is ignored
WARNING: [pool www] ACL set, listen.group = 'webserver' is ignored

Now, google the ignoring of listen. parameters relative to ACL and the serverfault discussion is on the top. Appears the additional parameters of access control located a bit below in /etc/php-fpm.d/www.conf:

; When POSIX Access Control Lists are supported you can set them using
; these options, value is a comma separated list of user/group names.
; When set, listen.owner and listen.group are ignored
listen.acl_users = apache, nginx
;listen.acl_groups =

Thank gosh, it’s found. Here are a couple of way how to proceed:

  1. Change the apache, nginx value to our web and comment listened. parameters
  2. Comment the string listen.acl_users = apache, nginx, keeping user, owner and listened. parameters active.

Finally restart php-fpm and nginx and enjoy the PHP test page again.

This entry was posted in linux, PHP, web. Bookmark the permalink.