Apache and php-fpm - user isolation - php

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

Related

Can't run PHP-FPM using apache MPM

for very long time I'm trying to set up apache server on ubuntu with multiple hosts and somehow it just doesn't want to work for me.
My general goal: Hosting multiple websites with apache and using chrooted php and ftp. For ftp it's not a problem using vsftpd but PHP seems to be a problem.
In the current configuration without chroot php can access to files using scandir and thus access to other virtual hosts.
If there's a better way to solve this problem you can also make a suggestion! Trying for 2 or 3 days now to get this working.
I've set up a virtual machine for testing purpose and want to show my current configuration and hope to find some help.
I've added two hosts on my /etc/hosts: web1 and web2, thus I'm using http://web1 and http://web2 for testing.
apache config of my vhost web1:
<VirtualHost *:80>
ServerAdmin admin#yadbo.com
ServerName web1
DocumentRoot /var/www/web1/html
ErrorLog /var/www/web1/logs/error.log
CustomLog /var/www/web1/logs/logaccess.log combined
AssignUserId web1 www-data
DirectoryIndex index.php
<Directory "/usr/lib/cgi-bin">
Require all granted
</Directory>
AddHandler php7-fcgi-web1 .php
Action php7-fcgi-web1 /php7-fcgi-web1
Alias /php7-fcgi-web1 /usr/lib/cgi-bin/php7-fcgi-web1
FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi-web1 -socket /run/php/php7.4-fpm.web1.sock -pass-header Authorization
<FilesMatch \.php$ >
SetHandler php7-fcgi-web1
</FilesMatch>
</VirtualHost>
I've added also new pool for my user web1 in /etc/php/7.4/fpm/pool.d/web1:
[web1]
listen = /run/php/php7.4-fpm.web1.sock
access.log = /var/www/web1/logs/$pool.access.log
prefix = /var/www/web1/
chroot = $prefix
chdir = /
user = web1
group = www-data
listen.owner = web1
listen.group = www-data
listen.mode = 0660
php_value[session.save_path] = /sessions
pm=dynamic
pm.max_children=5
pm.start_servers=2
pm.min_spare_servers=1
pm.max_spare_servers=3
That's pretty much all I got as configuration. I've also tried to add some softlinks in /var/www/html to make the sockets accessable and adapted the links but it still doesn't work...
In current configuration which I've used I get 404 for every php file and thus it claims it can't find e.g. /index.php 404.
I know I'm missing something due to chroot. But I'm new to this topic and have really difficulties at setting up this construction.
I really hope I can find help here.
Thank you in advance for your time!
FPM runs its own process, not as part of the apache process (mod_fcgid).

Site only opens in localhost

I'm setting up a windows server 2019 with apache 2.4 and PHP 5.6.
I was able to load the phpinfo in the browser with localhost.
I am trying to get the sites to open up in an htdocs folder on another drive (D:) using an alias that, according to our networking team is quoting, "DNS is set up correctly pointing to newprod.company.name.com", with "newprod" being the acutal alias.
In my httpd.conf file, I have the following settings:
Define SRVROOT "c:/Apache24"
ServerRoot "${SRVROOT}"
Listen 80
The above is pointing at the C: drive where Apache24 is located.
LoadModule rewrite_module modules/mod_rewrite.so
I have the above module uncommented. There are several other modules that have been uncommented, but the one above seems to be one of the main modules that, according to various Apache setup tutorials, is the main module.
ServerAdmin my.company#company.com
ServerName newprod.company.name.com:80
ServerName Localhost:80
According to various tutorials, the above seems to be accurate. I have compared my previous httpd.conf files, and they work using very similar configurations, including Localhost:80.
DocumentRoot "D:/htdocs"
<Directory "D:/htdocs">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
The main part to focus on above the D:/htdocs. This is where I figured the sites should be opening from, as well as opening using the alias.
<IfModule dir_module>
DirectoryIndex index.php index.html
</IfModule>
The above is typical for an Apache setup, per various tutorials.
<VirtualHost newprod.company.name.com:80>
ServerName newprod.company.name.com
Redirect / http://newprod.company.name.com/
</VirtualHost>
I use the above on another server (with a different alias) without any issues.
PHPIniDir "C:/PHP5.6"
AddHandler application/x-httpd-php .php
LoadModule php5_module "C:/PHP5.6/php5apache2_4.dll"
Then finally, the above is to ensure Apache will read PHP.
I have two other servers that are loading the sites with their own aliases with no problem. I literally went line for line trying to ensure everything matches. The only things that don't match is the PHP configurations at the bottom of the file. My other two servers are using PHP 7.4, while the problem server is using PHP 5.6.
Why aren't my sites loading using the alias I provided?
If you're using
ServerName newprod.company.name.com:80
ServerName Localhost:80
in main httpd.conf (or main apache config file), get rid of
ServerName Localhost:80
The vhost configuration
<VirtualHost newprod.company.name.com:80>
ServerName newprod.company.name.com
Redirect / http://newprod.company.name.com/
</VirtualHost>
is probably going to create a redirect loop: if that's all the configuration inside the virtualhost, get rid of it: it's useless.
Is port 80 on your apache server reachable from another pc? Are you able to telnet from a pc in the same lan on po 80 of apache server? Have you checked if the firewall is dropping the first syn packet?

Apache unique Vhost user, PHP sessions not working

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.

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.

VirtualHost is not working under Apache 2.4.6 on CentOS 7

I'm trying to setup some VH in Apache 2.4.6 on CentOS 7 but without success since it's not working. This is what I've tried til now:
Since in /etc/httpd/conf/httpd.conf is this line Include conf.modules.d/*.conf then I create a file under /etc/httpd/conf.d/vhost.conf and place this inside it:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName webserver
ServerAlias localhost devserver development
DocumentRoot /var/www/html
</VirtualHost>
Reload/Restart Apache service (tried both):
service httpd reload|restart
At Windows side edit the file C:\Windows\system32\drivers\etc\hosts and add this line:
192.168.3.131 webserver localhost devserver development # this is the IP of Apache Server
Open the browser and tried: http://webserver, http://devserver and both goes to default Apache page so VH is not working.
Place a file under /var/www/html/index.php with this lines <?php phpinfo(); ?> just to know which modules is Apache loading, this is the result:
core mod_so http_core mod_access_compat mod_actions mod_alias mod_allowmethods mod_auth_basic mod_auth_digest
mod_authn_anon mod_authn_core mod_authn_dbd mod_authn_dbm mod_authn_file mod_authn_socache mod_authz_core
mod_authz_dbd mod_authz_dbm mod_authz_groupfile mod_authz_host mod_authz_owner mod_authz_user mod_autoindex
mod_cache mod_cache_disk mod_data mod_dbd mod_deflate mod_dir mod_dumpio mod_echo mod_env mod_expires mod_ext_filter
mod_filter mod_headers mod_include mod_info mod_log_config mod_logio mod_mime_magic mod_mime mod_negotiation
mod_remoteip mod_reqtimeout mod_rewrite mod_setenvif mod_slotmem_plain mod_slotmem_shm mod_socache_dbm
mod_socache_memcache mod_socache_shmcb mod_status mod_substitute mod_suexec mod_unique_id mod_unixd mod_userdir
mod_version mod_vhost_alias mod_dav mod_dav_fs mod_dav_lock mod_lua prefork mod_proxy mod_lbmethod_bybusyness
mod_lbmethod_byrequests mod_lbmethod_bytraffic mod_lbmethod_heartbeat mod_proxy_ajp mod_proxy_balancer mod_proxy_connect
mod_proxy_express mod_proxy_fcgi mod_proxy_fdpass mod_proxy_ftp mod_proxy_http mod_proxy_scgi mod_systemd mod_cgi mod_php5
And apparently mod_vhost is loaded but is not working, did I miss something? Any help or advice around this? Maybe I forgot something but I read Apache docs and doesn't found something helpful
Update: test1
I made some changes to VH definition and now this is what I have:
<VirtualHost *:80>
DocumentRoot /var/www/html
ServerName webserver
#ServerAlias localhost devserver development
<Directory "/var/www/html">
Options FollowSymLinks Includes ExecCGI
AllowOverride All
Allow from all
#Require local
#Require 192.168.3.0/16
#Require 192.168.1.0/16
</Directory>
</VirtualHost>
But I'm getting a 403 Forbidden
Forbidden
You don't have permission to access /index.php on this server.
What is failing here?
To elaborate on jap1968's post, CentOS 7 comes with SELinux's pain in the butt level set to enforcing. This causes all kinds of confusion when perfectly normal service configuration silently fail (Apache).
To disable SELinux you'll need to:
0) [optional] Crack open a shell and become root... or enjoy a shiny new, super fun, configuring sudo to let you do "root stuffs" project. Probably.
su -l
1) Get the current status of SELinux. Run sestatus:
sestatus
2) If SELinux is causing hair loss and premature aging you'll get something like this:
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: enforcing
Mode from config file: enforcing
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
3) Edit the /etc/selinux/config file. Change SELINUX=enforcing to SELINUX=permissive. Doing this will set you up for endless joy next time you reboot. You'll end up with something like this:
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUX=enforcing
# ===> VOODOO HERE <===
SELINUX=permissive
# ===> END VOODOO <===
#
# SELINUXTYPE= can take one of three two values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
4) Disable SELinux. You can reboot at this point but it's easier to tell SELinux to take time off from tormenting you. Run setenforce to reset SELinux's enforcement level to match the /etc/selinux/config file:
setenforce 0
5) Check sestatus again:
sestatus
If everything went as expected sestatus will return something like this:
SELinux status: enabled
SELinuxfs mount: /sys/fs/selinux
SELinux root directory: /etc/selinux
Loaded policy name: targeted
Current mode: permissive
Mode from config file: permissive
Policy MLS status: enabled
Policy deny_unknown status: allowed
Max kernel policy version: 28
6) Restart Apache. If your vhost's domain name is resolving to the server you're working on you'll see your shiny new virtual host:
# Restart apache:
systemctl restart httpd.service
# Be lazy by checking your virtual host from the command line:
curl www.example.com/new-file-that-only-exists-in-your-new-vhost.txt
6.5) Stop reading here. Or don't. I'm a message board post, not your Mom.
Everything below is beyond the scope of the original question and only included because you really should be running with SELinux enabled.
7) Work towards re-enabling selinux. Start by watching the selinux logs to see some awesome alphabet soup:
tail -f /var/log/audit/audit.log
8) Be amazed at the depth of features, crazy number of poorly named utilities, and ugly UX mess that constitutes SELinux. You should probably put on your big boy pants and drink a whole pot of coffee before you dive in. Here's some Info:
CentoOS HowTo: https://wiki.centos.org/HowTos/SELinux
Project: http://selinuxproject.org/page/Main_Page
A couple of thing that may be causing you problems :-
NameVirtualHost *:80
Is no longer a valid syntax for Apache 2.4.x you should remove it completely.
On the Windows side once you have changed the HOSTS file, you need to reload the DNS Client service, so either reboot or better still, launch a command window using "Run as Administrator" and do this :-
net stop dnscache
net start dnscache
Lastly, within your virtual hosts definition, it will help to tell apache from where it is allowed to accept connections to this Virtual Host like so :-
<VirtualHost *:80>
ServerName webserver
ServerAlias localhost devserver development
DocumentRoot /var/www/html
<Directory "/var/www/html">
AllowOverride All
Require local
Require ip 192.168.3
</Directory>
</VirtualHost>
This will allow access from the machine running apache Require local and from any ip address on the local network Require ip 192.168.3
Also I am not sure where Apache on unix puts its default document root but it might be an idea to differentiate your 3 domain names to different directories like so
<VirtualHost *:80>
ServerName localhost
ServerAlias localhost
DocumentRoot /var/www/html
<Directory "/var/www/html">
AllowOverride All
Require local
Require ip 192.168.3
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName webserver
ServerAlias webserver
DocumentRoot /var/www/html/webserver
<Directory "/var/www/html/webserver">
AllowOverride All
Require local
Require ip 192.168.3
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName development
ServerAlias development
DocumentRoot /var/www/html/development
<Directory "/var/www/html/development">
AllowOverride All
Require local
Require ip 192.168.3
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName devserver
ServerAlias devserver
DocumentRoot /var/www/html/devserver
<Directory "/var/www/html/devserver">
AllowOverride All
Require local
Require ip 192.168.3
</Directory>
</VirtualHost>
Then put a simple html file in each directory saying 'Hello from Servername' and change servername in each file so you know you have got to the correct server.
RE: Update test1.php
Allow from all
Is not valid Apache 2.4 syntax either, unless you have loaded LoadModule access_compat_module modules/mod_access_compat.so
Even then it should be
Order Allow,Deny
Allow from all
So USE Apache 2.4 syntax
Require all granted
If you want to take the lazy route and allow access from the universe.
Be careful also with SELinux. The default configuration will prevent your virtual hosts directories from being accessed by httpd. You will need to set the appropriate context:
# chcon -R -u system_u -r object_r -t httpd_sys_content_t <DocumentRoot>
Another option is just to disable SELinux.

Categories