How to Setup Nginx for a PHP application on Fedora 28/29

30 November 2018

After switching from Linux Mint to Fedora 28/29 on my laptop, I had difficulties to run my Grav CMS or other PHP projects on Fedora OS. In the last 2 months, I've learned several things about the different between the Ubuntu-based OS and the RHEL-based OS. They are similar but some small differences can take so much time to run one application from other OS to another OS. My motivation was to clone my projects from my Git repositories (which were created under Linux Mint and Ubuntu), and run them on my laptop with Fedora 29. Unfortunately, it was not so easy and took more time as I thought.

Mostly the Fedora OS is just similar like other Linux distributions. Instead of sudo apt-get install, we write sudo dnf install for installing a new software package. So I can install Nginx and PHP-FPM with this command line:

sudo dnf install nginx php-fpm php-common

By default, the installed PHP creates a system user and a group name on Fedora which are declared as apache, where in Ubuntu we can find it as www-data. This difference can cause several permission issues if I want to run my Grav project (or other PHP web project) on Fedora 28/29 directly after git clone.

In my case, the Grav app runs on my server with Ubuntu 18.04. I synchronized the file from a Git repository of my server. After the clone, the folder group name is assigned as www-data. Since I don't want to have an inconsistency, I decided to use www-data instead of apache in my laptop.

In Fedora, the official place for the project directory is in /srv/www/mysite. However since I synchronize the project directory with git clone to my home folder, I need to ensure that the parent directories which points to the root folder has also a permission access for www-data. Otherwise I see an error message in /var/log/nginx/error.log. It can contain failed (13: Permission denied), for example:

2018/10/15 19:15:10 [crit] 31049#0: *1 stat() "/var/www/testsite/user/themes/antimatter/css/slidebars.min.css" failed (13: Permission denied), client: 127.0.0.1, server: testsite, request: "GET /user/themes/antimatter/css/slidebars.min.css HTTP/1.1", host: "testsite", referrer: "http://testsite/"

For more details, please read these discussions:

  1. serverfault.com - permission denied error 13.
  2. https://github.com/getgrav/grav/issues/2224

Fedora 28/29 Setting

Let's begin with the operating system first.

  1. As described before, I create a new system user called www-data as replacement to apache without home directory:

    sudo useradd -Mr www-data

    Maybe I can check whether the www-data user has been created before. To check its existence we need this command:

    ls /etc/group | grep www-data
  2. Clone the Grav project from your Git repository, for example to $HOME/mysite.
  3. Disable SELinux for NGINX:

    sudo semanage permissive -a httpd_t

    Or optionally you can allow httpd to access and write the user home directory (SELinux):

    sudo chcon -R -t httpd_sys_rw_content_t $HOME/mysite
    SE Linux Permission type Description
    httpd_sys_content_t Read-only directories and files used by Apache
    httpd_sys_rw_content_t Readable and writable directories and files used by Apache. Assign this to directories where files can be created or modified by your application, or assign it to files directory to allow your application to modify them.

Nginx Setting

These steps are my summary to install and configure Nginx:

  1. Install Nginx: dnf install nginx.
  2. Change the user of the Nginx process to www-data by opening the default config file in /etc/nginx/nginx.conf. Uncomment the first line user nginx and replace with user www-data. Check if include sites-enabled/; or include /etc/nginx/sites-enabled/; exists in /etc/nginx/nginx.conf. You can copy the nginx.conf from https://learn.getgrav.org/webservers-hosting/servers/nginx/.
  3. Create a nginx config file for your site under /etc/nginx/sites-available/mysite.conf, You can copy the configuration file from your downloaded Grav directory under webserver-configs/nginx.conf. Then, do these steps:

    • adapt the root folder,
    • adapt the server_name,
    • add accesslog and error_log folders to /var/log/nginx/mysite/_ (don't forget the semicolon at the end),
    • create the new directory sudo mkdir /var/log/nginx/mysite,
    • modify the fastcgi_pass path to unix:/run/php-fpm/php7.2-fpm.sock, since on Fedora the PHP folder installation is slightly different compared to the Ubuntu (check the PHP section below).

    Please see the details in the grav-site config section in https://learn.getgrav.org/webservers-hosting/servers/nginx/.

  4. Create a symbolic link to the /etc/nginx/sites-enabled/, e.g.:

    ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/mysite.conf

  5. activate the Nginx server:

    sudo systemctl enable nginx.service
    sudo systemctl start nginx.service
  6. Check if the Nginx worker process runs with www-data as the user:

    ps aux | grep nginx

    for example it returns:

    www-data  5973  0.0  0.0  39208  4752 ?        S    11:44   0:00 nginx: worker process
  7. Set the group of _/var/lib/nginx/ to www-data

    sudo chgrp www-data -R /var/lib/nginx
  8. Ensure that the directories to your root folder has a permission access for www-data:

    ls -l $HOME/testsite

PHP-FPM Setting

These steps help me to configure the PHP-FPM using the socket communication:

  1. Install php-fpm and php-common:

    sudo dnf install php-fpm php-common
  2. Install the required php modules:

    dnf install php-opcache php-json php-cli php-dom php-gd php-mbstring php-xml
  3. Edit the file /etc/php-fpm.d/www.conf, or create a new config file like /etc/php-fpm.d/grav.conf. Suppose I use the default www.conf file, then these setting are important:

    user = www-data
    group = www-data
    ; Note that in Ubuntu 18.04 the socket is under  /run/php/php7.2-fpm.sock
    listen = /run/php-fpm/php7.2-fpm.sock
    listen.owner = www-data
    listen.group = www-data

    Note that listen.acl_users has to stay commented. Otherwise the /run/php-fpm/php7.2-fpm.sock will be assigned as root for the owner and the group.

  4. Edit the default config in /etc/php.ini:

    file_uploads = On
    allow_url_fopen = On
    memory_limit = 256M
    upload_max_filesize = 100M
    max_execution_time = 360
    cgi.fix_pathinfo = 0
  5. Enable and start the php-fpm pool daemon:

    sudo systemctl enable php-fpm.service
    sudo systemctl start php-fpm.service
  6. Check the user of the running php-fpm pool is www-data:

    ps aux | grep php-fpm

    These output shows the two PHP pool (grav and www) with different usernames:

    www-data  6835  0.0  0.0 411644 10476 ?        S    12:01   0:00 php-fpm: pool grav
    
    apache    6840  0.0  0.0 411644 10484 ?        S    12:01   0:00 php-fpm: pool www
  7. Due to the custom username www-data instead of apache, we need the change the group folder of /var/lib/php/session, /var/lib/php/opcache, and /var/lib/php/wsdlcache.

     sudo chgrp www-data -R /var/lib/php/session /var/lib/php/opcache /var/lib/php/wsdlcache

    Execute this command to check the group owner: ls -l /var/lib/php.

Grav Setting

This section describes the Grav CMS as a specific PHP application. Errors, that come from the Grav CMS, can be seen in the /logs/grav.log file. The first step before analysing the error is to clear the cache using bin/grav clear-cache or sudo bin/grav clear-cache if you encounter the permission denied error.

Troubleshooting

This section describes all issues that I've encountered.

502 Bad Gateway

the error.log shows:

2018/12/23 12:22:03 [crit] 7780#0: *1 stat() "$HOME/mysite" failed (13: Permission denied), client: 127.0.0.1, server: localhost.mysite, request: "GET / HTTP/1.1", host: "localhost.mysite"
2018/12/23 12:22:03 [crit] 7780#0: *1 connect() to unix:/run/php-fpm/php7.2-fpm.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: localhost.mysite, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/php7.2-fpm.sock:", host: "localhost.mysite"

Cause

The group owner of socket file is not the same as the Nginx and PHP user:

ls -l /run/php-fpm/
total 4
srw-rw----. 1 root root 0 23. Dez 12:21 php7.2-fpm.sock

Which means that the listen.owner and listen.group in /etc/php-fpm.d/grav.conf are not set correctly or are still commented.

Solution

Change these lines in /etc/php-fpm.d/grav.conf:

listen.owner = www-data
listen.group = www-data

and restart the php-fpm application:

sudo systemctl restart php-fpm.service

Error Logs in /logs/grav.log

grav.Critical: Failed to start session: session_start(): Failed to read session data: filse ( path: /var/lib/php/session) 

Cause:

The PHP pool daemon with the user www-data cannot write on the folder /var/lib/php/session because on Fedora the standard group name is apache.

Solution:

sudo chgrp -R www-data /var/lib/php/opcache /var/lib/php/session /var/lib/php/wsdlcache

CSS and JS files are interpreted as MIME type

Error:

CSS and JS files are interpreted as MIME type text/html 

or

2018/10/15 19:15:10 [crit] 31049#0: *1 stat() "/var/www/testsite/user/themes/antimatter/css/slidebars.min.css" failed (13: Permission denied), client: 127.0.0.1, server: testsite, request: "GET /user/themes/antimatter/css/slidebars.min.css HTTP/1.1", host: "testsite", referrer: "http://testsite/"

Solution: https://github.com/getgrav/grav/issues/2224


Permission error in logs/grav.log

2018/12/23 15:59:03 [error] 14318#0: *10 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught UnexpectedValueException: The stream or file "$HOME/mysite/logs/grav.log" could not be opened: failed to open stream: Permission denied in $HOME/mysite/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php:107
Stack trace:#0 $HOME/mysite/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php(37): Monolog\Handler\StreamHandler->write(Array)

Cause

The grav.log file cannot be written due to the permission issue.

Solution

 sudo chmod 664 logs/grav.log