tliebrand.com Private Homepage von Thomas Liebrand

Running a php web application or web site on a windows server. This is mostly useful for small services where you don't want to spin up a separate (unix) server and already have a windows server (works on windows home to windows server) or you have otherwise windows dependency. The setup should cope well with any kind of PHP app but it is not intended to run high performance services.

If you are looking for a quick setup for your development machine, you should try:

  • winnmp
    this stack includes even a redis server, which is sadly not longer supported for windows.

  • xampp which solves the same problems but with an apache server

I won't describe how to include a database server like mysql, mariadb, mongodb as these are well documented and straight forward.

The here recommended setup is tested on 100+ installations.

 

The process flow:

  • We configure nginx to forward php requests

  • We run php spawner as a service

Sounds simple, right?

What we need:

  • Nginx for windows

  • PHP NTS (which requires c runtime according to the php version)

  • PHP Spawner

  • NSSM

Step by step

Download the latest nginx for windows and unzip it to your preferred directory, we will use "C:\server\nginx" in this example.

The nginx for windows documentation states: "Although several workers can be started, only one of them actually does any work." source: http://nginx.org/en/docs/windows.html

But don't worry, we will get around this.

Configure your nginx configuration to pass php requests to port 9001 as described on the nginx documentation for windows 


location ~ \.php$ {
  fastcgi_pass   127.0.0.1:9001;
  fastcgi_index index.php;
  fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  include       fastcgi_params;
}

Download and install a current PHP version for windows.

Remember to install the required c runtime.

As per today (February 2020) I do not recommend PHP 7.4 as it could break some of your dependencies.

Use the NTS version of php: 

Extract to "C:\server\PHP\PHP7.3"

Theoretically, we could already start a php console, but this would be visible:

cd C:\server\PHP\PHP7.3

php-cgi.exe -b 127.0.0.1:9001

But this would only give you one worker process. I see two possible work arounds:

  • Run multiple php-cgi processes and update the nginx confiugration to use them (each process will require its own port.) I believe this is how winnmp has solved that problem.

  • Spawn multiple php-cgi processes on one port using the php-spawner. This allows for running multiple processes and child process, which is awesome. The project hasn't been updated in a while, but don't get irritated, its very small and works great, it just doesn't need an update ;) https://github.com/deemru/php-cgi-spawner

Note: Nginx docs states to use a tool called RunHiddenConsole. This just hides the console, we will come to that with a different approach.

Put the latest php-spawner release to "C:\server\php-cgi-spawner.exe".

Then we start four processes with four child processes php-cgi-spawner.exe PHP/PHP7.3/php-cgi.exe 9001 4+4

Running php in this way, give us the advantage of reloading it anytime we want as stated in the nginx docs

nginx -s stop   fast shutdown
nginx -s quit graceful shutdown
nginx -s reload changing configuration, starting new worker processes with a new configuration, graceful shutdown of old worker processes
nginx -s reopen re-opening log files

Start PHP on start

Now we basically just need to start PHP and nginx whenever windows boots. We have the following possiblities:

  • Start with a task Event: start on boot Hidden Actions:

    • C:\server\nginx\nginx.exe

    • C:\server\php-cgi-spawner.exe with the arguments "PHP/PHP7.3/php-cgi.exe 9001 4+4" startup directory: C:\server\

  • Similar, we can do the same thing with entries to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run

  • We can create a windows service with a service wrapper

I personally prefer to wrap it with NSSM (the non-sucking-service-manager) , as it is very stable, can easily be stopped or restarted. It has the disadvantage that we cannot long reload it as it won't find the right instance to do so. If this is not a barrier continue with:

Install nssm

Download nssm and put it in the path (C:\windows\system32) which makes it available from the command line.

Create a service for nginx:

nssm install nginx C:\server\nginx\nginx.exe

Create a service for php:

nssm install php C:\server\php-cgi-spawner.exe  "PHP/PHP7.3/php-cgi.exe 9001 4+4"

Start the services

net start nginx
net start php

Obviously, you can create multiple instances of the php spawner service if you need to support multiple php versions simultaneously.