Configuration of PHP and MySQL on Windows Server with IIS

Recently I challenged myself to see how far we can go with PowerShell DSC and non Microsoft Products. My goal in this challenge was to install and configure PHP and MySQL on a blank Windows Server 2012 R2 offline server.

Why would someone do this?

Because I wanted gain a better understanding on how far PowerShell DSC configurations are useful in challenging tasks with non Windows or Microsoft Products. Another outcome should be a fully functional PHP server to host PIWIK for a SharePoint Farm.

And why would someone try this on a offline server without any connection to the internet? This a very common scenario I’m facing with customers.

What do we start with?

As I’m writing this blog, PHP version 7.2 is the current one. I used to work with PHP before in several projects and used XAMPP to host my applications for development purposes. XAMPP bundles Apache, PHP and MySQL. To get started with XAMPP on a windows system is a breeze.

Installing all that stuff manually works fine and there are many options available supporting the installations: e.g. the IIS Web Platform Installer – But not in an offline scenario. The same fact is preventing me from using chocolatey in PowerShell DSC. I do not have an offline option.

I started with the following example provided through the xWebAdministration DSC Resource:PowerShellDsc/xWebAdministration – Examples: Registering PHP

Install the necessary Windows Features and disable not needed IIS Pools

I use the following lines of PowerShell to configure Windows Server and IIS with DSC:


$features = @("Web-Server",
"Web-Mgmt-Tools",
"web-Default-Doc",
"Web-Dir-Browsing",
"Web-Http-Errors",
"Web-Static-Content",
"Web-Http-Logging",
"web-Stat-Compression",
"web-Filtering",
"web-CGI",
"web-ISAPI-Ext",
"web-ISAPI-Filter"
)
$dependsOn = @()
$features | ForEach-Object Process {
WindowsFeature $_ {
Name = $_
Ensure = "Present"
}
$dependsOn += "[WindowsFeature]$($_)"
}
@(
".NET v2.0" ,
".NET v2.0 Classic",
".NET v4.5",
".NET v4.5 Classic",
"Classic .NET AppPool",
"DefaultAppPool"
) | ForEach-Object Process {
xWebAppPool "Remove-$($_.ToString().Replace(" ","").Replace(".",""))"
{
Name = $_
Ensure = "Absent"
DependsOn = $dependsOn
}
}
xWebSite RemoveDefaultWebSite
{
Name = "Default Web Site"
PhysicalPath = "C:\inetpub\wwwroot"
Ensure = "Absent"
DependsOn = $dependsOn
}
Package vcRedist {
Path = "$($SourceFolder)\VC_redist.x64.exe"
ProductId = "{6c6356fe-cbfa-4944-9bed-a9e99f45cb7a}"
Name = "Microsoft Visual C++ 2017 Redistributable (x64) – 14.11.25325"
Arguments = "/install /passive"
}
Archive PHP {
Path = "$($SourceFolder)\php-7.1.12-nts-Win32-VC14-x64.zip"
Destination = $phpDirectory
}
File PhpWinCache {
SourcePath = "$($SourceFolder)\WinCache\php_wincache.dll"
DestinationPath = "$($phpDirectory)\ext"
Type = "File"
MatchSource = $true
DependsOn = @("[Archive]PHP")
}
File PhpIni {
SourcePath = "$($SourceFolder)\php.ini"
DestinationPath = "$($phpDirectory)\php.ini"
MatchSource = $true
Force = $true
Checksum = "SHA-512"
Ensure = "Present"
DependsOn = @("[Archive]PHP")
}
xIisModule PhpHandler {
Name = "phpFastCgi"
Path = "$($phpDirectory)\php-cgi.exe"
RequestPath = "*.php"
Verb = "*"
Ensure = "Present"
ModuleType = "FastCgiModule"
DependsOn = @("[Package]vcRedist", "[Archive]PHP") + $dependsOn
}
Script FixIisModule {
GetScript = {
return @{
Result = ""
}
}
SetScript = {
Import-Module WebAdministration
Set-WebHandler phpFastCgi Modules FastCgiModule
}
TestScript = {
Import-Module WebAdministration
$fastCgi = Get-WebHandler phpFastCgi
return $fastCgi.Modules -eq "FastCgiModule"
}
DependsOn = "[xIisModule]PhpHandler"
}
Environment PathPhp {
Name = "Path"
Value = ";$($phpDirectory)"
Ensure = "Present"
Path = $true
DependsOn = "[Archive]PHP"
}

After completing the IIS configuration we can start with the installation of PHP and MySQL.

Configuration of PHP and the WinCache Extension

With PHP 7.1 there are several installation options available. I opted for the Non Thread Save version of PHP and downloaded this version on my client and made it available on the server.

Additionally you will need to download:

The installation of PHP is fairly simple. It consists of the following steps:

  1. Install Microsoft Visual C++ 2017
  2. Extract the PHP zip file to your “installation” folder
  3. Copy the WinCache DLL to the ext folder in your PHP “installation” folder
  4. Rename the php.ini-production to php.ini
  5. Enable the WinCache extension in the php.ini
  6. Add the Php Handler
  7. Configure the Path for PHP

Steps 1 to 4 are regualr DSC Resources:

  1. Package Resource
  2. Archive Resource
  3. File Resource
  4. File Resource
  5. See below
  6. xIisModule Resource – Currently with one Issue
  7. Environment Resource

For Step 5 we have to write some Code using the script resource:


Script PhpWinCache {
GetScript = {
return @{
Result = ""
}
}
TestScript = {
$iniFile = "$($phpDirectory)\php.ini"
$currentStatus = Select-String Path $iniFile Pattern "^extension=php_wincache.dll"
Write-Debug "$($currentStatus)"
return ($null -ne $currentStatus)
}
SetScript = {
$iniFile = "$($phpDirectory)\php.ini"
Add-Content Path $iniFile Value "`r`nextension=php_wincache.dll" Force
}
DependsOn = @("[File]PhpWinCache", "[File]PhpIni")
}

Configuration of MySQL

The MySQL Part is fairly simple. Download the current MySQL Version:

and open this example provided through the xMySql Resource to finish your DSC configuration:

I modified the package resource to match the current MySQL version:


Package MySqlInstaller {
Path = "$($SourceFolder)\mysql-installer-community-5.7.20.0.msi"
ProductId = "{7999380B-7D4E-4E76-B61D-3AFCA710F24D}"
Name = "MySQL Installer – Community"
Arguments = ""
}
Package vcRedist2013 {
Path = "$($SourceFolder)\vcredist_x64.exe"
ProductId = "{ef6b00ec-13e1-4c25-9064-b2f383cb8412}"
Name = "Microsoft Visual C++ 2013 Redistributable (x64) – 12.0.40660"
Arguments = "/install /passive"
}
xMySqlServer MySqlInstance {
MySqlVersion = "5.7.20"
RootPassword = $MySqlRootPassword
Port = 3306
Ensure = "Present"
DependsOn = @("[Package]MySqlInstaller","[Package]vcRedist2013")
}
Script FixReadErrorinMySqlResource {
GetScript = {
return @{
Result = ""
}
}
SetScript = {
$filePath = "C:\Program Files\WindowsPowerShell\Modules\xMySql\2.1.0.0\MSFT_xMySqlUtilities.psm1"
$newLine = @"
if(`$line -match [RegEx]::Escape("mysql: [Warning] Using a password on the command"))
{
break
}
"@
$content = Get-Content $filePath
$content[241] = "{0}`r`n{1}" -f $newLine, $content[241]
$content | Set-Content $filePath
Import-Module $filePath
}
TestScript = {
$content = Get-Content "C:\Program Files\WindowsPowerShell\Modules\xMySql\2.1.0.0\MSFT_xMySqlUtilities.psm1"
if( $content.length -eq 319 -and
$content[241] -eq " if(`$line -match [RegEx]::Escape(`"mysql: [Warning] Using a password on the command`"))")
{
return $true
}
return $false
}
}
xMySqlServer MySqlInstance {
MySqlVersion = "5.7.20"
RootPassword = $MySqlRootPassword
Port = 3306
Ensure = "Present"
DependsOn = @("[Package]MySqlInstaller", "[Script]FixReadErrorinMySqlResource)
}
xMySqlDatabase MySqlPiwikDb {
MySqlVersion = "5.7.20"
DatabaseName = "Piwik"
RootCredential = $MySqlRootPassword
Ensure = "Present"
DependsOn = @("[xMySqlServer]MySqlInstance", "[Script]FixReadErrorinMySqlResource)
}

Summary

The installation process of PHP and MySQL on a Windows Server 2012 R2 is straight forward. Adding the WinCache Extension was tricky.

Biggest challenge: The examples provided in the github repsitories of xWebAdministration, xMySql were not up to date. The Guids and used versions differ from the current ones.

What’s next?

The next step would be to

  • Create a new IIS Web Application
  • Configure this IIS Web Application for HTTPS
  • Provision and configure PIWIK
Advertisement

4 thoughts on “Configuration of PHP and MySQL on Windows Server with IIS

  1. Hello Andi,

    I am new to powershell dsc. Was wondering if you can share the whole dsc script for php on IIS. I am getting confused between your 2 scripts IISInstallationDSC and phowincacheextension.

    Regards,
    Sai

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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