#IIS Hacks

Server & System Administration Archive · 2007–2013

An independent, non-commercial archive. Not affiliated with, endorsed by or connected to any vendor named in these notes.

Ordered parallel cable runs leaving a patch panel, each following its own separate path

How to Install PHP 5.3 FastCGI on Windows 2008 IIS 7

Archived note. Originally published 14 February 2011 on iishacks.com. It describes installing PHP 5.3 under FastCGI on IIS 7 and 7.5 on Windows Server 2008, and is preserved here as a record. PHP 5.3 and Windows Server 2008 are both long out of support, and the VC9 build designation and the separate PHP Manager download described below no longer match current PHP for Windows packaging. Verify against current vendor documentation before applying any of it to a live system.

The original note

PHP on Windows came a long way in the years before this was written. It used to be a chore to get PHP working properly on IIS. That was no longer the case by 2011.

PHP ISAPI had previously been recommended for IIS when using threaded applications and accelerators such as eAccelerator, xCache and APC. By this point APC included support for FastCGI, using the non-thread-safe build. The earlier note on installing PHP ISAPI on Windows 2008 IIS7 x64 covers PHP 4 through 5.2.x on the ISAPI path.

With PHP 5.3.x the ISAPI DLL was removed for Windows. Using it at all meant compiling it yourself. There was a strong push towards FastCGI on IIS, and with good reason: performance increased dramatically. Since most web applications — blogs, forums, content management systems — do not require a thread-safe install of PHP, FastCGI was the fastest and most stable option available.

PHP 5.3 for Windows was compiled with either VC6 or VC9. VC9 should be used with IIS; VC6 should be used with Apache 1 or 2. The VC9 builds require the Microsoft 2008 C++ runtime. Install the x86 or x64 runtime that matches the version of Windows, even though the PHP install itself is 32-bit.

When installing multiple versions of PHP with PHP Manager, each install can have a different php.ini and its own set of extensions installed and enabled. Within IIS, a different version of PHP can be enabled per site.

1. Install PHP Manager for IIS 7 / 7.5

Download and install PHP Manager. Even though PHP is 32-bit, install the version of PHP Manager that matches the Windows install — x86 or x64.

2. Install PHP 5.3.x for Windows, VC9, non-thread-safe

Either the installer or the zip package can be used. The installer is the better choice for a first install, because it sets the PATH for the PHP install in Windows. For adding a second version, or upgrading, download the zip package and unzip it. When running multiple versions of PHP side by side, name the directories with the PHP version, for example C:\php_5.3.5\.

3. Register the PHP version

In PHP Manager (IIS Manager → Server Name → PHP Manager), click Register New PHP Version and browse to the directory the PHP files were unzipped into. Select php-cgi.exe and click OK.

Once the PHP module is registered, configure php.ini. This can be done in Notepad or from within PHP Manager, under Manage All Settings. For most basic installs the default php.ini will suffice. For a MySQL database, the MySQL or MySQLi extension has to be enabled: IIS Manager → PHP Manager → PHP Extensions → Enable or disable an extension, click php_mysql.dll and/or php_mysqli.dll, and under Actions in the right sidebar click Enable.

4. On Windows x64, allow 32-bit applications in the application pool

On 32-bit Windows, skip this step. On x64, the application pool settings have to allow 32-bit PHP to run: IIS Manager → Application Pools → right-click the website’s application pool (or Default, if none has been set up yet) → Advanced Settings, and set Enable 32-bit applications to TRUE, then click OK.

This spawns the application pool in 32-bit mode. If other modules on the same server need to run in 64-bit mode, separate the website into two application pools, one 32-bit and one 64-bit.

5. Multiple PHP versions

To install several versions of PHP, register each one using PHP Manager. Each individual website can then be set to run a specific version. Remember to modify the php.ini of every version registered.

If CGI errors appear when viewing a page, check that cgi.force_redirect = 0 in php.ini, or that the directive is commented out.

Why FastCGI replaced ISAPI on IIS

The two models differ in where the interpreter runs. An ISAPI extension is a DLL loaded into the IIS worker process. It executes inside the web server’s own address space, on the server’s threads, and it lives and dies with the worker process. A FastCGI handler is a separate long-running process — here php-cgi.exe — that IIS starts, keeps alive across requests and talks to over a defined protocol.

Three consequences follow, and together they are the reason the platform moved.

Isolation. An extension that faults takes the worker process with it, and with it every request that process was serving. A FastCGI process that dies affects the request it was handling; the FastCGI module notices, recycles it and carries on.

Thread safety. An in-process extension is called concurrently on many threads at once, so every part of the interpreter and every loaded extension has to be safe under that. A FastCGI process handles one request at a time, so that entire class of requirement disappears.

Lifecycle control. Because the processes are external, IIS can control how many of them exist, how many requests each serves before being recycled, and how long an idle one survives. That is what made a leaky third-party extension survivable in production rather than a reason to restart the server.

The general IIS documentation is at Microsoft’s IIS documentation home.

Thread-safe and non-thread-safe builds

PHP for Windows has long shipped in two flavours. The thread-safe build compiles in the mechanism that lets multiple interpreter threads coexist in one process. The non-thread-safe build leaves it out.

The choice is not a preference. It follows from the execution model. An in-process, multi-threaded host such as an ISAPI extension requires the thread-safe build. A one-request-per-process model such as FastCGI does not, and the thread-safe build simply costs performance there for a guarantee nothing needs.

The second-order effect is the one that bit people: an extension has to match the build it is loaded into. That is what made accelerators the deciding factor. As long as APC and its contemporaries only worked in a thread-safe build, ISAPI remained the practical route for anyone who wanted an opcode cache, which is precisely the history the original note opens with. Once the accelerator worked under a non-thread-safe FastCGI install, the last argument for ISAPI on IIS was gone.

The VC6 and VC9 distinction

VC6 and VC9 refer to the Visual C++ toolchain a binary was built with, and therefore to the C runtime it links against. VC6 builds were the historical default and matched the Apache binaries distributed for Windows at the time. VC9 builds were compiled with the Visual C++ 2008 toolchain and matched the runtime IIS itself used, which is why they were the correct choice on IIS — and why the corresponding redistributable had to be installed first.

Bitness is a separate axis from the toolchain, and mixing the two up was a common source of trouble. The redistributable follows the operating system; the PHP build in this note is 32-bit regardless. Current Windows builds of PHP, and their supported toolchains, are published at windows.php.net, and the platform’s own installation guidance is in the PHP manual’s Windows installation chapter.

Why 32-bit PHP needs a 32-bit application pool

Step 4 is where most installations of this era failed, and the reason is a hard rule of the platform rather than a configuration nicety: a 64-bit process cannot load a 32-bit binary. On x64 Windows, IIS worker processes are 64-bit by default. Handing one a 32-bit php-cgi.exe to run therefore fails.

Enable 32-bit applications makes the worker processes for that pool start in 32-bit mode instead. The setting is per application pool, which is what makes the split suggested in the note workable: 32-bit sites in one pool, anything that needs a 64-bit worker in another, on the same server.

The related IIS notes from this period are collected under Internet Information Server and PHP, including the note on migrating websites from IIS6 to IIS7. Platform notes of the same vintage are under Windows / Server, and the full index of preserved notes is at post archives.