Setting up PHP with FastCGI on Windows using Apache

While PHP-FPM isn't available on Windows, you can use mod_fcgid to run PHP as FastCGI under Apache instead.

The Apache Lounge distribution doesn't ship with mod_fcgid included by default though, and you have to install it as an extra step which I thought was worth documenting for future reference.

Install PHP

I use Chocolatey to manage packages, so installing PHP is as easy as:

choco install php

The manual installation process is pretty simple too though:

  • Download the current either x86 or x64 (depending on your OS) "Non Thread Safe" distribution from PHP for Windows.
  • Extract the downloaded ZIP to somewhere on your filesystem. Chocolatey installs to C:\tools\php84 by default, and the rest of this post will assume the same path.
  • Add C:\tools\php84 as an entry in your PATH environment variable.

Copy the php.ini-development or php.ini-production file to php.ini and make any required changes.

Check that PHP is working by checking its version:

php -v

You should expect some output such as:

PHP 8.4.3 (cli) (built: Jan 15 2025 11:02:41) (NTS Visual C++ 2022 x64)
Copyright (c) The PHP Group
Zend Engine v4.4.3, Copyright (c) Zend Technologies

Install Apache

While Apache is available in the Chocolatey public feed, it uses the Apache Haus distribution and unfortunately this project is on hold.

Manual installation is similarly easy:

  • Download the current Apache release from Apache Lounge, making sure that if you chose an x64 version of PHP that you also choose an x64 version of Apache.
  • Extract the downloaded folder to C:\Apache24.
  • Add C:\Apache24\bin as an entry in your PATH environment variable.

Run the following command to install Apache as a service:

C:\Apache24\bin\httpd.exe -k install -n Apache

Make any required changes to C:\Apache24\conf\httpd.conf to configure the server, such as setting the document root, enabling modules, etc.

Check the syntax of the server configuration file:

httpd -t

You should expect some output such as:

Syntax OK

Install mod_fcgid

We have to install mod_fcgid manually, as it is not included when installed either through Chocolatey or manually.

  • Head to the Apache Lounge downloads page.
  • Scroll down to the heading "Apache 2.4 modules VS17".
  • Download the mod_fcgid module.
  • Open the downloaded ZIP file, which should contain the following items (and several others that we're not interested in):
    • mod_fcgid.so
  • Copy these items as follows within C:\Apache24\Apache24:
    • Copy mod_fcgid.so to modules\mod_fcgid.so

Now that we have the module installed, we need to load and configure it.

Open conf\extra\httpd-fcid.conf in a text editor. Replace the content of the file with the following:

<IfModule fcgid_module>
	FcgidInitialEnv PHPRC "C:\\tools\\php82"
	FcgidInitialEnv PATH "C:\\tools\\php82;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;"
	FcgidInitialEnv SystemRoot "C:\\Windows"
	FcgidInitialEnv SystemDrive "C:"
	FcgidInitialEnv TEMP "C:\\WINDOWS\\TEMP"
	FcgidInitialEnv TMP "C:\\WINDOWS\\TEMP"
	FcgidInitialEnv windir "C:\\WINDOWS"

	FcgidIOTimeout 40
	FcgidConnectTimeout 10
	FcgidMaxProcesses 8
	FcgidOutputBufferSize 64
	ProcessLifeTime 240
	FcgidMaxRequestsPerProcess 0
	FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 0
	FcgidInitialEnv PHP_FCGI_CHILDREN 0
	FcgidProcessLifeTime 3600
	FcgidMinProcessesPerClass 0

	<Files ~ "\.php$">
		Options ExecCGI SymLinksIfOwnerMatch
		AddHandler fcgid-script .php
		FcgidWrapper "C:/tools/php82/php-cgi.exe" .php
	</Files>
</IfModule>

httpd-fcgid.conf

Open conf\httpd.conf in a text editor. Add or uncomment the following to the end of the file (or put it next to the other Include directives):

LoadModule fcgid_module modules/mod_fcgid.so
Include conf/extra/httpd-fcgid.conf

httpd.conf

Closing Thoughts

Immediately after switching to mod_fcgid, there was a perceivable performance improvement. This is most likely due to mod_php requiring a thread safe version of PHP which will include locks.

The actual upgrade to PHP 8.2 from 8.1 itself also went pretty smoothly, with no breakage to existing code - which is always nice!