Tag Archives: FAQ

Wamp-Developer Server FAQ

Using phpMyAdmin to Create a MySQL Database, User, Password

Make sure Apache and MySQL are running, and access phpmyadmin via URL:
http://127.0.0.1/phpmyadmin

Login with:

Username: root
Password: (leave it blank, it's not set by default)

Click ‘Go’.

* User “root” under WampDeveloper Pro is restricted to local network access in multiple ways, so setting a password is not absolutely necessary.

Create a database:

  1. Click on the ‘Databases’ tab.
  2. Specify a Database name.
  3. Leave everything else as-is (don’t select a collation).
  4. Click ‘Create’.

Create a user:

  1. Click on that database.
  2. Click on its ‘Privileges’ tab.
  3. Click in ‘New’ group, ‘Add user’.
User name ('Use text field'): username-here
Host (select 'Use text field'): 127.0.0.1
Password ('Use text field'): password-here
Re-type: password-here

Leave everything else as-is:

'Database for user' group: Grant all privileges on database "database-name".
'Global privileges' group: None

* Don’t select any “Global” privileges/permissions, this user only needs all privileges/access on that specific database, and not on all the databases under MySQL.

Click ‘Go’.

Whenever you need to specify this info when you install or configure a web-app or script, make sure to enter the db and user info exactly as above, with “Host” as 127.0.0.1 and not as “localhost”.

Connecting WAMP Server to Oracle With PHP’s php_oci8_11g.dll

Download the proper Oracle Instant Client

If using 32 bit PHP, you’ll need use the 32 bit Windows Oracle Instant Client:
Instant Client Downloads for Microsoft Windows (32-bit)

Download package:
"Instant Client Package - Basic Lite"

Use version 11 of the client, not 12, with PHP’s php_oci8_11g.dll.

Unzip the package into a location such as:
C:\WampDeveloper\Tools\Oracle\

Then modify the System’s PATH environmental variable with the end location. This is important as otherwise its DLLs (OCI.dll) will not be found/loaded by PHP’s php_oci8_11g.dll:
C:\WampDeveloper\Tools\Oracle\instantclient[version]

Restart the system for Path changes to fully propigate.

Installed the VC++ 2012 Runtime

Under PHP 5.5, which is a VC11 (VS.NET 2012) build, some of the extensions depend on the full set of Microsoft VC++ 2012 Runtime DLLs.

Download and install the 32 bit VC++ 2012 Runtime Redistributable (vcredist_x86.exe):
Visual C++ Redistributable for Visual Studio 2012 Update 4

PHP 5.5 extension php_oci8_11g.dll, and other extensions such as php_intl.dll, depend on files: msvcr110.dll and msvcp110.dll, which this will place into your C:\Windows\System32 folder.

Check Dependencies of php_oci8_11g.dll

Open the command line, change to the PHP’s directory, and check to see if all php_oci8_11g.dll dependancies (DLLs) are being found.

C:
cd \WampDeveloper\Components\Php
deplister ext\php_oci8.dll
deplister ext\php_oci8_11g.dll

Everything should be listed as found, and you should not see this (the Oracle Client DLL not being found) – OCI.dll,NOTFOUND

Load php_oci8_11g.dll

Edit php.ini and un-comment:

extension=php_oci8.dll
extension=php_oci8_11g.dll

Save file. Restart Apache.

Then check to make sure this module has been loaded:

http://serverhost/phpinfo.php

* phpinfo.php contains this code: <?php echo phpinfo(); ?>, and will show you all the loaded PHP extensions and their settings.

Issues

PHP Startup: Unable to load dynamic library ‘C:/WampDeveloper/Components/Php/ext\php_oci8_11g.dll’ – %1 is not a valid Win32 application.

This indicates a build-type mismatch.

The used PHP extension (php_oci8_11g.dll) is not matching the PHP build type: 32bits (x86), VC11 (VS.NET 2012), TS (Thread Safe). * TS (Thread Safe) is for Regular PHP; NTS (Not Thread Safe) is for PHP-FCGI.

Chances are you are using the 64-bit build of php_oci8_11g.dll, or a VC9 build, or a NTS build – that replaced the default ext\php_oci8_11g.dll file that PHP came with.

Unable to load dynamic library ‘C:/WampDeveloper/Components/Php/ext\php_oci8_11g.dll’ – The specified module could not be found.

The module is being found (and you can verify that it’s present), but the real problem is that it has dependencies on other DLLs which are not being found.

Update the System’s PATH environmental variable with the Oracle Instant Client’s OCI.dll file location.

Also make sure PHP’s root folder is in the PATH. It and it’s \ext paths should already be listed in WampDeveloper’s %wampdev% environmental variable (which itself is expanded in %path%).

* In the error message, the backslash (“\”) being used instead of the “/”, is never the problem.

Oracle Instant Client Version 11 vs. 12

You should use the Oracle Instant Client version that matches the php_oci8 extension version:

Use client version 11 for extension php_oci8_11g.dll

Use client version 12 for extension php_oci8_12c.dll

You can download the oci8 extension for client version 12 from:
http://windows.php.net/downloads/pecl/releases/oci8/

The nomenclature of the extension’s file name to built-type is:

  • PHP 5.5 32bit: TS, VC11, x86
  • PHP-FCGI 5.5 32bit: NTS, VC11, x86

For WampDeveloper’s PHP 5.5 (regular, not FCGI) 32bit channel, you would get this file:
php_oci8-2.0.8-5.5-ts-vc11-x86.zip

Unzip the contents into PHP “\ext” folder (make sure to overwrite all files), and load it via php.ini:

extension=php_oci8.dll
extension=php_oci8_12c.dll

PDO

If your code uses PDO methods to connect to databases, you’ll also need to load this extension:

extension=php_pdo_oci.dll

Notes

OCI8 Requirements (php.net)

Using PHP OCI8 with 32-bit PHP on Windows 64-bit

Installing PHP and the Oracle Instant Client for Linux and Windows, For PHP 5.4 and Oracle Database 11g Release 2

Installing PHP and the Oracle Instant Client for Linux and Windows, For PHP 5.5, OCI8 2.0 and Oracle Database 12c Release 1

Running PHP Scripts as Cron Jobs on Windows

How do I hit a set of web pages to run scripts that perform tasks or update data?

On Windows you would use the “Windows Task Scheduler” to execute PHP scripts either via a URL, or directly via php.exe – at specific times or on specific events.

Run PHP Script Via URL

To hit a URL you can use command line tools such as “wget” or “curl” (wget and curl are already included in WampDeveloper Pro under the Tools folder), and for multiple URLs you would wrap it all up into 1 batch file.

For example, to hit this URL…
http://domain.name/webapp/tools/cron.php

You would use “wget” by executing this command…

C:\WampDeveloper\Tools\gnuwin32\wget.exe -q -O NUL http://domain.name/webapp/tools/cron.php

* The “-q” switch makes wget silent and the “-O NUL” option discards the output (instead of saving it to a file).

Set up a “Windows Scheduled Task” (via “Task Scheduler”)…

Create Task...
Triggers: Daily
Advanced settings... Repeat task every: 5 minutes; Indefinitely
Action: Start a program
Program/script: C:\WampDeveloper\Tools\gnuwin32\wget.exe
Arguments: -q -O NUL http://domain.name/webapp/tools/cron.php
Start In: C:\WampDeveloper\Tools\gnuwin32\

Run PHP Script Directly

An even simpler and more straight-forward way to perform the above is to just run the PHP scripts directly without involving Apache, or anything other than the PHP interpreter/engine (php.exe)…

For example, to create a Task that executes this PHP file every 5 minutes…
C:\WampDeveloper\Websites\domain.name\webroot\webapp\tools\cron.php

Set up a “Windows Scheduled Task” (via “Task Scheduler”)…

Create Task...
Triggers: Daily
Advanced settings... Repeat task every: 5 minutes; Indefinitely
Action: Start a program
Program/script: C:\WampDeveloper\Components\Php\php.exe
Arguments: -f C:\WampDeveloper\Websites\domain.name\webroot\webapp\tools\cron.php
Start In: C:\WampDeveloper\Websites\domain.name\webroot\

* The ‘start in’ path would need to reflect the path the script is expecting to be started in (so all its inner relative paths work). Usually this is either the webapp’s folder, or the folder the script is in.

You could also create this Task via the command-line -

schtasks /create /sc minute /mo 5 /tn "my task name" /tr "C:\WampDeveloper\Components\Php\php.exe -f C:\WampDeveloper\Websites\domain.name\webroot\webapp\tools\cron.php"

* The command-line method doesn’t allow a start-in directory.

Run Multiple PHP Scripts via Batch File

If you have multiple scripts or URLs to hit on 1 Task, create a batch file (filename.bat) containing multiple instances of the above commands…

C:\WampDeveloper\Tools\gnuwin32\wget.exe -q -O NUL http://domain.name/url1
C:\WampDeveloper\Tools\gnuwin32\wget.exe -q -O NUL http://domain.name/url2
C:\WampDeveloper\Tools\gnuwin32\wget.exe -q -O NUL http://domain.name/url3
C:\WampDeveloper\Components\Php\php.exe -f C:\WampDeveloper\Websites\domain.name\webroot\path\file1.php
C:\WampDeveloper\Components\Php\php.exe -f C:\WampDeveloper\Websites\domain.name\webroot\path\file2.php
C:\WampDeveloper\Components\Php\php.exe -f C:\WampDeveloper\Websites\domain.name\webroot\path\file3.php

Set up a “Windows Scheduled Task” (via “Task Scheduler”)…

Create Task...
Triggers: Daily
Advanced settings... Repeat task every: 5 minutes; Indefinitely
Action: Start a program
Program/script: C:\path\filename.bat
Arguments:
Start In: C:\path\

Installing and Running Ghost CMS under Apache

Ghost CMS is a blogging platform like WordPress, except with a minimalistic feel. Ghost uses Node.JS and SQLite, but can be connected and ran through a full Apache, PHP, and MySQL web-server platform such as WampDeveloper Pro (for Windows).

1. Download Ghost CMS:
https://ghost.org/download/

2. Extract the Ghost CMS package into your website’s non-DocumentRoot folder (e.g., not into \webroot):
C:\WampDeveloper\Websites\www.example.com\ghost

3. Open the command-line, change to the ghost folder, and install Ghost CMS:

C:
cd C:\WampDeveloper\Websites\www.example.com\ghost
npm install --production
npm start

This will automatically download a number of Ghost CMS dependencies (node.js modules) and set up a default configuration file.

* WampDeveloper Pro already comes with Node.JS and NPM.

4. Test the installation by going to URL:

http://127.0.0.1:2368/ghost

Integrate Apache with Ghost + Node.JS

Open the website’s HTTP VirtualHost file, and add all configuration inside the “<VirtualHost>” block…

Transparently proxy all http://www.example.com/blog requests through Apache:

ProxyPass /blog http://127.0.0.1:2368/ghost

And if you want to secure /blog to local system access only:

<Location "/blog">
    Options None
    AllowOverride None
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1 ::1
</Location>

Save VirtualHost file. Restart Apache.

Ghost Hosted Through Apache

See your Ghost CMS installation hosted by Apache (on the regular HTTP port 80):
http://www.example.com/blog

Ghost’s configuration file is config.js, located in Ghost’s folder, and the settings are listed here:
http://support.ghost.org/config/

Installing Comodo PositiveSSL Certificate Bundled with Root and Intermediate CA Certificates on Apache

The problem with basic domain-validation certificates is they tend to have multiple “Intermediate CA” certificates that have to be bundled together and included into the setup, and the provided instruction on how to use those 3 additional certificate files is often missing, outdated, or just wrong. I think this is done by design, to get you to spend more on the more expensive extended validation certs (that don’t need multiple intermediary certs).

Aside from that, the basic low-end “domain validation” certs win on 3 fronts:

  • They cost $10 instead of $300.
  • They are very easy to get since the “validation” step (to prove who you are) is basically opening an email sent to the domain name (admin@domain.name) and clicking the provided link.
  • They tend to have faster/more-responsive page load times, since the Browser does not download the Certificate Revocation List (CRL) or perform a check of the certificate status (via OCSP), either of which can add an additional .5-2 seconds before the page is displayed (this is why Amazon does not use an EV “green bar” cert).

Here is how to install the most common certificate on the market, the Comodo PositiveSSL Certificate bundled with Root and Intermediate CA Certificates on Apache.

These instructions can be used on WampDeveloper Pro, on any other WAMP (Xampp, WampServer, etc) or Apache setup, and on Linux – with just some path changes. The fictitious domain used in this example is www.example.com.

Open the command line with elevated privileges (e.g., right-click cmd.exe and select ‘Run as admin’). And change to the website’s \certs folder:

C:
cd \WampDeveloper\Websites\www.example.com\certs\

1. Generate a 2048 bit private key named www_example_com.key.

openssl genrsa -out www_example_com.key 2048

2. Generate a Certificate Signing Request (csr) file named www_example_com.csr.

openssl req -new -sha256 -key www_example_com.key -out www_example_com.csr -config C:\WampDeveloper\Config\Apache\openssl.cnf

* Update the above line with the correct openssl “-config ...” path… On your WampDeveloper installation, update path for your drive letter. On other WAMPs, update the full path. And on Linux, leave that part out.

For “Common Name” enter:
www.example.com

For all other fields enter:
.

The “.” means empty / no value. Because you are purchasing a simple “domain validation” certificate, all other fields will get erased.

* If you specify the “www” host on the domain.name (as above), Comodo will issue the certificate for both: www.example.com and example.com

3. Open the “Certificate Signing Request” file www_example_com.csr and copy/paste its entire (full) contents into the proper box when activating the SSL Certificate you have purchased.

4. After the confirmation process, you’ll receive an email with an attached zip file named “www_example_com.zip”.

1. Save this file to some location.
2. Right click this file, select Properties. Click button: Unblock (or Windows won’t allow you to extract the certs due to security issues).
3. Extract the contents of the zip into the website’s \certs folder.

5. Create the CA (Certificate Authority) Intermediate Certificates Bundle file:

copy /B COMODORSADomainValidationSecureServerCA.crt + COMODORSAAddTrustCA.crt + AddTrustExternalCARoot.crt PositiveSSL.ca-bundle

For Linux, this command would instead be:

cat COMODORSADomainValidationSecureServerCA.crt COMODORSAAddTrustCA.crt AddTrustExternalCARoot.crt > PositiveSSL.ca-bundle

This will create a file named PositiveSSL.ca-bundle containing the 3 CA (Certificate Authority) intermediate certificates, all in the proper order. Each CA certificate basically validates the one next to it, top to bottom, from the root CA certificate that your Browser has on file, through the intermediate certs, and down to the public certificate file.

6. Configure the website’s SSL VirtualHost file to use the private key, public certificate, and the bundled intermediate certificates chain file.

Edit the website’s SSL VirtualHost file:
C:\WampDeveloper\Vhosts\www.example.com.ssl.vh.conf

Update existing SSLCertificateFile and SSLCertificateKeyFile paths with the proper file names. And add in the SSLCertificateChainFile directive + path.

SSLCertificateFile "C:/WampDeveloper/Websites/www.example.com/certs/www_example_com.crt"
SSLCertificateKeyFile "C:/WampDeveloper/Websites/www.example.com/certs/www_example_com.key"
SSLCertificateChainFile "C:/WampDeveloper/Websites/www.example.com/certs/PositiveSSL.ca-bundle"

Save VirtualHost file.

7. Restart Apache.

Check your website -

PositiveSSL-Bundled-Chain

WampDeveloper Pro v4 Download Links

The last WampDeveloper Pro v4 releases can be downloaded here:
http://www.devside.net/download/s23qw/WampDeveloper-4.2.0.3.zip
http://www.devside.net/download/s23qw/WampDeveloper-v4.2.0.4-delta.zip

* The “delta” release can just be extracted right over the 4.2.0.3 installation (overwrite everything + make sure WampDeveloper . exe is not running / open). It’s a package of 10 or so DLL files and the WampDeveloper exe file… That fixes a couple of minor bugs (mostly registration bugs).

Load Testing Apache with AB (Apache Bench)

The only productive way to load test an Apache or WAMP (such as WampDeveloper Pro) web-server is to test a real-world page that itself performs -

  • Loading and processing of multiple PHP files.
  • Establishment of multiple MySQL connections, and performing multiple table reads.

This is the minimum, because the test of an almost empty and static page (used by most examples) tells us nothing about how the different parts of a web-server hold up under stress, nor how that web-server setup will handle real-world concurrent connections to websites running on web-apps such as WordPress.

* Ideally, this test would also a) perform GETs of all page assets (css, js, images) and b) simulate traffic of which 10% is DB writes (we’ll skip this because its more complicated to set up).

Using AB

Luckily, this type of test is very easy to do in a quick (and somewhat dirty) way by using Apache’s ab (Apache Bench) application (that’s included with each Apache version in its \bin directory).

This ab test won’t be the most extensive test, and it comes with its own caveats, but it will quickly show you -

  • If there is an immediate problem with the setup (this problem will manifest itself in Apache crashing).
  • How far you can push the Apache, PHP, and MySQL web-server (with concurrent connections and page request load).
  • And what Apache and PHP settings you should modify to get better performance and eliminate the crashes.

AB Issues

There are some problems with ab to be aware of -

  • ab will not parse HTML to get the additional assets of each page (css, images, etc).
  • ab can start to error out, breaking the test, as the number of requests to perform is increased, more connections are established but not returned, and as the load increases and more time passes (see ab -h for explanation of -r switch).
  • ab is an HTTP/1.0 client, not a HTTP/1.1 client, and “Connection: KeepAlive” (ab -k switch) requests of dynamic pages will not work (dynamic pages don’t have a predetermined “Content-Length: value“, and using “Transfer-Encoding: chunked” is not possible with HTTP/1.0 clients).

More on AB and the KeepAlive issue -

KeepAlive – Apache Directive

A Keep-Alive connection with an HTTP/1.0 client can only be used when the length of the content is known in advance. This implies that dynamic content will generally not use Keep-Alive connections to HTTP/1.0 clients.

Compatibility with HTTP/1.0 Persistent Connections – Hypertext Transfer Protocol HTTP/1.1 Standard

A persistent connection with an HTTP/1.0 client cannot make use of the chunked transfer-coding, and therefore MUST use a Content-Length for marking the ending boundary of each message.

Chunked transfer encoding – Wikipedia

Chunked transfer encoding allows a server to maintain an HTTP persistent connection for dynamically generated content. In this case the HTTP Content-Length header cannot be used to delimit the content and the next HTTP request/response, as the content size is as yet unknown.

Request Floods

ab will flood the Apache server with requests – as fast as it can generate them (not unlike in a DDoS attack). AB has no option to set a delay between these requests.

And given that these requests are generated from the same local system they are going to (i.e., the network layer is bypassed), this will create a peak level of requests that will cause Apache to stop responding and the OS to start blocking/dropping additional requests. Especially if the requested page is a simple PHP file that can be processed within a millisecond.

In this context, with ab, the bigger the -c (concurrent number of requests to do at the same time) is, the lower your -n (total number of requests to perform) should be… Even with a -c of 5, -n should not be more than 200.

Expect the behavior of the ab tests to be very non-deterministic under higher concurrent loads, they will fail and succeed randomly. Even a -c of 2 will cause issues.

These are the error messages displayed by ab -

apr_socket_recv: An existing connection was forcibly closed by the remote host. (730054)
apr_pollset_add(): Not enough space (12)

And the dialog displayed by Windows -
httpd-apache-crash

When this happens (a message is displayed that Apache has crashed), just ignore it (Apache is still running), and keep repeating the test until “Failed requests:” is reported as “0″, AND “Percentage of the requests served within a certain time (ms)” is about 2-20x between the 50% and 99% mark (and not 200x). Otherwise, the test is not reliable due to the issues that present themselves when ab floods Apache on loopback (and due to how the OS responds to that flood).

This is what you should see on a good test of a simple index.php page…

C:\WampDeveloper> ab -l -r -n 100 -c 10 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/

Benchmarking www.example.com (be patient).....done

Server Software:        Apache/2.4.10
Server Hostname:        www.example.com
Server Port:            80

Document Path:          /
Document Length:        Variable

Concurrency Level:      10
Time taken for tests:   0.046 seconds
Complete requests:      100
Failed requests:        0
Keep-Alive requests:    100
Total transferred:      198410 bytes
HTML transferred:       167500 bytes
Requests per second:    2173.91 [#/sec] (mean)
Time per request:       4.600 [ms] (mean)
Time per request:       0.460 [ms] (mean, across all concurrent requests)
Transfer rate:          4212.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       2
Processing:     1    4   5.9      3      33
Waiting:        1    4   5.9      3      32
Total:          1    4   6.0      3      33

Percentage of the requests served within a certain time (ms)
  50%      3
  66%      4
  75%      4
  80%      5
  90%      6
  95%     22
  98%     32
  99%     33
 100%     33 (longest request)

Before Performing The Load Test

Make sure that -

  • You’ve rebooted the system and don’t have anything extra open/running (i.e., YouTube videos playing in your Browser).
  • These extra PHP extensions are not loaded: Zend OPcache, APC, nor XDebug.
  • You wait 4 minutes before performing another ab test to avoiding TCP/IP Port Exhaustion (also known as ephemeral port exhaustion).
  • And in a test where KeepAlive works (it doesn’t in ab tests getting dynamic pages), the number of Apache Worker Threads are set to be greater than the number of concurrent users/visitors/connections.
  • If Apache or PHP crashes, you’ve rebooted the computer or VM before performing another test (some things get stuck and continue to persist after Apache and/or mod_fcgid’s PHP processes are restarted).

Start The AB Test

1. Install WordPress as http://www.example.com/blog

2. Open the command-line (cmd.exe).

3. Restart Apache and MySQL, and prime the web-server (with 1 request):
ab -n 1 -c 1 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

4. Run the Apache Bench program to simulate -

1 concurrent user doing 100 page hits

This is 100 sequential page loads by a single user:
ab -l -r -n 100 -c 1 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

This shows you how well the web-server will handle a simple load of 1 user doing a number of page loads.

5 concurrent users each doing 10 page hits

This is 100 page loads by 5 different concurrent users, each user is doing 10 sequential pages loads.
ab -l -r -n 50 -c 10 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

This represents a peak load of a website that gets about 50,000+ hits a month. Congratulations, your website / business / idea has made it (and no doubt is on its way up).

10 concurrent users each doing 10 page hits

This is 100 page loads by 10 different concurrent users, each user is doing 10 sequential pages loads.
ab -l -r -n 100 -c 10 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

This is where the load starts to really stress test the web-server, as 10 concurrent (simultaneous) users is a lot of traffic. Most websites will be lucky to see 1 or 2 users (visitors) a minute… So let me say it again, 10 users per second is a lot of traffic!

30 concurrent users each doing 20 page hits

This is 600 page loads by 30 different concurrent users, each user is doing 20 sequential pages loads.
ab -l -r -n 600 -c 30 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

This is the edge of what a non-cached WordPress setup will be able to handle without crashing or timing-out the web-server (and/or ab itself). This type of load represents an extremely active website or forum, the top 1%.

90 concurrent users each doing 30 page hits

This is 2700 page loads by 90 different concurrent users, each user is doing 30 sequential pages loads.
ab -n 2700 -c 90 -k -H "Accept-Encoding: gzip, deflate" http://www.example.com/blog/

Only a fully cached (using mod_cache) Apache setup will be able to handle this type of a load. This represents some of the busiest sites on the net, and there is no hope of this not maxing out and crashing (if your settings are not just right) the web-server with a non-cached WordPress setup.

Analyze the AB Results

We only care about 3 things:

1. How many Requests Per Second are we seeing? The other metrics are not really useful, as they are not representative of anything real in this ab context. * This value will remain somewhat the same regardless of the concurrency level used.

2. Are there any errors in the website’s or Apache’s (general) error and php logs? * When things stat to choke, PHP memory issues will start coming up. A lot of PHP scripts also begin to crash (and take out Apache + PHP processes) if they are not written with concurrency in mind.

3. At what concurrency level does Apache crash and/or time-out? * If this is happening at a lower concurrency level, something is wrong and you need to adjust these settings either lower of higher…

Adjust Settings to Gain Stability Under Load

Apache:
C:\WampDeveloper\Config\Apache\extra\httpd-mpm.conf

# The number of Apache threads (workers) to deploy. Each worker can handle a separate concurrent connection or request.
# This should never be set more than the expected traffic can bring in, otherwise it will waste server resources.
# Setting this value DOWN from the default 64-128 is a good idea.
ThreadsPerChild 64
# ThreadLimit should be about 50% more than ThreadsPerChild, as this has a side-effect of allotting more memory and enabling Apache to use that extra memory during peak load times.
ThreadLimit 96

# The number of requests (or connections if KeepAlive is On) after wich to recycle all Apache threads (to help control memory leaks and process bloat).
# Renamed to MaxConnectionsPerChild under Apache 2.4 (&quot;MaxRequestsPerChild&quot; is still valid).
MaxRequestsPerChild 16384

# The default stack size on Windows is less than or equal to 1MB, and 8MB on Linux.
# Increase size to help crashes from segmentation faults / stack overflows due to PHP scripts needing more stack size.
# Can decrease value to lower memory consumption by Apache when PHP is ran via mod_php (PHP as an Apache thread).
# Can decrease value even more when PHP is ran via mod_fcgid (PHP as a process outside of Apache).
# 8MB*1024*1024 is 8388608, 4MB*1024*1024 is 4194304, 1MB*1024*1024 is 1048576, 0.5MB*1024*1024 is 524288
<IfVersion >= 2.2>
ThreadStackSize 2097152
</IfVersion>

# The maximum number of free Kbytes that every Apache thread is allowed to hold without attempting to give it back to the OS.
# Apache 2.0 and 2.2 default to 0 / unlimited (bad), Apache 2.4 to 2MB (better).
# This might prevent the Apache process from growing too large as this will typically restrict its process max size to threads * MaxMemFree.
MaxMemFree 2048

# Backlog queue when all threads/workers are taken up.
# Increase to handle peak loads, and during TCP SYN flood attacks (default is 511).
ListenBacklog 2711

# TCP receive buffer size (in bytes). 0 specifies to use the OS default.
ReceiveBufferSize 0

# TCP send buffer size (in bytes). 0 specifies to use the OS default.
SendBufferSize 0

Apache:
C:\WampDeveloper\Config\Apache\extra\wampd-default.conf

# Turn BufferLogs On to buffer logs for multiple requests instead of writing them out individually to the log files
# Good for performance, but inconvenient for trying to detect or debug issues
BufferedLogs Off

# Use the OS's abilities to speed up memory access and file reading
# These settings are OFF to improve stability during concurrent and peak loads
# Note - EnableSendfile should be Off if a website's DocumentRoot is a network mounted location
# Note - EnableSendfile is set to Off under the default configuration of Apache 2.4
EnableMMAP Off
EnableSendfile Off

# Fixes issues but does disable a faster way of accepting network connections on Windows
# Implemented for the following known issues -
# A) The network layer (winsock) is often broken due to network, firewall, anti-virus, etc, software (s/w that adds its own filters to winsock)
# B) Apache 2.4 is being used (general issue on Windows with 2.4?...)
# C) Some requests do not start/complete (initial req is broken but sequential reqs, when performed within a 3-second window, complete)
<IfVersion < 2.3>
Win32DisableAcceptEx
</IfVersion>
<IfVersion >= 2.3.3>
AcceptFilter http none
AcceptFilter https none
</IfVersion>

PHP (for crashes):
C:\WampDeveloper\Config\Php\php.ini

; Determines the size of the realpath cache to be used by PHP. This value should
; be increased on systems where PHP opens many files to reflect the quantity of
; the file operations performed.
; http://php.net/realpath-cache-size
;realpath_cache_size = 16k
realpath_cache_size = 1M

For stability, also make sure to test both PHP and PHP-FCGI. The difference is PHP (mod_php) runs inside of Apache, PHP-FCGI (separate process via mod_fcgid) runs outside of Apache. PHP-FCGI might be more stable under some circumstances, and more fickle under others.

Performance Gains

For top performance gains use -

1. Apache’s mod_cache module to cache page requests/results. This will produce 5-10x the performance gains over all other methods combined.

2. PHP’s Zend OPcache extension to cache PHP scripts as compiled objects. This will produce a 3-5x Requests Per Second speed up.

3. memcached + php_memcache setup to cache PHP script’s or web-app’s internal data and results. This can produce a good 50%-100% performance gain.

4. Cache plugins and/or setting adjustments specific to the web-app: Cache plugins for WordPress, Speedup tips for PrestaShop, etc.

5. mod_expires to make the client’s (visitor’s) Browser cache pages and page assets for a given time, instead of re-getting those pages and assets on each page load.

* Some of these are more difficult to configure and set up than others.

Also, in my experience, the switch from 32 bit to 64 bit Apache, PHP, and MySQL versions only provides limited/marginal performance gains (and in some cases it’s even negative).

To sum everything up, 99% of all performance gains will come from utilizing Apache’s caching mechanisms (via mod_cache), using PHP Zend OPcache (extension), and afterwards (once the bottleneck is moved from Apache with PHP to MySQL), improving MySQL performance by tuning my.ini settings, and optimizing/restructuring MySQL queries by utilizing MySQL’s Slow Query log (to see what the problem is).

Having said that, there are also performance robing issues that can exist on the OS, in the Apache/MySQL/PHP settings, and even the client’s Browser, that are covered here -
http://www.devside.net/wamp-server/wamp-is-running-very-slow

Setting File Permissions with chmod on Windows for Apache and PHP

Oftentimes this question comes up for WAMP -

How do I chmod 777 (change) filesystem permissions for Apache and PHP to be able to read/write this file/folder on Windows?

The simple answer is you don’t, and you don’t need to. And here is why…

Apache already has all the permissions it needs, as it runs under the LocalSystem account on Windows, which has extensive read/write access to local paths. This is inherited by PHP.

For example, when you are using WordPress to upload a file (and already have the wp-content\uploads folder created), WP already has the needed permissions to be able to create a new sub-folder for the year + month in the uploads folder, and move that file in from the temporary folder. No file permission changes are needed. No php.ini edits are needed. No WP settings changes are needed.

If there is a problem with the above example -

  • The additional file permissions that have been set up afterwards are at fault (check Windows Event viewer).
  • Settings have been wrongly edited: WP upload path settings, php.ini temp folder location + upload settings, etc.
  • The Apache Service ‘Log On’ account has been switched from “LocalSystem” to something else (check Service’s Properties).
  • Or there are internal PHP errors (check the website’s HTTP and PHP error logs).

If you really really need to run chmod (read/write permissions) and chown (ownership) for some reason, there are some Windows equivalents and ports of these Linux commands that you can download, that just take the number, re-interpret it, and then use Windows native methods and commands to set the permissions…

http://gnuwin32.sourceforge.net/packages/coreutils.htm

But Apache, for the most part, already has *full* read and write permissions in the WAMP folder, so there is nothing that needs changing, unless you are trying to set lesser permissions.

You can even use a PHP script to do this, as PHP has chmod() and chown() functions…

http://php.net/manual/en/function.chmod.php

Aside form that, to set file-permissions under Windows, using Windows native ways, you can right-click any folder or file, go to Properties, Security, and set the permissions there. Or use any number of command-line utilities…

http://superuser.com/questions/106181/equivalent-of-chmod-to-change-file-permissions-in-windows

Setting MySQL Root Password

To set MySQL’s root account password -

Login to phpMyAdmin

http://127.0.0.1/phpmyadmin

Use username ‘root’ and do not enter anything for the password.

Username: root
Password:

Update Root Password

Go into phpMyAdmin’s Users Tab.

There are 3 root accounts… One for each loopback IP (IPv4′s ’127.0.0.1′ and IPv6′s ‘::1′), and one for host-name ‘localhost’.

  • root@127.0.0.1
  • root@::1
  • root@localhost

This represents the same account, the difference is the IP address and/or Host-name it’s accessed from.

Click the ‘Edit Privileges’ link that’s to the right of each account for the above.

In the ‘Change password’ Group, only fill in the Password box (and “Re-type” box), and then in that same Group click ‘Go’. Don’t change anything else.

Do this for all 3 root accounts, making sure that -
1) the password is the same in each account
2) the password only contains letters and numbers (don’t use any special characters like ‘&’ as they can later cause issues)

WampDeveloper

To let WampDeveloper know what the root password is (so WebApps Tab can install webapps) -

Once you’ve set root’s password, open file C:\WampDeveloper\WampDeveloper.xml with a simple editor like Notepad (and not a special XML editor), by right-clicking this file and selecting ‘Open With -> Notepad’, and near the bottom find these lines and fill in the password…

...
<values>
  <key name="dbUsername">root</key>
  <key name="dbPassword">fill-in-root-password-here</key>
...

Save file. Restart WampDeveloper.

If the password contains special XML characters (", &, ‘, <, >, etc), enclose that password string within “<![CDATA[string]]>“…

...
  <key name="dbPassword"><![CDATA[fill-in-root-password-here]]></key>
  ...
...

* Fancy XML editors can re-structure this file and mess it up; and since it’s ultimately just a text file, editing with Notepad is perfectly fine for this.

Blocking Download Managers and Accelerators

Some users like to use Download Managers & Accelerators in an attempt to complete file downloads faster.

These download managers/accelerators work by creating dozens to hundreds (and sometimes thousands) of independent concurrent and sequential connections, with each connection downloading a different part (byte range) of the same file.

The client sends a request with a “Range” Header specifying the part of the file it wants, and the server returns that part of the file back to the client using the HTTP 206 (“Partial Content”) Response.

This type of download abuse can easily overload your server’s connection limits and resources, and also get around any per-connection bandwidth restrictions you might have set.

Here is how to stop these Download Managers dead in their tracks by using mod_headers and mod_rewrite under Apache (or a WAMP Server such as WampDeveloper Pro).

This example will abort all partial requests for content located within URL:

http://www.example.com/files/

Unset Accept-Ranges Header

Indicate to the clients that the server will not attempt to honor Range requests (partial content requests), by changing Response Header “Accept-Ranges” from “bytes” to “none“.

<IfModule !mod_headers.c>
    LoadModule headers_module modules/mod_headers.so
</IfModule>

<Location /files/>
    <IfModule mod_headers.c>
        Header set Accept-Ranges none
    </IfModule>
</Location>

But this is only a superficial message to the client, that the download manager/accelerator software can easily ignore…

The client is still able to send “Range” requests (partial content requests), and Apache will still return the requested byte range of the file. So let’s remove that option once and for all…

Abort All Range (Partial Content) Requests

<IfModule !mod_rewrite.c>
    LoadModule rewrite_module modules/mod_rewrite.so
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On

    # Detect URL /files/...
    RewriteCond %{REQUEST_URI} ^files/
    # Detect "Range" request header
    RewriteCond %{HTTP:Range} !^$
    # Stop and Return HTTP FORBIDDEN (403) response header
    RewriteRule .* - [F,L]
</IfModule>

* If instead of placing this inside a VirtualHost block, you place it in an .htaccess file, then “AllowOverride FileInfo” (or “AllowOverride All“) and “Options +FollowSymLinks” (or “Options All“) have to be set (in the VirtualHost) for the directory the .htaccess file is in (otherwise neither mod_rewrite, nor working with the Header data, will work).

* Don’t use “RequestHeader unset Range” as this will get around the mod_rewrite configuration while turning all partial content downloads into full size downloads.

Problems

Incomplete downloads are not resumable… A client will not be able to pause or stop a download, and later resume it.

Downloads started with download accelerators will stop at whatever % of full file size the first connection retrieves.

May also break some -

  • Clients that do streaming of video and audio
  • Clients that do reading/loading of meta-data from large files
  • e-Readers
  • Client-side bandwidth throttling

Notes on using mod_rewrite

Per-directory Rewrites

http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriterule

For mod_rewrite, “Options FollowSymLinks” must be enabled for anything related to directories to work…

To enable the rewrite engine in this context, you need to set “RewriteEngine On” and “Options FollowSymLinks” must be enabled. If your administrator has disabled override of FollowSymLinks for a user’s directory, then you cannot use the rewrite engine. This restriction is required for security reasons.

Behavior of mod_rewrite in <Location> sections can be unpredictable…

Although rewrite rules are syntactically permitted in <Location> and <Files> sections, this should never be necessary and is unsupported.