Description, Purpose & Scope

Often with a VPS, dedicated server or elastic services such as AWS, there’s a need or requirement to be able to install and update new plugins and themes. WordPress requires write privileges to the filesystem through the webserver (Apache httpd / nginx). This requires more than just setting a few permissions on the system, for this we need to change the PHP handler from the stock mod_php (DSO) to something capable of handling these requests. This is where PHP-FPM comes in, it is built into PHP core and alters the way PHP files are handled and processed by the webserver.

What is PHP-FPM? – Features

PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites.

  • Ability to start workers with different uid/gid/chroot/environment and different php.ini (replaces safe_mode)
    • Separate chrooted DocumentRoot per site, protecting sites from one another
    • Independent PHP settings per site; upload limits, memory, etc
  • Adaptive process spawning (NEW!)
  • Basic statistics (ala Apache’s mod_status) (NEW!)
  • Advanced process management with graceful stop/start
  • Stdout & stderr logging
  • Emergency restart in case of accidental opcode cache destruction
  • Accelerated upload support
  • Support for a “slowlog”
  • Enhancements to FastCGI, such as fastcgi_finish_request() – a special function to finish request & flush all data while continuing to do something time-consuming (video converting, stats processing, etc.)

Required Packages & Configuration Files

php70u-fpm
/etc/php-fpm.d
example.com vhost config
/etc/httpd/conf.d/example.com.conf
example.net vhost config
/etc/httpd/conf.d/example.net.conf
example.org vhost config
/etc/httpd/conf.d/example.org.conf

In this setup we’ll assume the following:

  1. The server is running Centos, RHEL or Fedora. This information can be adapted to any system running Apache httpd and PHP-FPM, though filenames and locations may be different the core directives and applications are not.
  2. The server is running php56u or php70u from IUS repo.
  3. The server has a users and groups ‘webcom’, ‘webnet’, ‘weborg’.
  4. The domains are SSL/TLS enabled.
  5. The domains are ‘example.com’, ‘example.net’, ‘example.org’.
  6. Decide whether you want to use TCP or Unix sockets for your configuration (see options below)
  7. Note: Unix socket method inspired by Jeff Hays (aka jphase).


Doing the work

  1. Install the required packages, the assumes you’ve installed php70u from IUS repository.
  2. yum install php70u-fpm


  3. Create your PHP-FPM users on the system with nologin shells
  4. These users will never login to the system and are only used for PHP-FPM processes. Do not assign them passwords and follow the securing sshd document to make sure no one can login except those users approved to.

    sudo useradd -s /sbin/nologin webcom
    sudo useradd -s /sbin/nologin webnet
    sudo useradd -s /sbin/nologin weborg


  5. PHP-FPM site configuration files
  6. Note: Using Unix sockets over TCP sockets is marginally faster and more secure, as it’s not connecting to the network. However, you may need to adjust your operating system settings to allow for more connections if you start getting errors, or switch to the TCP method.

    example.com PHP-FPM configuration | /etc/php-fpm.d/example.com.conf

    »»» example.com Unix socket configuration «««

    touch /var/run/php-fpm/example.com.sock
    chown root:root /var/run/php-fpm/example.com.sock
    chmod 600 /var/run/php-fpm/example.com.sock


    example.net PHP-FPM configuration | /etc/php-fpm.d/example.net.conf

    »»» example.net Unix socket configuration «««

    touch /var/run/php-fpm/example.net.sock
    chown root:root /var/run/php-fpm/example.net.sock
    chmod 600 /var/run/php-fpm/example.net.sock


    example.org PHP-FPM configuration | /etc/php-fpm.d/example.org.conf

    »»» example.org Unix socket configuration «««

    touch /var/run/php-fpm/example.org.sock
    chown root:root /var/run/php-fpm/example.org.sock
    chmod 600 /var/run/php-fpm/example.org.sock


  7. Apache httpd VirtualHost configuration files:
  8. Add these 2 lines within the VirtualHost block of each of your sites’ configurations:
    IMPORTANT NOTES
    TCP Socket Method: $1 at the end expands to the entire request-URI from the original request, minus the leading slash.
    Unix Socket Method: With this approach, the captured request URI ($1) is not passed after the path.

    Site 1
    example.com Apache httpd configuration
    /etc/httpd/conf.d/example.com.conf

    Site 2
    example.net Apache httpd configuration
    /etc/httpd/conf.d/example.net.conf

    Site 3
    example.org Apache httpd configuration
    /etc/httpd/conf.d/example.org.conf

  9. Use chown and chmod on the DocumentRoot’s to set their respective users/groups and set standard filesystem permissions
  10. Set the owner/group of directories and files starting at the DocumentRoot.

    • chown -Rf webcom:webcom /var/www/example.com/main/siteroot
    • chown -Rf weborg:weborg /var/www/example.org/main/siteroot
    • chown -Rf webnet:webnet /var/www/example.net/main/siteroot

    Set directory permissions to 755, set file permissions to 644.

    • find /var/www/example.com/main/siteroot -type d -exec chmod 755 {} \; && find /var/www/example.com/main/siteroot -type f -exec chmod 644 {} \;
    • find /var/www/example.org/main/siteroot -type d -exec chmod 755 {} \; && find /var/www/example.org/main/siteroot -type f -exec chmod 644 {} \;
    • find /var/www/example.net/main/siteroot -type d -exec chmod 755 {} \; && find /var/www/example.net/main/siteroot -type f -exec chmod 644 {} \;

SELinux Considerations

Problem:

PHP-FPM cannot start because it cannot bind to the defined ports:

C6: service php-fpm restart
C7: ssystemctl restart php-fpm.service

Solution:

Allow httpd connections to certain non-standard ports:

  • semanage port -a -t http_port_t -p tcp 9000
  • semanage port -a -t http_port_t -p tcp 9001
  • semanage port -a -t http_port_t -p tcp 9002
Other SELinux Considerations or Connection Problems

503 errors or connection refused errors in the error log:
semanage fcontext -a -t httpd_sys_rw_content_t '/var/www/example.com/main/siteroot'
restorecon -v '/var/www/example.com/main/siteroot'
or, to allow globally, instead of per site/directory:
setsebool -P httpd_unified 1

Other problems:
setsebool -P httpd_can_network_connect on

chcon -R -h -t httpd_sys_content_t /var/www/example.com/main/siteroot
chcon -R -h -t httpd_sys_script_rw_t /var/www/example.com/main/siteroot

Interesting SELinux Booleans

getsebool -a | grep user
getsebool -a | grep http

C6: service php-fpm restart
C7: ssystemctl restart php-fpm.service


Appendix


Instructions

 

IUS PHP 5.6 Package List


php56u
php56u-bcmath
php56u-cli
php56u-common
php56u-devel
php56u-fpm
php56u-gd
php56u-imap
php56u-intl
php56u-ldap
php56u-mbstring
php56u-mcrypt
php56u-mysqlnd
php56u-pdo
php56u-pear
php56u-pecl-apcu
php56u-pecl-geoip
php56u-pecl-imagick
php56u-pecl-jsonc
php56u-pecl-jsonc-devel
php56u-process
php56u-tidy
php56u-xml
php56u-xmlrpc
 
 


Instructions

 

IUS PHP 7.0 Package List


php70u-bcmath
php70u-cli
php70u-common
php70u-devel
php70u-embedded
php70u-fpm-httpd
php70u-fpm-nginx
php70u-fpm
php70u-gd
php70u-imap
php70u-intl
php70u-json
php70u-mbstring
php70u-mcrypt
php70u-mysqlnd
php70u-opcache
php70u-pecl-apcu
php70u-pecl-apcu-panel.noarch
php70u-pecl-xdebug
php70u-pdo
php70u-pear
php70u-process
php70u-pspell
php70u-recode
php70u-snmp
php70u-soap
php70u-tidy
php70u-xmlrpc
php70u-xml
 
 

Last Modified: 1 Dec, 2017 at 13:33:20