Per-site PHP configuration with IIS FastCGI

There have been a few questions on IIS.NET PHP forum regarding enabling per-site PHP configuration. This is a common requirement when running PHP applications in shared hosting environment, because each PHP application may require a different set of PHP settings. Shared hosting providers often want to provide their customers with an option of controlling PHP configuration if necessary.

Until recently, it was thought that per-site PHP configuration was only possible when running PHP on Apache in *nix based OS. However, with FastCGI module it is possible to enable this for PHP applications hosted on IIS 6.0 and IIS 7.0.

The development team at GoDaddy.com has researched and validated several options for enabling per-site PHP configuration on Windows. Based on their findings, we have updated the PHP shared hosting guide with instructions on how to allow per-site php.ini files when running PHP via FastCGI on IIS 7.0. In this post I will explain how to accomplish the same on IIS 6.0 by using FastCGI extension.

Assume we have two web sites in IIS 6.0 – website1.com and website2.com. We want each web site to use its own version of php.ini file. Let’s assume that php.ini for website1.com is located in C:\Inetpub\website1.com folder and php.ini for website2.com is located in C:\Inetpub\website2.com folder.

First step is to create script mappings and FastCgi configuration sections for each web site. For that you can use the helper script fcgiconfig.js located in %WINDIR%\system32\inetsrv\ folder. Execute the following commands to create PHP script mappings for website1.com and website2.com. Make sure you put the correct path to PHP executable instead of <php_path> and correct site ID instead of <site_id>.

cscript fcgiconfig.js -add -section:"PHP website1.com" -extension:php -path:<php_path> -site:<site_id>

cscript fcgiconfig.js -add -section:"PHP website2.com" -extension:php -path:<php_path> -site:<site_id>

After executing these commands open the fcgiext.ini file located in %WINDIR%\system32\inetsrv. It should contain the following sections:

[Types]
php:169297538=PHP website1.com ; The actual site id will be different for your site
php:273357939=PHP website2.com ; The actual site id will be different for your site

[PHP website1.com]
ExePath=C:\php523nts\php-cgi.exe

[PHP website2.com]
ExePath=C:\php523nts\php-cgi.exe

Now [PHP website1.com] and [PHP website2.com] can be used to specify some site specific FastCGI configuration settings. We are going to use these sections to specify the path to php.ini file for each of the web sites.

When PHP process starts it determines the location of configuration php.ini file by using various settings. The PHP documentation provides detailed description of the PHP start up process. Note that one of the places where PHP process searches for php.ini location is the PHPRC environment variable. If PHP process finds a php.ini file in the path specified in this environment variable then it will use it, otherwise it will revert to default location of php.ini. We will configure FastCGI to set this environment variable to point to site specific php.ini file:

cscript fcgiconfig.js -set -section:"PHP website1.com" -EnvironmentVars:PHPRC:C:\Inetpub\website1.com

cscript fcgiconfig.js -set -section:"PHP website2.com" -EnvironmentVars:PHPRC:C:\Inetpub\website1.com

Now, if you look into fcgiext.ini file, you will see the configuration sections updated:

[PHP website1.com]
ExePath=C:\php523nts\php-cgi.exe
EnvironmentVars=PHPRC:C:\Inetpub\website1.com 

[PHP website2.com]
ExePath=C:\php523nts\php-cgi.exe
EnvironmentVars=PHPRC:C:\Inetpub\website2.com

After completing these steps, you can easily verify that PHP loads its configuration from site specific location:

  1. Copy php.ini into C:\Inetpub\website1.com
  2. Create a phpinfo.php file in C:\Inetpub\website1.com
  3. Place this code inside of phpinfo.php: <?php phpinfo(); ?>
  4. Open web browser and make a request to http://website1.com/phpinfo.php

The output of phpinfo.php file will show the location from where php.ini file was loaded:

PerSitePHP

91,046 views

ruslany on July 12th 2008 in FastCGI, PHP

PoorFairAverageGoodExcellent (5 votes, average: 4.40 out of 5)

17 Responses to “Per-site PHP configuration with IIS FastCGI”

  1. Gravatar ImageAmit Shah responded on 16 Jul 2008 at 5:52 am #

    How could we apply rewrite rule on IIS?

    For more specific I want to apply rewrite rule for zend framework using IIS.

  2. Gravatar ImagePablo Weyne responded on 16 Jul 2008 at 6:39 am #

    The security of the server cannot be affected?

  3. Gravatar Imageruslany responded on 16 Jul 2008 at 10:10 am #

    Amit,

    It depends on what version of IIS you are using. If you work with IIS 6.0 then you can use either ISAPI_Rewrite or IONICS Rewrite Filter .

    If you work with IIS 7.0 then you can use the Microsoft URL rewrite module .

  4. Gravatar Imageruslany responded on 16 Jul 2008 at 10:18 am #

    Pablo,

    As usual, in shared hosting environment you would need to ensure that account that is used to run php-cgi.exe has minimal set of privileges. It is recommended that you turn on fastCGI impersonation for PHP. That way php-cgi processes for each web site will be running in a security context of impersonated user for that site. This article explains how to configure fastcgi on IIS 6.0 and turn on impersonation.

  5. Gravatar ImageAmit Shah responded on 16 Jul 2008 at 10:19 pm #

    Hi Ruslany,

    Thanks for reply. Im using IIS 5.1. I have installed ISAPI_Rewrite on my system. Now rewrite rule is working fine. but I have rewrite rule problem with zend framework. Is there any other settings I have to apply?

    Im using following rule for zend framework.
    #RewriteRule ^/amit/(?!index\.php|(?:\.(?:js|ico|gif|jpg|png|css))).*$ /amit/index.php

    My local URL is http://localhost:8081/amit/

  6. Gravatar ImagePablo Weyne responded on 17 Jul 2008 at 11:16 am #

    Thank You! Very good!

  7. Gravatar Imageruslany responded on 17 Jul 2008 at 11:55 am #

    Amit,

    The only thing I can think of is that it may be possible that Zend Framework relies on the REQUEST_URI server variable to contain the original un-rewritten URL. This server variable is not available on IIS 5.1. ISAPI_Rewrite sets another server variable “HTTP_X_REWRITE_URL” that contains the original URL.

    Typically, if PHP application relies on REQUEST_URI, then it is fairly easy to fix it for IIS with ISAPI_Rewrite by adding this code:

    if (isset($_SERVER[ 'HTTP_X_REWRITE_URL' ]))
    $_SERVER[ 'REQUEST_URI' ] = $_SERVER[ 'HTTP_X_REWRITE_URL' ];

  8. Gravatar Images.r. responded on 18 Aug 2008 at 5:27 pm #

    actually %WINDIR%\system32\inetpub\ is not right path
    Should be %WINDIR%\system32\inetsrv\
    I didn’t find inetpub folder in the system32 dir

  9. Gravatar Imageruslany responded on 18 Aug 2008 at 7:05 pm #

    s.r., you are correct. That was a typo – the correct path is %WINDIR%\system32\inetsrv\. Thanks for pointing that out – I’ve fixed the text now.

  10. Gravatar Imageshee responded on 08 Mar 2009 at 2:12 pm #

    Thanks for sharing.

  11. Gravatar ImageKimio Tanaka responded on 12 Mar 2009 at 4:16 am #

    Thank you for the other day.

    At last, I succeeded in Per-site PHP configuration with IIS7 FastCGI
    using GUI.

    http://iis.museum-in-cloud.com/wordpress/index.php/archives/87

  12. Gravatar ImageRuslanY Blog responded on 11 Jul 2009 at 12:23 am #

    Per-site PHP configuration with PHP 5.3 and IIS…

    About a year ago I wrote an article about how to enable per-site PHP configuration on IIS with FastCGI. The instructions in that article required some non-trivial manipulations of IIS and FastCGI configuration settings. At that time it was one of the p…

  13. Gravatar ImageAbdallah M. Gazal responded on 22 Sep 2009 at 2:35 am #

    Hi,

    very nice article but with me i had to modify the fcgiext.ini manually (something wrong with the script) anyway my problem is, no matter what i do it always sees the first TYPE only, and cannot see the rest, i tried all types of syntax and yet always see the 1st entry, any idea why? Here is my code

    [Types]
    php:204766269=PHP STI-Travel;
    php:1341913653=PHP SakkaraPayment;
    php:628365814=PHP SakkaraToursIndia;

    [PHP STI-Travel]
    ExePath=C:\program files\PHP\php-cgi.exe
    EnvironmentVars=PHPRC:C:\Inetpub\wwwroot\STI-Travel.com\httpdocs

    [PHP SakkaraPayment]
    ExePath=C:\program files\PHP\php-cgi.exe
    EnvironmentVars=PHPRC:C:\Inetpub\wwwroot\Sakkarapayment.com\httpdocs

    [PHP SakkaraToursIndia]
    ExePath=C:\program files\PHP\php-cgi.exe
    EnvironmentVars=PHPRC:C:\Inetpub\wwwroot\SakkaraToursIndia.com\httpdocs

  14. Gravatar Imageruslany responded on 30 Sep 2009 at 3:29 pm #

    @Abdallah: Turned out that the problem is caused by semicolons at the end of the types declarations. If you remove those it should work.

    This will be fixed in the RTW release of the FastCGI Extension 1.5.

  15. Gravatar Imageigor responded on 23 Feb 2010 at 12:57 pm #

    Hi,

    Thanks for the post. However I came to this page accidentally regarding another problem. As you said earlier in the comment:

    As usual, in shared hosting environment you would need to ensure that account that is used to run php-cgi.exe has minimal set of privileges. It is recommended that you turn on fastCGI impersonation for PHP. That way php-cgi processes for each web site will be running in a security context of impersonated user for that site.

    I have w2k3 se sp2 x32, FastCGI, PHP 5.2.12 (fastcgi.impersonate = 1). I have a web site with identity, let’s say, webUser. The application pool for this web sites runs under, let’s say, appPoolUser (part of IIS_WPG group). Web site works fine, but the one thing I can’t understand is the following:
    1. Worker process (w2wp.exe) starts under appPoolUser as expected.
    2. php-cgi.exe start under the same appPoolUser identity (as per TaskManager).

    Why php-cgi.exe does not run under webUser? or am I missing something?

  16. Gravatar Imageruslany responded on 25 Mar 2010 at 5:01 pm #

    @igor: The php-cgi.exe will run under the appPoolUser identity – this is expected. But it will impersonate the web site user when performing any file system operations. This way for example you can have the same PHP process pool handling requests from multiple web sites and as long as the sites use different anonymous identities, the PHP scripts for those sites will not be able to read each other files because PHP will impersonate the site’s user when reading or writing files.

  17. Gravatar ImageLaiQue responded on 19 Feb 2012 at 12:32 pm #

    Great Topic, Thanks for sharing Ruslany.

    I’ve a question about security and it is not related to this topic.
    When a php shell like C99 runs on windows, it can traversal from one directory to another directory or even one partition to another partition. How can we prevent it ?

Trackback URI | Comments RSS

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

XML Markup: If You want to add XML code to the comment please XML encode it first, otherwise the code will not show up.

Recently Published Articles