Apache unique Vhost user, PHP sessions not working - php

I am looking to run an number of Apache server which will host websites for multiple clients. I have installed the libapache2-mpm-itk module and have created unique users/groups for each clients set of files. And configured their corresponding vhost file to run the process with that user/group.
<IfModule mpm_itk_module>
AssignUserId www-client www-client1
</IfModule>
This works fine until I try to use PHP sessions. In the vhost file I have also added a custom session save path.
php_admin_value session.save_path "/var/www/html/client1/_php/session"
A PHP script is able to generate session files in the directory with the following permissions but isn't able to read them:
-rw------- www-client1 www-client1
A full example of my vhost is:
<VirtualHost *:443>
ServerName client1.com
ServerAlias client1.com www.client1.com
DocumentRoot /var/www/html/client1/www
ErrorLog /var/www/logs/client1/www-error.log
CustomLog /var/www/logs/client1/www-access.log combined
php_admin_value error_log "/var/www/logs/client1/www-error.php.log"
<Directory /var/www/html/client1/www>
Options None
AllowOverride None
Order Deny,Allow
Allow from All
</Directory>
<IfModule mpm_itk_module>
AssignUserId www-client1 www-client1
</IfModule>
php_admin_value log_errors 1
php_admin_value open_basedir "/var/www/html/client1"
php_admin_value upload_tmp_dir "/var/www/html/client1/_php/upload_tmp"
php_admin_value session.save_path "/var/www/html/client1/_php/session"
php_admin_value soap.wsdl_cache_dir "/var/www/html/client1/_php/soap_cache"
SSLEngine On
SSLCertificateFile /var/www/certs/client1/www.crt
SSLCertificateKeyFile /var/www/certs/client/www.key
</VirtualHost>
I'm running Apache 2.4.41,PHP 7.4.3 on Ubuntu 20.04 and there are no errors being outputted to any of my log files.
Any ideas/suggestions on this and further enhancements would be very much appreciated.

After a lot of Googling I have found a solution.
I also needed to ensure that php-fpm was installed and adding the following lines of configuration to the Apache VHost pointing to a unique PHP FPM socket per user fixed my issue.
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php-fpm-client1.sock|fcgi://localhost"
</FilesMatch>
My PHP FPM configuration file looks like:
vi /etc/php/X/fpm/pool.d/client1.conf
[client1]
user = www-client1
group = www-client1
listen = /run/php/php-fpm-client1.sock
listen.owner = www-client1
listen.group = www-client1
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[log_errors] = 1
php_admin_value[error_log] = "/var/www/logs/client1/php-error.log"
php_admin_value[open_basedir] = "/var/www/html/client1"
php_admin_value[session.save_path] = "/var/www/html/client1/_php/session"
bash /etc/init.d/php*-fpm restart
I also found that all php_admin_value values defined in the VHost needed to be moved to the FPM pool.

Related

php-fpm not creating socket

I'm setting up a WordPress website using Apache and php7.4-fpm.
I'm aware that the most common misconfiguration in this combination is a mismatch between the socket definition in the configuration files of both httpd and php-fpm.
I've created both configurations and restarted both services.
After restarting both services, attempts to load the website fail. The logs indicate that the socket can't be reached. When I check the filesystem, I can see that the socket hasn't been created.
This is the vhost configuration:
<VirtualHost *:80>
DocumentRoot /var/www/mysite.localdev
Servername mysite.localdev
<Directory /var/www/mysite.localdev>
AllowOverride none
FallbackResource /index.php
Require all granted
Options Indexes FollowSymLinks MultiViews
</Directory>
#ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/var/www/mysite.localdev/$1
ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:/var/run/php/mysite.sock|fcgi://127.0.0.1:9000/var/www/mysite.localdev
DirectoryIndex index.php /index.php
ErrorLog ${APACHE_LOG_DIR}/mysite.localdev.error-log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/mysite.localdev.access-log combined
</VirtualHost>
and this is the pool configuration
[mysite]
user = mantis
group = mantis
listen = /var/run/php/mysite.sock
listen.owner = mantis
listen.group = mantis
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[post_max_size] = 5G
php_admin_value[upload_max_filesize] = 5G
What could be preventing php from creating the socket?

Upload files with Apache & PHP-FPM

I have installed a new Ubuntu 16.04 server and enabled PHP-FPM using this guide. I have also enabled the userdir module (so that I can have virtual sites running from a public_html folder under /home/$user) and mod_ruid2.
One of the things that has to be done according to the first guide is to add these three lines to 000-default.conf:
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000/"
</FilesMatch>
With the tree lines added, my conf-file looks like this:
<VirtualHost *:80>
ServerName jrrtest
RMode stat
ServerAdmin webmaster#localhost
DocumentRoot /home/jrr/public_html
ErrorLog ${APACHE_LOG_DIR}/jrrtest-error.log
CustomLog ${APACHE_LOG_DIR}/jrrtest-access.log combined
<FilesMatch "\.php$">
SetHandler "proxy:fcgi://127.0.0.1:9000/"
</FilesMatch>
</VirtualHost>
PHP is now executing as expected, but when I try to upload files using the examples on this page, it is not working. If i try to upload a file I get this error in the Apache error_log:
PHP Warning: move_uploaded_file(uploads/jorara.png): failed to open stream: Permission denied in /home/jrr/public_html/upload.php on line 38\nPHP message: PHP Warning: move_uploaded_file(): Unable to move '/tmp/phpAJsos1' to 'uploads/jorara.png' in /home/jrr/public_html/upload.php on line 38
If i remove the FilesMatch lines from 000-default.conf the upload functionality is working againg, but php is no longer executing using FastCGI as I want it to.
If I reenable the FilesMatch lines and change the owner on the uploads folder to www-data:www-data I can also get the upload functionality to work.
How can I configure PHP-FPM so that the owner of the php script can upload files to a folder owned by same owner as the script owner?
Regards,
Jørgen
After spending a couple of hours searching, I finally found a solution that seems to be working.
What I ended up doing was this.
Installed a standard Ubuntu with LAMP.
Installed these extra packages:
apt-get install libapache2-mod-fastcgi php7.0-fpm
Enabled these Apache modules:
a2enmod actions fastcgi
Created a couple of directories:
/var/www/testsite/htdocs
/var/www/testsite/phpsessions
/var/www/testsite/logs
Created a new php-fpm pool in the file /etc/php/7.0/fpm/pool.d/testsite.conf:
[testsite]
user = testsite
group = testsite
listen = /run/php/php7.0-fpm.testsite.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[session.save_path] = /var/www/testsite/phpsessions
php_admin_value[session.save_handler] = files
php_admin_value[display_errors] = Off
php_admin_value[log_errors] = On
php_admin_value[error_log] = "/var/www/testsite/logs/php_error.log"
php_admin_value[open_basedir] = "/var/www/testsite/htdocs:/usr/share/php:/tmp:/var/www/testsite/phpsessions"
In my first attempts with listen.owner and listen.group I had them set to testsite. That gave me problems accessing the socket file /run/php/php7.0-fpm.testsite.sock if I did not set listen.mode to 0666. In my (and a lot of other peoples) opinion that is a security risk. Instead I enden up setting listen.owner, listen.group and listen.mode to the above shown values which seems to be the recommend solution.
Created a site definition in the file /etc/apache2/sites-available/testsite.conf with this content:
<IfModule mod_fastcgi.c>
AddHandler php7-fcgi-testsite .php
Action php7-fcgi-testsite /php7-fcgi-testsite
Alias /php7-fcgi-testsite /usr/lib/cgi-bin/php7-fcgi-testsite
FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi-testsite -socket /run/php/php7.0-fpm.testsite.sock -pass-header Authorization
<Directory "/usr/lib/cgi-bin">
Require all granted
</Directory>
</IfModule>
<VirtualHost *:80>
ServerName testsite
ServerAdmin webmaster#localhost
DocumentRoot /var/www/testsite/htdocs
ErrorLog ${APACHE_LOG_DIR}/testsite-error.log
CustomLog ${APACHE_LOG_DIR}/testsite-access.log combined
<Directory /var/www/testsite/htdocs>
Options -Indexes
</Directory>
<IfModule mod_fastcgi.c>
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler php7-fcgi-testsite
</FilesMatch>
</IfModule>
</VirtualHost>
Enabled the new site:
a2ensite testsite
Disabled the default php module in Apache:
a2dismod php7.0
Restartet Apache and PHP-FPM:
systemctl restart php7.0-fpm apache2
The status of php-fpm (including the new pool) can be seen with this command:
systemctl status php7.0-fpm
Created the file info.php in /var/www/testsite/htdocs with this content:
<?php
phpinfo();
?>
Accessing testsite/info.php in a browser now shows that php is running as FastCGI which is what i wanted and files can be uploaded without problems.

Disable PHP eval in Virtualhost per location

I have successfully installed suhosin in my server and I'm blocking the devil PHP eval function on some virtualhosts with this configuration:
<VirtualHost 123.123.123.123:80>
<Directory /var/www/html/www.example.com>
#SUHOSIN
php_admin_value suhosin.executor.disable_eval On
</Directory>
</VirtualHost>
However, I need to enable eval on some specific URL since it is used by the platform on some specific cases. I've tried the following:
<VirtualHost 123.123.123.123:80>
<Directory /var/www/html/www.example.com>
# SUHOSIN
php_admin_value suhosin.executor.disable_eval On
</Directory>
<Location "/some/path">
# Reenable eval for this path
php_admin_value suhosin.executor.disable_eval Off
</Location>
</VirtualHost>
And also with the tag LocationMatch, with no success (it's like if it was not there: no effect at all).
Any ideas how can I have this directive working just for a specific path?
Thanks
I am not using SUHOSIN, I solved with different php.ini files for each website.
Something like:
<VirtualHost 123.123.123.123:80>
[...]
PHPINIDir /path/to/specificinifile
[...]
</VirtualHost>
Hope this helps.

Apache and php-fpm - user isolation

I have set up a default Apache + php-fpm and the setup below works. Is it good enough for running hosting on or is there modules I'm missing?
I'm just trying to learn how it all works together and how to create user separation/isolation - so that files created on a vhost on server is owned by that user and not apache/www (system users). I also want to be able to have several php-fpm pools.
The way I have set it up, kind of works by having one php-fpm pool per user. All files managed by this vhost is owned by the user I have put into the fpm-pool-config. But I would need to create a lot of ports and one /etc/php-fpm.d/test99com.conf per user.
Is the setup below safe? I notice cPanel have user-section in their vhost and I only have it in my php-fpm.
I would also know how to limit the vhost by memory: For instance max 256 MB.
Note that I only intend to host PHP-software (no cgi/perl).
Apache httpd.conf
<VirtualHost *>
DocumentRoot "/home/test99/public_html"
ServerName test99.com
<FilesMatch \.php$>
#SetHandler application/x-httpd-php
SetHandler "proxy:fcgi://127.0.0.1:9001"
</FilesMatch>
<Directory "/home/test99/public_html">
allow from all
Options None
Require all granted
</Directory>
</VirtualHost>
php-fpm.d/test99no.conf
; Start a new pool named 'www'.
; the variable $pool can we used in any directive and will be replaced by the
; pool name ('www' here)
[test99]
user = test99
group = test99
listen = 127.0.0.1:9001
listen.allowed_clients = 127.0.0.1
php_admin_value[error_log] = /var/log/php-fpm/www-error.log

PHP-FPM requires restart to access generated file when visiting webpage

As part of a web-based project I work on, we generate new "sites" which are accessed by passing in a different parameter to $_GET. All of the sites live in /usr/local/sites. None of the sites are owned (either user or group) by the user we use (hwphp, www-data is the default apache user still), but the user is in the group so can read all files in the directories.
I have a python script that generates sites and after running it, half the time when I try and visit it by going to http://localhost/index.php?site=newsite I get File not found: /var/local/sites/newsite/config/config.ini though running PHP CLI it can find the file and hwphp user can read it just fine, just when I go through PHP-FPM/Apache it fails.
Here's my pool configuration:
; Start a new pool named 'www'.
; the variable $pool can be used in any directive and will be replaced by the
; pool name ('www' here)
[submitty]
user = hwphp
group = hwphp
listen = /run/php/php7.0-fpm-submitty.sock
listen.owner = www-data
listen.group = www-data
;listen.mode = 0660
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
and my apache configuration:
<VirtualHost 192.168.56.101:80>
AddDefaultCharset utf-8
ServerAdmin ADMIN#DOMAIN.HERE
ServerName 192.168.56.101
DocumentRoot /usr/local/submitty/site/public
DirectoryIndex index.html index.php index.htm index.cgi
SuexecUserGroup hwphp hwphp
<IfModule mod_fastcgi.c>
AddHandler php7-fcgi .php
Action php7-fcgi /php7-fcgi
Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi
FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi -socket /var/run/php/php7.0-fpm-submitty.sock -pass-header Authorization
<FilesMatch ".+\.ph(p[345]?|t|tml)$">
SetHandler php7-fcgi
</FilesMatch>
<Directory /usr/lib/cgi-bin>
Require all granted
</Directory>
</IfModule>
<Files .*>
Order allow,deny
Deny from all
</Files>
<Files *~>
Order allow,deny
Deny from all
</Files>
<Files #*>
Order allow,deny
Deny from all
</Files>
<Directory />
AllowOverride None
</Directory>
<Directory /usr/local/submitty/site/public>
Require all granted
Order allow,deny
Allow from all
</Directory>
LogLevel error
ErrorLog ${APACHE_LOG_DIR}/submitty.log
CustomLog ${APACHE_LOG_DIR}/submitty.log combined
</VirtualHost>
as soon as I do:
service php7.0-fpm restart
and it works fine and the file is found. Not sure why this might be as it makes no sense (and why a simple restart is what fixes it).
Server is Ubuntu 16.04, using PHP 7 and Apache 2.4, everything from the stock apt-get installs.
The issue ended up being that PHP was doing some caching of the file read which was causing the issues when trying to open the files. Doing a restart of php-fpm flushed the cache and made things just work.

Categories