Get in touch!Get in touch!

Installing and Configuring Apache, PHP & MySQL on Cygwin

I had a hard time setting up Apache, PHP and MySQL to work in a Cygwin Environment. At first, I thought it would be as easy as installing any other Cygwin package. However, when I searched for PHP from the official Cygwin mirrors via setup.exe, I couldn’t find it. So I scratched my head, did some searching on Google, and I learnt about the Cygwin Ports Project, which I found to be interesting. I decided to document the entire process for future reference.

Installing Cygwin, Apache & MySQL

»Download the setup.exe and run it as Administrator

Run setup.exe as Administrator

»You can see from below that I was using setup.exe v 2.774. Click Next to continue

The version of setup.exe I used was 2.774


»Choose The Installation Type.

Choose The Installation Type


»Choose the Installation Directory. The Default is C:cygwin. Don’t choose a location that contains spaces anywhere in its path name.

Choose the Installation Directory


»Choose the Local Package Directory, where Cygwin will store the downloaded installation files .

Select the Local Package Directory


»Select your internet connection type

Select your internet connection type


»Select a Download Mirror. I read somewhere that the xmission mirror was faster

Choose Download Site(s)


Cygwin Setup…


Observe the Setup Alert


»Select the packages you want to install. At this stage, the default install will do, plus a few other packages, namely

  • gawk,
  • tar,
  • bzip2,
  • wget,
  • subversion,
  • mail,
  • sSMTP,
  • util-linux,
  • ncurses,
  • openSSH,
  • cygrunsrv,
  • apache2
  • and MySQL 

Note that the first three in the above list (gawk, tar & bzip2) are part of the default install – I’m mentioning them because they in conjuction with wget are needed for us to use a package called apt-cyg , as we shall see later on.

Selecting apache2 package


Selecting MySQL package

Package Selection – util-linux


Package Selection – mail


Package Selection – openSSH


Package Selection – sSMTP

Once you select your packages, click on Next, and you will informed of any dependencies, which Cygwin will automatically resolve if the checkbox is selected…

Resolving Dependencies


Cygwin Setup – Package Download & Installation in Progress


Installation Complete – the easiest part is done! :-)


Installing PHP

»Launch Cygwin terminal as Administrator

Open Cygwin Terminal by Running as Admininistrator


»At first run, you will see the following in the terminal:

Copying skeleton files. 
These files are for the users to personalise their cygwin experience.

They will never be overwritten nor automatically updated.

`./.bashrc' -> `/home/USER//.bashrc'
`./.bash_profile' -> `/home/USER//.bash_profile'
`./.inputrc' -> `/home/USER//.inputrc'
`./.profile' -> `/home/USER//.profile'



»Launch the Cygwin Setup with the k- flag as follows:

cygstart -- /path/to/setup.exe -K

where path/to/setup.exe is the location of the ,setup.exe that you downloaded earlier. In my case, the setup.exe was located at /cygdrive/d/cygwin/setup.exe.
The Cygwin Setup will launch, then proceed as per instructions from the Cygwin Ports Project Homepage:

  • On Choose Installation Type page, select “Install from Internet”.
  • On Choose Download Site(s) page, select a distro mirror (we use the same xmission mirror we used earlier), then enter in the User URL field and press Add (making sure that both are highlighted).
  • Proceed with package selection and installation, making sure to install any indicated dependencies.

However, when I entered the URL according to the above instructions, setup would get stuck at the point shown in the screenshot below.

when I entered the URL according to the official instructions, setup would get stuck at this point

Therefore, I followed the advice to use a mirror, and I picked on after encountering a similar problem with several other mirrors.

I expected to find PHP in the package list, but to my dismay – my search returned no results. I don’t know where I went wrong, all tutorials I read indicated success at this stage, but it didn’t work for me:

where is PHP? Did I miss something here?

After a lot of fidgeting coupled with painstaking Googling, I came across apt-cyg, a very useful tool, which, I installed by entering the following in the Cygwin terminal:


  $ svn --force export /bin/
  $ chmod +x /bin/apt-cyg
  $ svn --force export /bin/
  $ chmod +x /bin/apt-cyg


Then, I installed PHP using:

apt-cyg -m install php

Boom! php is installed! way to go :-)

In a similar fashion, I installed several other PHP packages, getting package names from the package list at Examples of important packages to install when working with PHP are:

  • apache2-mod_php5
  • php-mysql
  • php-mysqli
  • php-PEAR
  • ...there are so many of them...


Configuring Servers

»During the course of working with Cygwin, the following message would pop up now and again:

warning: setlocale: LC_CTYPE: cannot change locale (UTF-8)

This can be fixed by adding the following to your ~/.bash_profile:

export LC_CTYPE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
export LC_CTYPE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

»Now Let us configure cygserver by running


Here is the output:

$ /usr/bin/cygserver-config
Generating /etc/cygserver.conf file

Warning: The following function requires administrator privileges!

Do you want to install cygserver as service?
(Say "no" if it's already installed as service) (yes/no) yes

The service has been installed under LocalSystem account.
To start it, call `net start cygserver' or `cygrunsrv -S cygserver'.

Further configuration options are available by editing the configuration
file /etc/cygserver.conf.  Please read the inline information in that
file carefully. The best option for the start is to just leave it alone.

Basic Cygserver configuration finished. Have fun!


»Then Start Cygserver service by

cygrunsrv -S cygserver


»Next I setup SSH as follows:


Here is the output:

$ ssh-host-config

*** Info: Generating /etc/ssh_host_key
*** Info: Generating /etc/ssh_host_rsa_key
*** Info: Generating /etc/ssh_host_dsa_key
*** Info: Generating /etc/ssh_host_ecdsa_key
*** Info: Creating default /etc/ssh_config file
*** Info: Creating default /etc/sshd_config file
*** Info: Privilege separation is set to yes by default since OpenSSH 3.3.
*** Info: However, this requires a non-privileged account called 'sshd'.
*** Info: For more info on privilege separation read /usr/share/doc/openssh/README.privsep.
*** Query: Should privilege separation be used? (yes/no) yes
*** Info: Note that creating a new user requires that the current account have
*** Info: Administrator privileges.  Should this script attempt to create a
*** Query: new local account 'sshd'? (yes/no)
*** Query: new local account 'sshd'? (yes/no) yes
*** Info: Updating /etc/sshd_config file

*** Query: Do you want to install sshd as a service?
*** Query: (Say "no" if it is already installed as a service) (yes/no) yes
*** Query: Enter the value of CYGWIN for the daemon: [] ntsec
*** Info: On Windows Server 2003, Windows Vista, and above, the
*** Info: SYSTEM account cannot setuid to other users -- a capability
*** Info: sshd requires.  You need to have or to create a privileged
*** Info: account.  This script will help you do so.

*** Info: You appear to be running Windows XP 64bit, Windows 2003 Server,
*** Info: or later.  On these systems, it's not possible to use the LocalSystem
*** Info: account for services that can change the user id without an
*** Info: explicit password (such as passwordless logins [e.g. public key
*** Info: authentication] via sshd).

*** Info: If you want to enable that functionality, it's required to create
*** Info: a new account with special privileges (unless a similar account
*** Info: already exists). This account is then used to run these special
*** Info: servers.

*** Info: Note that creating a new user requires that the current account
*** Info: have Administrator privileges itself.

*** Info: No privileged account could be found.

*** Info: This script plans to use 'cyg_server'.
*** Info: 'cyg_server' will only be used by registered services.
*** Query: Do you want to use a different name? (yes/no) no
*** Query: Create new privileged user account 'cyg_server'? (yes/no) yes
*** Info: Please enter a password for new user cyg_server.  Please be sure
*** Info: that this password matches the password rules given on your system.
*** Info: Entering no password will exit the configuration.
*** Query: Please enter the password:
*** Query: Reenter:

*** Info: User 'cyg_server' has been created with password 'password'.
*** Info: If you change the password, please remember also to change the
*** Info: password for the installed services which use (or will soon use)
*** Info: the 'cyg_server' account.

*** Info: Also keep in mind that the user 'cyg_server' needs read permissions
*** Info: on all users' relevant files for the services running as 'cyg_server'.
*** Info: In particular, for the sshd server all users' .ssh/authorized_keys
*** Info: files must have appropriate permissions to allow public key
*** Info: authentication. (Re-)running ssh-user-config for each user will set
*** Info: these permissions correctly. [Similar restrictions apply, for
*** Info: instance, for .rhosts files if the rshd server is running, etc].

*** Info: The sshd service has been installed under the 'cyg_server'
*** Info: account.  To start the service now, call `net start sshd' or
*** Info: `cygrunsrv -S sshd'.  Otherwise, it will start automatically
*** Info: after the next reboot.

*** Info: Host configuration finished. Have fun!


»Start the openSSH server via

cygrunsrv -S sshd


»View Running Services:

Launch Microsoft Windows’ services.msc


Confirmation that the daemons we launched are running


»Now we configure the apache2 Web server via


Here’s the output:

$ /usr/sbin/httpd2-config

*** Warning: The following function requires administrator privileges!
*** Query: Do you want to install httpd2 as service? (yes/no) yes

*** Info: The httpd2 service has been installed under the LocalSystem
*** Info: account (also known as SYSTEM). To start the service now, call
*** Info: `net start httpd2' or `cygrunsrv -S httpd2'. Otherwise, it
*** Info: will start automatically after the next reboot.

*** Info: Check /etc/apache2/httpd.conf first, if it suits your needs.

Configuration finished. Have fun!


»Start the apache2 web server as per instructions in the above output, then refresh services.msc and voila! — apache2 web server is running!

Apache2 daemon running successfully


»Let’s test our apache2 server by opening localhost on our browser:

Apache Installed Successfully – It Works! Yay :-)


»Let’s test our PHP installation by creating a test.php file with the following code and placing it in /srv/www/htdocs/.

<?php phpinfo(); ?>
<?php phpinfo(); ?>

Open http://localhost/test.php in your web browser:

PHP is working! yay! :-)

»It is worth noting that although things seem to be working well at this point, there’s still some work that needs to be done with regard to the apache2 server — to ensure that it behaves appropriately. I followed the instructions at The file to edit is /usr/local/apache/conf/httpd.conf. Add the following directives (if already there, verify they are correct):

# Make sure there's only **1** line for each of these 2 directives:
# Use for PHP 4.x:
#LoadModule php4_module	modules/
#AddHandler php-script	.php

# Use for PHP 5.x:
LoadModule php5_module	modules/
AddHandler php5-script	.php 

# Add index.php to your DirectoryIndex line:
DirectoryIndex index.html index.php

AddType text/html	.php

# PHP Syntax Coloring
# (optional but useful for reading PHP source for debugging):
AddType application/x-httpd-php-source phps

Set allowOverride to All for Permalinks to work well in WordPress , courtesy of this link, where it was stated that


If you’re doing this all via localhost, then you probably just need to tweak your httpd.conf file and set AllowOverride to All. There was another fellow with the same issue just yesterday.

The permalink settings are stored in the database and WP dynamically generates the page using the .htaccess and database.



# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
AllowOverride All

Then restart the apache2 web server to load the new changes.


Note: I could have done this before even starting the apache2 server, but I only knew this after I had already configured it (I encountered some problems while working with Permalinks in WordPress). Nevertheless, all you need to do is restart the Apache web server after making changes to the httpd.conf file.


Configuring MySQL

»We begin by entering the following at the Cygwin prompt:


This prepares mySQL on the system; creates a database called "test". The user is "root" and the password is "". The output is as follows:

$ mysql_install_db
Installing MySQL system tables...
Filling help tables...

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

To do so, start the server, then issue the following commands:

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h USER-PC password 'new-password'

Alternatively you can run:

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &

You can test the MySQL daemon with
cd /usr/mysql-test ; perl

Please report any problems with the /usr/bin/mysqlbug script!


»I secured the mySQL installation via


The output is as follows:

$ mysql_secure_installation


In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Set root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
ERROR 1008 (HY000) at line 1: Can't drop database 'test'; database doesn't exist
 ... Failed!  Not critical, keep moving...
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

»Create a new mySQL database. I didn’t know how to do this via the command-line, so I followed the instructions at and These two articles helped me out a lot.

The page at was also helpful, because I remember messing up the database & I had to drop it and create another one.

If you want to change the mySQL root password, run the following command:

mysqladmin -u root password "old-password" "new-password"

»Next, we launch the MySQL daemon via

/usr/bin/mysqld_safe &

the output is as follows:

USER@USER-PC /srv/www/htdocs
$ mysqld_safe &
[1] 6664

USER@USER-PC /srv/www/htdocs
$ 121105 07:22:38 mysqld_safe Logging to '/var/lib/mysql/Victor-PC.err'.
chown: invalid user: `mysql'
121105 07:22:39 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql

Starting mySQL daemon: Windows Security Alert


Configuring sendmail

»First we configure the sSMTP package we installed at the beginning:


You will be led through a simple wizard that will help you onfigure sSMTP. Here is my ssmtp.conf (located in /etc/ssmtp/) file after configuration:

# /etc/ssmtp/ssmtp.conf -- a config file for sSMTP sendmail.


# Configure sSMTP in Six Easy Steps (or so)
# (1) mailhub
# This is the computer responsible for handling your outgoing mail.
# It could be the SMTP server of your ISP, or a departmental mailhub.
# Use the fully-qualified domain name ( of the mailhub;
# if it uses an unusual SMTP port number, use the colon syntax
# Otherwise sSMTP will use the standard SMTP port number (25).
# (Note that sSMTP can support a user-dependent mailhub with the
# 'reverse aliases' feature, for which see the man page.)
# (2) FromLineOverride
# This specifies how sSMTP handles the From: line of outgoing mail.
# If FromLineOverride=YES, sSMTP will leave the From: line alone if
# it already exists.  If FromLineOverride has any other value, or
# there is no From: line, sSMTP creates the From: line using your
# username (or the -f command-line option), and the value of the
# rewriteDomain option (step (4), below).
#     If you use a mail user agent (MUA; e.g. mutt, pine) I recommend
# using YES and having the MUA set the From: line.  (Exception: the
# 'reverse aliases' feature can be used to set up a particular From:
# address for each user, in which case don't use FromLineOverride=YES.
# See the man page.)
# (3) hostname
# sSMTP uses the hostname of your computer to identify itself to the
# mailhub, and in the Received: headers of the outgoing mail.  This
# has relatively little effect on how the mail is handled.
#     Use the fully-qualified domain name (FQDN) of your computer
# (  If it doesn't have a FQDN, use some name for your box.
# (4) rewriteDomain
# Please enter the mail name of your system.
# sSMTP uses this value to add a domain to unqualified e-mail addresses
# (addresses without an @-sign).
#     You probably want to use the domain from your own e-mail address.
# You probably want to set up your MUA to handle unqualified addresses
# itself, in which case sSMTP will never have to use this.  (Users of
# cron note that cron always uses unqualified addresses.)
# (5) root
# If sSMTP finds an unqualified e-mail address among
# the recipients, and it corresponds to a username on your local
# machine with a userid less than 1000, then the e-mail is sent to
# this value instead.  The idea is that mail sent to 'root' should
# probably go to 'postmaster' instead.
#     If you set up your MUA to do its own handling of unqualified
# addresses, this is irrelevant.  (But note that cron does use
# unqualified addresses corresponding to local usernames.)
# Use your own e-mail address unless you know a better postmaster.
# (6) link /usr/sbin/sendmail to /usr/sbin/ssmtp?
# Some programs (e.g. cron) expect /usr/sbin/sendmail to handle mail.
# You may wish to ensure that it is a symbolic link to /usr/sbin/ssmtp.
# (7) Miscellaneous SSL/TLS configuration
# Use SSL/TLS to send secure messages to server.
# Use SSL/TLS certificate to authenticate against smtp host.
#	UseTLSCert=YES
# Use this RSA certificate.
#	TLSCert=/etc/ssl/certs/ssmtp.pem
# (8) Debugging
# Get enhanced (*really* enhanced) debugging information in the logs
# If you want to have debugging of the config file parsing, move this option
# to the top of the config file and uncomment
#	Debug=YES

»Then we configure email.conf in /etc/email/ to match ssmtp settings. A very important entry in the email.conf file is:

SENDMAIL_BIN = '/usr/lib/sendmail -t -i'

The above is the default setting (the path to sendmail is wrong), change it to:

SENDMAIL_BIN = '/usr/sbin/sendmail -t -i'

Other important Settings are:

MY_NAME  = 'My Name'
#REPLY_TO = ''

The following links were very helpful; they contain guidance on setting up the sSMTP package:

Note[1]: See for guidance on using special characters in passwords.

Note[2]: I found Mutt to be interesting — check it out:

»Having configured sendmail on our Cygwin Installation, let us see if it works. I created a mail-test.php file and placed it in the /srv/www/htdocs/ folder. Here’s the code:

 $to = "";
 $subject = "PHP sendmail";
 $body = "This is a simple test email";
 $from = "From: Foo Bar <>";
 if (mail($to, $subject, $body, $from)) {
   echo("<p>Message successfully sent!</p>");
  } else {
   echo("<p>Message delivery failed...</p>");
 $to = "";
 $subject = "PHP sendmail";
 $body = "This is a simple test email";
 $from = "From: Foo Bar <>";
 if (mail($to, $subject, $body, $from)) {
   echo("<p>Message successfully sent!</p>");
  } else {
   echo("<p>Message delivery failed...</p>");

Open your web browser and navigate to http://localhost/mail-test.php and you should see the following:

Sendmail working!


Putting it all together

To determine whether Apache, mySQL and PHP (AMP) were all working properly, I installed WordPress, which requires the services of these three amigos!

Installing WordPress


WordPress Successfully Installed!


WordPress Working: I guess this means that we have properly setup PHP, mySQL & Apache on our system! yay! :-)


Note: If you encounter an error of the form unable to remap xxx to same address as parent, which I encountered at some point, check out this page for the solution, which worked for me! I got the problem as I was trying to setup phpMyAdmin.


Concluding Remarks

So, this is how I setup Apache, mySQL and PHP on my Cygwin system. What are your thoughts? Is there a step I missed? Is there something wrong somewhere? Do you have better ways of doing certain things, like configuring Sendmail? If you are attempting to follow the procedures laid out in this post, what are your experiences? What problems are you encountering? Please write your comments below. Thank you for reading my post.


References (util-linux package for whereis and more)

19 comments on Installing and Configuring Apache, PHP & MySQL on Cygwin

  1. Victor
    whall March 14th, 2013

    Great post – it was very helpful for the mysql part. As a long time cygwin advocate and perl hacker, I needed to go to the next step, which is to actually use a database for some scripts. I’d prefer to use a local copy of mysql on cygwin instead of a VM of a LAMP server, and this did the trick.

    • Victor
      victor March 15th, 2013

      Thanks for reading my post and for the kind words. I’m glad you were able to get things working!

  2. Victor
    Andres March 24th, 2013

    Exactly what I needed, thanks for the information!

    Bookmarking… now!

  3. Victor
    Bothwell March 26th, 2013

    Thanks Victor… It was very useful for setting up Apache just what I needed

  4. Victor
    Tunde April 4th, 2013

    Excellent post! Very detailed.

  5. Victor
    Ferry May 7th, 2013

    Thanks for this great and usefull tutorial!

  6. Victor
    Mel May 19th, 2013

    I’m getting the following error when I try to set up the apache service, and afterwards pointing my browser to localhost shows an error page:

  7. Victor
    prometheus May 22nd, 2013

    for me, adding
    “LoadModule php5_module lib/apache/”
    worked for me instead of libphp5.dll, otherwise the apache2 would not run and phpinfo () did not work. No other website mentions this. Once I get my website setup, I will post this.

  8. Victor
    Ethan M May 22nd, 2013


  9. Victor
    homer June 20th, 2013

    thanks,excellent post!

    but i get a problem. i have installed all the stuff as your post and worked perfectly, but when i want to install a php redis extension, there is no such extension on the port list. so i just download the dll file and put it into the extensions’ directory. then i run php command on the cygwin and get this warning:

    PHP Warning: PHP Startup: Unable to load dynamic library ‘/usr/lib/php/20100525/php_redis.dll’ – No such file or directory in Unknown on line 0

    I can make sure that the dll file is existed and i also tried both of the thread-safe and non-thread-safe version. I cannot figure out what’s the problem, so can you give me some advice, thanks!

    • Victor
      victor June 27th, 2013

      Thank for reading my post, I’m happy to hear that the things contained herein worked for you.
      However, with regards to deal long with the dll files, I believe that the message you used cannot work, because those dll files were not compiled for Cygwin, but for Windows, and besides, I believe cygwin doesn’t work like that. I’m sorry I don’t know how to solve this one, have you tried searching the web?

  10. Victor
    wiel July 17th, 2013

    apt-cyg -m install php-session

    run this if youre getting session errors like i was

  11. Victor
    Alvin June 27th, 2015

    Here are some comment.
    1. When using the subversion it requires me to change the ‘md5′ to sha512
    2. I had to install all php, mysql,mysqld package for it to work , i not necessary had to install anything apache related. I just have to use php -S to start the server.

    • Victor
      Victor June 29th, 2015

      Many thanks for your heads up @Alvin. I have noticed that the cygwin repositories actually have PHP at the time of your comment. I might have to update this article to reflect such changes.

Leave a Reply