How to CORRECTLY install PHP 7.4.16 for IIS on Windows

It is easy to fall into old learnings and habits with Windows because it can be difficult to keep up with the latest methods.

If you’ve been around Windows and IIS for a long time, you might still think that IUSR is your best friend in providing anonymous authentication for your websites. This is not the case. You should be using a combination of dedicated site users and Application Pools when using PHP in Windows IIS.

Note: Windows build support on PHP is ending.

First, you need to understand IUSR and the IIS_IUSRS Group.

In short IUSR is a system level account that IIS uses, similar to NETWORKSERVICE or LOCALSERVICE. Any Application Pool created in IIS will use IUSR.

The IIS_IUSRS Group is similar to IUSR, but in group form.

“This built-in group has access to all the necessary file and system resources so that an account, when added to this group, can seamlessly act as an application pool identity.”

Microsoft

Note the last part: seamlessly act as an application pool identity.

References:

https://docs.microsoft.com/en-us/troubleshoot/iis/default-permissions-user-rights

https://docs.microsoft.com/en-us/iis/get-started/planning-for-security/understanding-built-in-user-and-group-accounts-in-iis

IIS_IUSRS, Application Pools, and IIS

This is how I set up IIS on my Windows servers:

Site name/Application Pool name: testsite.local. The App Pool is automatically named using the website’s name (but remains the same if you update the site name).

  • c:\sites
    • Default OS permissions + IIS_IUSRS (with inheritance, all sub-folders have these perms)
  • c:\sites\websitename
  • c:\sites\websitename\writeable-assets (storing site assets outside of Git repo and symlinked)
    • IIS AppPool\testsite.local (modify permissions)
  • c:\sites\websitename\webroot
  • c:\sites\websitename\webroot
    • <symlink-to-writeable-assets> outside of the public site folder
  • c:\sites\websitename\webroot\writeable-folder e.g. Laravel public log files
    • IIS AppPool\testsite.local (modify permissions)

In IIS, the website’s Anonymous Authentication is then set to the site’s Application Pool, i.e. “IIS AppPool\testsite.local”. This isolates the website and for anonymous users, and only allows writable folders by the website. IUSR and the IUSR_GROUP (with a global Modify) is not used.

PHP, FastCGI, and Drivers Installation

Getting back to why you came here. To install PHP you need to install the following:

Note: Web Platform Installer no longer installs PHP (or, it might but unreliably)!

  • IIS (Windows 10 Pro, and above) with CGI module installed (Windows FastCGI is included)
  • An understanding of FastCGI in IIS
  • Visual C++ installation drivers
  • PHP 7.4.16 zip file (Non-Thread Safe, NTS, 64 Bit)
  • The latest ODBC/PDO drivers (if needed for Microsoft SQL)

FastCGI

When used in conjunction with IIS, PHP FastCGI (with settings in php.ini) with IIS will impersonate the Application Pool under which it is utilized, i.e. the website’s Application Pool. The following settings in php.in enable this:

cgi.force_redirect = 0
cgi.fix_pathinfo = 1
fastcgi.impersonate = 1
fastcgi.logging = 1

Install Dependencies and PHP Config

Making folders

  • Create folders with default OS permissions
    • c:\php
    • c:\php-system in your root
  • Copy the unzipped PHP folder to c:\php
    • c:\php\php-7.4.16-nts-Win32-vc15-x64
    • When you add more versions, add the new version folder here
  • Create a sub-folder in c:\php-system of the same name
    • c:\php-system\php-7.4.16-nts-Win32-vc15-x64
    • This is where you will put php log files, temp files, etc.
  • Use Web Platform Installer to install URL reWrite
    • Open WPI in IIS > search “URL rewrite” > install URL Rewrite 2.1
  • Windows Cache Extension 2.0 (x64) for PHP 7.4
    • Not required, but recommended
    • If you use WPI, it will install PHP, as well.
    • Download, run the exe and it will extract files to a folder
    • Copy php_wincache.dll to C:\php\php-7.4.16-nts-Win32-vc15-x64\ext\

Updating php.ini

I usually leave most of the default php.ini intact and add my values to the bottom to avoid scrolling. We’re not setting any performance values, security, etc. This is just to get PHP running.

  • Make a copy of php.ini-production as php.ini (I used production on both local/production for consistency)
  • Open c:\php\php-7.4.16-nts-Win32-vc15-x64\php.ini
  • Add this to the bottom of your file:
[PHPconfig]
;fast.cgi
cgi.force_redirect = 0
cgi.fix_pathinfo = 1
fastcgi.impersonate = 1
fastcgi.logging = 1

; misc. paths
extension_dir="C:\php\php-7.4.16-nts-Win32-vc15-x64\ext\"
upload_tmp_dir="C:\php-system\php-7.4.16-nts-Win32-vc15-x64\"
session.save_path="C:\php-system\php-7.4.16-nts-Win32-vc15-x64\"
error_log = "C:\php-system\php-7.4.16-nts-Win32-vc15-x64logs\PHP7416_errors.log"

;wincache https://sourceforge.net/projects/wincache/ (x64)
extension=php_wincache.dll

Add PHP to IIS

There are three main aspects to this installation:

  • Add PHP to Windows path
  • Create the FastCGI Handler mapping
  • Configure FastCGI Performance

Add PHP to Windows path

  • Open System Properties
  • Server Manager > Local Server > Click Computer Name> Advanced > Environmental Variables > copy this to the beginning of the “path” item (don’t forget the semi-colon):
    C:\php\php-7.4.16-nts-Win32-vc15-x64;
  • Close and re-open CMD, then test with php --version

By default, php --version will show the first instance of PHP in the system path. If you need to call a specific version of php, find the version of PHP you want to run in CMD and move it to the first entry in EVs.

Note: When in IIS, which is using FastCGI impersonation, the version of PHP will be that which is assigned to that website, regardless of the position in the environmental variables.

Create the FastCGI Handler mapping

In the root of IIS manager (machinename (user)) > handler mappings > “Add Module Mapping…”

Request Path: *.php
Module: FastCGIModule
Executable: C:\php\php-7.4.16-nts-Win32-vc15-x64\php-cgi.exe
Name: php7416 

Request Restriction:

Mapping > File or folder
Verbs & Access > Default
Click Ok and Yes to create the handler.

Update FAST-CGI settings for performance

IIS Manager > <machine name> (below Start Page) > FastCGI Settings

This will change settings in C:\Windows\System32\inetsrv\config\applicationHost.config

Double click the one named “C:\php\php-7.4.16-nts-Win32-vc15-x64\php-cgi.exe”

application fullPath="C:\php\php-7.4.16-nts-Win32-vc15-x64\php-cgi.exe"
monitorChangesTo="C:\php\php-7.4.16-nts-Win32-vc15-x64\php.ini" 
activityTimeout="600" 
requestTimeout="600" 
instanceMaxRequests="10000" 

Warning: if you have created the site prior to this and added a default doc, web.config may have two entries, causing a 500 error.

Add default document

Default documents > add index.php

Change permissions for App Pool for PHP

  • Assign IIS AppPool\testsite.local permissions to PHP folders
  • Go to C:\php-system\php-7.4.16-nts-Win32-vc15-x64\ > properties
  • In security > edit > add IIS AppPool\testsite.local and give it modify permissions

Test your work

Add in index.php file in your website. Use this simple script to show the IIS user and the version of PHP:

<?php
/*
#PHP CONFIG#
Prove PHP is working
Choose which one you need. Default gives you just PHP version
*/
echo 'Current PHP version: ' . phpversion() . '<hr>';
//phpinfo(); //All PHP config 
//phpinfo(INFO_GENERAL); //Config, php.ini location, build date, Web Server, System and more. 
//phpinfo(INFO_MODULES); //Loaded modules and their respective settings 

// show IIS user
echo exec('whoami'); 
?>

Here’s another script to check if the PHP log file can be written to. If it fails, it’s a path issue or a permissions issue.

<?php 
$logPath = ini_get('error_log');
$iisUser = exec('whoami');
error_log("PHP wrote this to test the log.\n");
echo "Check the log file for PHP  " . phpversion() . " <br>IIS User:<br>" . $iisUser . " <br> in: <br>" . $logPath . "<br />";
?>

Troubleshooting

500 Errors:

  • Make sure default index.php was added to your site
  • CMD > change to the folder with php-cgi.exe in it > php-cgi.exe + enter. Review the error message
  • Check PHP log file. If nothing was written there, it’s probably permissions.
  • If this an additional version of PHP you’ve installed > website > handler mappings > disable all other PHPs
  • Check the web.config in your site for duplications or anything odd

Add a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.