How to install a LAMP stack in Windows 10 WSL.

The days of running a LAMP stack on Windows with XAMPP and virtual machines are gone. Nothing wrong with those solutions, but in WSL apache2 can runs natively, no hogging resources by a virtual machine, and no hacks to get PHP running smoothly (ok, that's actually one thing wrong with XAMPP).

We'll install:

...and fix a couple common issues.

  • Install WSL Ubuntu in Windows 10
  • Make sure it's up-to-date by running:
    sudo apt update && sudo apt upgrade

Install apache2

This one is easy, just run:

sudo apt install apache2

You can now start the apache server:

sudo service apache2 start

You might see a warning: Protocol not available: AH00076: Failed to enable APR_TCP_DEFER_ACCEPT. To fix, add this to /etc/apache2/apache2.conf:

# fix error in WSL (Protocol not available: AH00076: Failed to enable APR_TCP_DEFER_ACCEPT)
AcceptFilter http none
AcceptFilter https none

You'll probably want apache2's rewrite module enabled:

sudo a2enmod rewrite
sudo service apache2 restart

The default page when accessing http://localhost from a browser should look like this:


Install mysql server

Install mysql by running:

sudo apt install mysql-server

During the installation, you'll be asked to set the root password for mysql. You want to set a password, otherwise it will be randomly generated:


The mysql user folder is not set correctly by default and the server will complain about it when started (No directory, logging in with HOME=/). To fix, change the mysql user's home directory to /var/lib/mysql:

sudo usermod -d /var/lib/mysql mysql

Start the mysql server:

sudo service mysql start

Install php

Run this command to install php, the apache2 php module and some necessary libraries:

sudo apt install libapache2-mod-php php php-curl php-gd php-mbstring php-mcrypt php-mysql php-xml php-zip

Increase the php module's maximum allowed upload size in php.ini. For php7.0 the file to edit is /etc/php/7.0/apache2/php.ini. Search for the following line and change the value to whatever works for you (I set it to 16M that so I can upload database dumps in phpmyadmin):

upload_max_filesize = 16M

Enable the mcrypt and mbstring php modules:

sudo phpenmod mcrypt
sudo phpenmod mbstring

Move the www folder to a Windows drive and test things out

It's not advised to keep work files under WSL, so let's move apache2's www folder to a Windows drive. I made a folder on the C: drive where all my web projects will live: C:\Projects\www. To point apache2 to this folder, edit /etc/apache2/apache2.conf and add a <Directory> section:

<Directory /mnt/c/Projects/www>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted

Note: AllowOverride All enables .htaccess file processing under this folder. If you don't want to do that, change the value to None.

We can store multiple virtual sites in C:\Projects\www. Let's make a folder here for the default site: C:\Projects\www\default. To point the default virtual site configuration to this folder, we'll update the DocumentRoot setting in /etc/apache2/sites-enabled/000-default.conf:

DocumentRoot /mnt/c/Projects/www/default

Make a simple index.html in C:\Projects\www\default:

<h2>Hello Default Site!</h2>

Tell apache2 to reload the configuration files:

sudo service apache2 reload

Our awesome new website should show up at http://localhost now:


Let's make another virtual site on a different port. First we'll make a copy of the default site's configuration and symlink it to the sites-available folder:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/001-test.conf
sudo ln -s /etc/apache2/sites-available/001-test.conf /etc/apache2/sites-enabled

This site will work on port 8001. By default apache2 only listens on port 80, so we need to add a Listen directive to /etc/apache2/sites-enabled/001-test.conf. We'll also update the DocumentRoot setting to point to C:\Projects\www\test (there are 3 modifications, marked by red arrows):


This a good excuse to test our php installation with phpinfo(). Create the C:\Projects\www\test folder and make a file in it called index.php:


// Show all information, defaults to INFO_ALL

// Show just the module information.
// phpinfo(8) yields identical results.


Reload the apache2 config:

sudo service apache2 reload

The new test site should show the output of phpinfo() at http://localhost:8001:


To remove the virtual site, delete 001-test.conf from /etc/apache2/sites-available and /etc/apache2/sites-enabled.

Install phpMyAdmin

Lastly let's make out life easier by adding phpMyAdmin to our setup. There is an Ubuntu package for it. Make sure mysql-server is running, then install it:

sudo service mysql start
sudo apt install phpmyadmin

The installer will ask several question. Make sure apache2 is selected for configuration:


Answer Yes to configure the database:


Set a password for the phpmyadmin user:


If there is an error during setup (most likely because the mysql service was not running), you can run the configuration step again with:

sudo dpkg-reconfigure -plow phpmyadmin

Let's add the phpMyAdmin configuration to apache2. Edit /etc/apache2/apache2.conf and add the following line at the bottom:

Include /etc/phpmyadmin/apache.conf

Should look something like this:


Reload the apache2 config:

sudo service apache2 reload

You should have phpMyAdmin working at http://localhost/phpmyadmin. For full access to the database login as root with the password you set during mysql installation.


One last, optional step: since this is a local development environment, we probably don't want to keep logging in to phpMyAdmin every time. The easiest way to do this is to have phpMyAdmin default to the root user (this involves adding the mysql root password as plain text to the config file, don't do this on a production server;).

Edit /etc/phpmyadmin/, and search for "Authentication type". Comment out this line:

//    $cfg['Servers'][$i]['auth_type'] = 'cookie';

Add these lines below, replacing YOUR_PASSWORD with your password:

$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['username'] = 'root';
$cfg['Servers'][$i]['password'] = 'YOUR_PASSWORD';

It will look something like this:


And that's it! A LAMP stack running natively in Windows 10 WSL.

Note: The server won't start automatically. To start from a bash shell:

sudo service apache2 start
sudo service mysql start

Add a comment

Next Post Previous Post