PHP permissions issue? Bare-metal nginx setup

Hey there, everyone. So I've been spoiled by shared hosting for far too many years, so I've decided to experiment in what it takes to set up a FreeBSD-based web server from "bare metal" (right now, for testing purposes, that means a VirtualBox session not exposed to the internet). I've also not set up nginx before.

I think I have nginx working ok... a test index.html file is displayed. So the next step was to get PHP set up so that a CMS can work (I do not need MySQL in this instance). However trying to start the CMS after uploading it to the web directory (same place I had the test index.html) does not work even after setting the same file permissions. nginx's error.log contains tons of "Permission denied" PHP errors. So I believe I'm looking at something PHP-specific here, clearly requiring more than just installing PHP (newbie alert). I installed php81 and the following modules: php81-ctype php81-curl php81-dom php81-iconv php81-gd php81-mbstring php81-session php81-simplexml php81-xml php81-zip php81-zlib php81-filter php81-ftp php81-tokenizer php81-calendar php81-fileinfo (I believe php*-json and php*-openssl are also required but they don't appear available in php81-* versions). Then I simply:

Code:
# sysrc php_fpm_enable=yes
# service php-fpm start

Tutorials I found online didn't go any deeper than that re: PHP but clearly I'm missing something. Anyone feeling gentle and willing to guide me, provide insight or point me to a proper tutorial?

I do have a dummy user for the website set up with no password, no login and disabled. Unclear what it should own vs what www should own. Does the dummy user need to be part of wheel?
 
Assuming that you have php-fpm configured to listen on socket /var/run/php_fpm.sock - here's an minimal nginx server block which uses the php-fpm backend:
Code:
server {
    listen 192.168.7.29:80;
    server_name example.com;

    root /usr/local/www/your_website;
    index index.php;
  
    location / {
        try_files $uri $uri/ /index.php$args;
    }

    location ~ ^/(.*)\.(php|phtml)$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php_fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Getting php-fpm to spawn the socket is as simple as:
Code:
listen = /var/run/php_fpm.sock
and permissions:
Code:
listen.owner = www
listen.group = www
listen.mode = 0660
The corresponding location block in the nginx config depends on multiple factors so you'll most likely have to modify it to fit your requirements.
Also don't forget to read the documentation - don't just blindly copy things.

The "important" thing is that nginx actually has permissions to use the php-fpm socket. Usually you'd run nginx as user www. Hence we also setup the php-fpm config accordingly.
 
Assuming that you have php-fpm configured to listen on socket /var/run/php_fpm.sock

Well... let's not assume! :D Can you elaborate? How do I confirm?

Here's my current server block:
Code:
server {
 listen 80;
 server_name xxxxxxxx.xxx www.xxxxxxxx.xxx 192.168.1.44;
 root /xxxxxxxx;
 index index.php;
 location ~ \.php$ {
 fastcgi_split_path_info ^(.+\.php)(/.+)$;
 try_files $fastcgi_script_name =404;
 set $path_info $fastcgi_path_info;
 fastcgi_param PATH_INFO $path_info;
 fastcgi_index index.php;
 include fastcgi_params;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_pass 127.0.0.1:9000;
 }
 location / {
 try_files $uri $uri/ /index.php?$args;
 }
 location ^~ /bl-content/tmp/ { deny all; }
 location ^~ /bl-content/pages/ { deny all; }
 location ^~ /bl-content/databases/ { deny all; }
}

Should I just add those "listen" lines to that? Or is there something intrinsically wrong with what I have now?
 
In the nginx config block that you're showing nginx will "invoke" php-fpm via 127.0.0.1:9000. That works as well - no strict need to use the Unix socket - especially if you're just getting started.

Should I just add those "listen" lines to that?
Nah, those would be located in your php-fpm configuration (by default /usr/local/etc/php-fpm.d/www.conf). Check for those lines in there.
For a generic setup, make sure that both php-fpm and nginx are running as the www user.
 
Ok, I added listen = /var/run/php_fpm.sock to /usr/local/etc/php-fpm.d/www.conf and uncommented out the other 3 lines (which were already there in commented form). Rebooted for safe measure.

Code:
# ps -aux | grep nginx
root  762   0.0  0.8 21520  8000  -  Is   12:13   0:00.00 nginx: master process /usr/local/sbin/nginx
www   764   0.0  0.8 21520  8476  -  I    12:13   0:00.00 nginx: worker process (nginx)

# ps -aux | grep php
root  756   0.0  1.7 50336 16848  -  Ss   12:13   0:00.01 php-fpm: master process (/usr/local/etc/php-fpm.conf) (php-f
www   758   0.0  1.7 50336 16860  -  I    12:13   0:00.00 php-fpm: pool www (php-fpm)
www   759   0.0  1.7 50336 16860  -  I    12:13   0:00.00 php-fpm: pool www (php-fpm)

Now, when I try to pull up the root URL, I get "502 Bad Gateway". Progress? I'm not getting anything in the nginx logs though.
 
When you modify the the listen part to use the socket you'll also need to modify your fastcgi_pass setting in your nginx config.

No need to reboot:
Code:
service nginx restart
service php-fpm restart
 
Ok, I changed the fastcgi_pass line to:
Code:
fastcgi_pass unix:/var/run/php_fpm.sock;

That fixed the 502 error, but now we're back to a blank page return and a flood of "Permission denied" errors in nginx error.log. I seem to have a fundamental permissions issue that I still don't understand.
 
Do your "website files" have the necessary permissions for user/group www:www to access them?
 
Do your "website files" have the necessary permissions for user/group www:www to access them?
Well, even if I chown -R www:www the entire directory of files, the end result is mostly the same. I don't get anything in the nginx error.log but the web page is still just spitting out a "1" (only visible if you view source). Although I read conflicting information about doing this... some guides say www:www should own everything, others say that's a security risk and have it be the "dummy" account instead. What are your thoughts?

And should "www" and/or the dummy account be a member of "wheel"?
 
Please post the output of the following commands:
  • sockstat -l | grep nginx
  • sockstat -l | grep php
  • ls -l /path/to/your/www/root
some guides say www:www should own everything
This is not a "one rule fits all" situation. File permissions need to be evaluated carefully. Some (php) application might have configuration files which should definitely be read-only, other files should not be exposed to the webserver at all etc. Refer to your application's documentation and be as restrictive as possible (or as reasonable within your requirements).
Also note that there is more to this than just user/group. The actual permissions themselves matter too.

others say that's a security risk
Almost everything is a security risk.

have it be the "dummy" account instead. What are your thoughts?
Rather than having dummy accounts, you probably just want to make proper use of jails.
I tend to have one jail per web service. This way, if ever there is a breach into the system, the attacker cannot do anything outside the jail. Furthermore, backup and maintenance tasks become easier as it's a self-contained unit.
Please note that there is a magnitude of different "security risks" and attack vectors. This is not something that can be covered in a forum topic.

And should "www" and/or the dummy account be a member of "wheel"?
Definitely a hard "No!" on this one.
 
Code:
#  sockstat -l | grep nginx
www      nginx      1104  6  tcp4   *:80                  *:*
root     nginx      1103  6  tcp4   *:80                  *:*

Code:
#  sockstat -l | grep php
www      php-fpm    1123  5  stream /var/run/php_fpm.sock
www      php-fpm    1122  5  stream /var/run/php_fpm.sock
root     php-fpm    1121  7  stream /var/run/php_fpm.sock

Code:
# ls -l /websitedata/
total 48
-rw-r--r--   1 www  www   1083 Jul 29  2020 LICENSE
drw-r--r--   2 www  www    512 Jun 15 20:59 bl-content
drw-r--r--  10 www  www   1024 Jun 15 20:59 bl-kernel
drw-r--r--   2 www  www   1024 Jun 15 20:59 bl-languages
drw-r--r--  27 www  www    512 Jun 15 20:59 bl-plugins
drw-r--r--   4 www  www    512 Jun 15 20:59 bl-themes
-rw-r--r--   1 www  www    900 Jul 29  2020 index.php
-rw-r--r--   1 www  www  20294 Jul 29  2020 install.php
 
Anyone feeling gentle and willing to guide me, provide insight or point me to a proper tutorial?
Not a tutorial per se, but I did come across this book recently. I haven't bought it yet so can't comment on it's content. However, I was pleasantly surprised to see that it treats FreeBSD as it's main OS when setting up a website. And even if you don't buy the book, you may find inspiration amongst the scripts that the author has kindly posted on Github here.
 
Not a tutorial per se, but I did come across this book recently. I haven't bought it yet so can't comment on it's content. However, I was pleasantly surprised to see that it treats FreeBSD as it's main OS when setting up a website. And even if you don't buy the book, you may find inspiration amongst the scripts that the author has kindly posted on Github here.

Thanks for the lead! I'll definitely check out that book.
 
Back
Top