How to select PHP version 5 and 7 per virtualhost in Apache 2.4 on Debian?

53,570

Solution 1

Let's start from beginning. I assume that you would prefer to use php-fpm instead of Apache module.

First install apache:

sudo apt-get update
sudo apt-get install apache2

Next install multiple PHP:

Debian 9:
Install PHP 7:

sudo apt-get install php7.0-cli php7.0-fpm php-pear libapache2-mod-fastcgi

Configure repositories:

sudo apt-get install apt-transport-https
sudo curl https://packages.sury.org/php/apt.gpg | apt-key add -
sudo echo 'deb https://packages.sury.org/php/ stretch main' > /etc/apt/sources.list.d/deb.sury.org.list
sudo apt-get update

Install PHP 5:

sudo apt-get install php5.6-cli php5.6-fpm

Debian 8:
Install PHP 5:

sudo apt-get install php5 php5-fpm php-pear libapache2-mod-fastcgi

Configure repositories:
Edit /etc/apt/sources.list and add the following lines to the end of file:

deb http://packages.dotdeb.org jessie all
deb-src http://packages.dotdeb.org jessie all

Install GPG key:

wget https://www.dotdeb.org/dotdeb.gpg
sudo apt-key add dotdeb.gpg
sudo apt-get update

Install PHP 7:

sudo apt-get install php7.0 php7.0-fpm

Next switch from prefork and enable necessary modules:
For Debian 8:

a2dismod php5 mpm_prefork

For Debian 9:

a2dismod php7 mpm_prefork

Next for both:

a2enmod actions fastcgi alias proxy_fcgi mpm_worker
systemctl restart apache2

Change content of /etc/apache2/mods-enabled/fastcgi.conf to the following one:

<IfModule !mod_fastcgi.c>
    AddHandler fcgid-script fcg fcgi fpl
</IfModule>
<IfModule mod_fastcgi.c>
    <Directory /usr/lib/cgi-bin>
        Require all granted
    </Directory>
</IfModule>

Now create document root folders for websites:

mkdir -p /var/www/example.com/public_html
mkdir -p /var/www/test.com/public_html

Add sys users for these websites:

sudo useradd example --home-dir /var/www/example.com
sudo useradd test --home-dir /var/www/test.com

Configure ownership:

sudo chown -R example.example /var/www/example.com
sudo chown -R test.test /var/www/test.com

For example website example.com will use PHP 5 and website test.com will use PHP 7.

Create configuration files for websites:
Website on PHP 5:

touch /etc/apache2/sites-available/example.com.conf
ln -s /etc/apache2/sites-available/example.com.conf /etc/apache2/sites-enabled/example.com.conf
cat /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>

        ServerAdmin webmaster@localhost
        ServerName example.com
        ServerAlias www.example.com
        DocumentRoot /var/www/example.com/public_html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_fastcgi.c>
            AddType application/x-httpd-fastphp5 .php
            Action application/x-httpd-fastphp5 /php5-fcgi
            Alias /php5-fcgi /usr/lib/cgi-bin/php5-fcgi-example.com
            FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi-example.com -socket /var/run/php5-fpm-example.com.sock -pass-header Authorization
        </IfModule>

</VirtualHost>

Website on PHP 7:

touch /etc/apache2/sites-available/test.com.conf
ln -s /etc/apache2/sites-available/test.com.conf /etc/apache2/sites-enabled/test.com.conf
cat /etc/apache2/sites-available/test.com.conf
<VirtualHost *:80>

        ServerAdmin webmaster@localhost
        ServerName test.com
        ServerAlias www.test.com
        DocumentRoot /var/www/test.com/public_html
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <IfModule mod_fastcgi.c>
                AddHandler php7-fcgi .php
                Action php7-fcgi /php7-fcgi virtual
                Alias /php7-fcgi /usr/lib/cgi-bin/php7-fcgi-test.com
                FastCgiExternalServer /usr/lib/cgi-bin/php7-fcgi-test.com -socket /var/run/php/php7.0-fpm-test.com.sock -pass-header Authorization
        </IfModule>

</VirtualHost>

Create pool configs (I used the following):
Website on PHP 5:

cat /etc/php5/fpm/pool.d/example.com.conf
[example.com]
user = example
group = example
listen = /var/run/php5-fpm-example.com.sock
listen.owner = www-data
listen.group = www-data
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /

Website on PHP 7:

cat /etc/php/7.0/fpm/pool.d/test.com.conf
[test.com]
user = test
group = test
listen = /var/run/php/php7.0-fpm-test.com.sock
listen.owner = www-data
listen.group = www-data
php_admin_value[disable_functions] = exec,passthru,shell_exec,system
php_admin_flag[allow_url_fopen] = off
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /

Restart apache and php-fpm services:

sudo systemctl restart apache2 php5-fpm php7.0-fpm

Enjoy!

Solution 2

The answer by @elvis-plesky is really detailled. But Apache suggests the usage of mod_proxy_fcgi:

With the release of apache httpd 2.4 upon an unsuspecting populace, we have gained some very neat functionality regarding apache and php: the ability to run PHP as a fastCGI process server, and address that fastCGI server directly from within apache, via a dedicated proxy module (mod_proxy_fcgi.)

Here are the steps to setup two vhosts with different PHP versions for Debian 10 using Apache's mod_proxy_fcgi and php-fpm.

Configure repositories:

sudo apt-get install apt-transport-https
sudo curl https://packages.sury.org/php/apt.gpg | apt-key add -
sudo echo 'deb https://packages.sury.org/php/ stretch main' > /etc/apt/sources.list.d/deb.sury.org.list
sudo apt-get update

Install needed PHP versions:

sudo apt-get install php5.6-cli php5.6-fpm php7.3-cli php7.3-fpm

Configure php5.6-fpm in /etc/apache2/conf-available/php5.6-fpm.conf:

<IfModule !mod_php5.c>
<IfModule proxy_fcgi_module>
    # Enable http authorization headers
    <IfModule setenvif_module>
        SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
    </IfModule>

    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://php56.localhost"
    </FilesMatch>
    # Deny access to files without filename (e.g. '.php')
    <FilesMatch "^\.ph(ar|p|ps|tml)$">
        Require all denied
    </FilesMatch>
</IfModule>
</IfModule>

Configure php7.3-fpm in /etc/apache2/conf-available/php7.3-fpm.conf:

<IfModule !mod_php7.c>
<IfModule proxy_fcgi_module>
    # Enable http authorization headers
    <IfModule setenvif_module>
        SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
    </IfModule>

    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://php73.localhost"
    </FilesMatch>
    # Deny access to files without filename (e.g. '.php')
    <FilesMatch "^\.ph(ar|p|ps|tml)$">
        Require all denied
    </FilesMatch>
</IfModule>
</IfModule>

Now add a virtual host that uses PHP 5.6:

<VirtualHost *:80>
    ServerName test-php56.localhost
    DocumentRoot "/var/www/test-php56/"
    # use php 5.6
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php5.6-fpm.sock|fcgi://php56.localhost"
    </FilesMatch>
</VirtualHost>

And a virtual host that uses PHP 7.3:

<VirtualHost *:80>
    ServerName test-php73.localhost
    DocumentRoot "/var/www/test-php73/"
    # use php 7.3
    <FilesMatch ".+\.ph(ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php7.3-fpm.sock|fcgi://php73.localhost"
    </FilesMatch>
</VirtualHost>

Activate the correct Apache module and the configs:

sudo a2enmod proxy_fcgi
sudo a2enconf php5.6-fpm
sudo a2enconf php7.3-fpm
sudo systemctl restart apache2 php5.6-fpm php7.3-fpm

The default configuration of the FPM pools should be correct already.


Important:

This change will break old virtual hosts. You need to reconfigure all your virtual hosts and add the FilesMatch block which your project needs. For example if your project needs php 7.4 then you first need to install the fpm package:

sudo apt-get install php7.4-fpm
sudo a2enconf php7.4-fpm
sudo systemctl restart apache2 php7.4-fpm

Then add this section to your vhost config:

...
# use php 7.4
<FilesMatch ".+\.ph(ar|p|tml)$">
    SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://php74.localhost"
</FilesMatch>

Then restart apache service apache2 restart.

Share:
53,570
Z0q
Author by

Z0q

Updated on November 05, 2021

Comments

  • Z0q
    Z0q over 2 years

    Would it be possible to run PHP 7 and PHP 5 simultaneously in Apache 2.4 on Debian 9? I would like to be able to select the PHP version I wish to use per virtualhost. I believe this would be useful considering that some of my websites still use deprecated PHP features. This allows me to perform upgrades per site. How do I achieve something like this?

    For example

    <VirtualHost *:80>
       ServerAdmin webmaster@localhost
       ServerName mywebsite.com
       DocumentRoot /var/www/mywebsite.com
    
       # UsePHP 7
    </virtualHost>
    

    And

    <VirtualHost *:80>
       ServerAdmin webmaster@localhost
       ServerName mywebsite2.com
       DocumentRoot /var/www/mywebsite2.com
    
       # UsePHP 5
    </virtualHost>
    
  • Z0q
    Z0q almost 7 years
    Thank you very much for the detailed explanation! I will try it out. I have one question. What is the difference between PHP-FPM and regular PHP?
  • Elvis Plesky
    Elvis Plesky almost 7 years
    Check the explanation at serverfault.com/questions/645755/…
  • Elvis Plesky
    Elvis Plesky almost 7 years
    By the way. You can achieve the same with the help of hosting control panel like Plesk. It will create all configuration for you =)
  • Jannes Botis
    Jannes Botis almost 7 years
    @Elvis Plesky, is it necessary to create users "example" and "test"? Can "www-data" be used for both?
  • Elvis Plesky
    Elvis Plesky almost 7 years
    Sure, but using separate users is more secure.
  • Rola
    Rola about 6 years
    Thank you for the detailed explanation I'm trying to use multiple php versions in debian stretch and apache. The problem is that I can't install libapache2-mod-fastcgi with my repos... Which one should I use?
  • Elvis Plesky
    Elvis Plesky about 6 years
    @Rola, strange, it is available in Stretch main repository. packages.debian.org/stretch/libapache2-mod-fcgid
  • Rola
    Rola about 6 years
    @ElvisPlesky the guide uses 'libapache2-mod-fastcgi' and the link points to 'libapache2-mod-fcgid'... Are you telling me it is the same? If it is... After installing and enabling that module do I've to change some step more from this guide? Thank you
  • Riccardo
    Riccardo over 5 years
    Somehow I can't get this to work, I had to edit all the php5 related strings for php5.6 and also my path for pool is a little bit different: /etc/php/5.6/fpm/pool.d/ anyway I'm stuck with all the website running php7.3 probably because I can't manage to setup the repository correctly.
  • Pranav Jituri
    Pranav Jituri over 4 years
    Thanks a lot! This is the best comment. This actually worked for me where I had a botched website which was not running with PHP 7.3. Worked flawlessly!
  • Earlee
    Earlee almost 4 years
    I find this one easier to follow
  • Auspex
    Auspex over 3 years
    atm, I am trying to run a number of sites on PHP 7.2 (working) and one on PHP5.6. The 5.6 site's info.php is showing that it's using PHP7.2! Any hints for tracking down why?
  • naitsirch
    naitsirch over 3 years
    @Auspex Sorry, but this is not enough context. You should provide all relevant configs, which is not possible in a comment ;-)
  • Auspex
    Auspex over 3 years
    If it comes to that I'll need to post my own question, but I was just hoping for some debugging tips. I find it very difficult to determine what config any particular vhost is using. In any case, I think your solution is not complete. I'm finding that a2enconf for both PHP versions only enables ONE (the last one executed at apache startup, I think), and that I need to physically Include "conf-available/php5.6-fpm.conf" for the other site
  • Black
    Black over 2 years
    This change destroyed other virtual hosts. I added a section to your answer .