Install and configure a fully functional web server on WSL 2
Prerequisites
We assume that the linux subsystem is already activated. If you haven't already, follow the tutorial here.
For this example, we'll be using Ubuntu 20.04 LTS.
Update the distribution
In order to have the latest versions of the various libraries pre-installed, we will need to update
the libraries.
sudo apt update
Then we will perform an upgrade
of the libraries.
sudo apt upgrade
This last command may take a few minutes depending on your internet connection.
Install the necessary libraries
We will then install Apache, MySQL and PHP In order to create the basic structure of the LAMP stack (Linux, Apache, MySQL, PHP).
sudo apt-get install apache2 php7.4 libapache2-mod-php7.4 mysql-server php7.4-mysql
Here we have specified the PHP version we wanted to use. Here version 7.4.
We are also going to need to install some very common modules.
sudo apt-get install php-curl php-gd php-intl php-json php-mbstring php-xml
At the end of this step, we have: Apache as well as MySQL installed on the Linux subsystem. All that remains is to configure everything.
First of all, we will stop the apache2 and mysql services.
sudo service apache2 stop
sudo service mysql stop
We are now going to prevent these two services from starting automatically.
sudo systemctl disable apache2
sudo systemctl disable mysql
Installation of a graphical interface for the database
In order to facilitate the management of the database, it may be convenient to install a database management interface. If you are already using database management tools such as TablePlus or HeidiSQL, you will not need to perform this step.
Let's start by installing the adminer library.
sudo apt-get install adminer
Adminer is a small, very simple and very light interface for managing databases. It is written in PHP. We prefer to use Adminer rather than other solutions like phpMyAdmin because it is much lighter.
We can now configure the url that will be used to access the admin interface.
echo "Alias /adminer.php /usr/share/adminer/adminer.php" | sudo tee /etc/apache2/conf-available/adminer.conf
All that remains is to activate this new apache configuration.
sudo a2enconf adminer.conf
Then to restart the apache2
service.
sudo service apache2 restart
In this way, by going to the url localhost/adminer.php
, you will be on the admin interface.
MySQL configuration
It's all very well to have an interface for database management, but if we don't have any databases, it's useless.
So we'll have to create a user
to access the database.
Indeed, since Ubuntu 18.04, the connection with the
root
user is only possible with the use of the commandsudo
. We must therefore create a user to avoid this restriction.
To do this, we first need to start the mysql
service.
sudo service mysql start
It is possible that when you start the
mysql
service, the terminal returns[failed]
. To resolve this, try running the commandsudo usermod -d /var/lib/mysql/ mysql
. If this still doesn't work, perform ashutdown
of WSL 2 with the commandwsl.exe --shutdown
directly in the WSL terminal. Once done, restart the terminal and then run the commandsudo service mysql start
again. If this still doesn't work, stop the Apache service, then try starting MySQL and then Apache.
Then we will use the MySQL command lines.
sudo mysql
To create a user, simply enter the following command.
CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
user
will be the name of the new user. localhost
is the host that the user will be able to connect to. Finally, password
is the password for this new user. Of course, you can use a different username and password than the one shown in this demonstration.
We then need to add permissions to this user.
GRANT ALL PRIVILEGES ON * . * TO 'user'@'localhost';
Here ALL PRIVILEGES
means that we want to give this user the rights to :
- CREATE
- DROP
- DELETE
- INSERT
- SELECT
- UPDATE
- GRANT OPTION
It is also possible to give only certain privileges to this user.
GRANT right_name ON db_name.table_name TO 'username'@'localhost';
Then to remove rights, simply change the GRANT keyword to REVOKE.
REVOKE right_name ON db_name.table_name TO 'username'@'localhost';
All that remains is to update the user's privileges.
FLUSH PRIVILEGES;
So, if we go to the url : localhost/adminer.php
, and use the user we have just created and then indicate the database : mysql
, we now access the database named mysql
with the user we have created.
To exit the MySQL command interface, simply enter the
quit
command.
PHP configuration
We will need to make some changes to the php.ini
file located in /etc/php/7.4/apache2
.
To modify this file, we will use the nano
utility natively available on Ubuntu 20.04.
sudo nano /etc/php/7.4/apache2/php.ini
We will then perform a search on the display_errors
element. To do this, execute the command ctrl+w
and then type the text : display_errors
.
The cursor should automatically move to the following line:
display_errors = Off
If this is not the case, press
ctrl+w
again and then press theenter
key on the keyboard until you find the right line.
Change the value of display_errors
to On
. You should get :
display_errors = On
Do the same for the display_startup_errors
element a few lines below.
Then for the error_reporting
element, we will keep only the value E_ALL
.
error_reporting = E_ALL
We will now save the changes and exit. To do this, press ctrl+x
then y
and finally press enter
on the keyboard.
Apache configuration file
Let's take a look at what an Apache configuration file looks like. These are located in the /etc/apache2/sites-available
folder.
Currently, in this folder we find two files :
- 000-default.conf
- default-ssl.conf
If we display the contents of the 000-default.conf
file with the command :
cat /etc/apache2/sites-available/000-default.conf
We will end up with something like this :
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
The most important lines are:
<VirtualHost *:80>
: Here, we will accept any IP on port 80. For now, the only IP configured islocalhost
,DocumentRoot /var/www/html
: This line is the entry point for the site,ErrorLog ${APACHE_LOG_DIR}/error.log
: This line will allow you to specify the log file containing the list of errors that occurred during the hosting of the site.
To make things a little easier during the development of a site, we will create a symbolic link between a directory on your Windows machine and a directory on the Linux subsystem.
By chance, when WSL is initialized, it will automatically mount
your hard disks. This way we can access them from Ubuntu 20.04 via the /mnt
directory.
To do this, assuming that we have a directory located in D:\Sites\project
. We will then create a symbolic link between this directory and the symbolic directory located in /var/www/project
. To do this, we will run the following command.
sudo ln -s /mnt/d/Sites/projet /var/www/projet
In order to verify that the link has been executed, we will run the command
cd /var/www && ls -l
We notice that the html
directory has not moved, but a new directory has been created. Furthermore, with the ls -l
command, we notice that the project
directory is linked to the /mnt/d/Sites/project
directory.
All that remains is to modify the Apache configuration file to include the new directory as an entry point.
sudo nano /etc/apache2/sites-available/000-default.conf
Then we will modify the DocumentRoot
line.
DocumentRoot /var/www/projet
All that remains is to apply the new changes.
sudo service apache2 reload
So, if we go to localhost
we see this page appear.
This is quite normal because, at the moment, we have no file in the D:\Sites\project
directory.
If we create a index.php
file in the D:\Sites\project
directory, and then put the following content :
<?php phpinfo(); ?>
By refreshing the page on your browser, you should see a next page.
It is possible that, when starting the apache2
service, you may get the following error :
Protocol not available: AH00076: Failed to enable APR_TCP_DEFER_ACCEPT
To solve this problem, simply add the lines AcceptFilter http none
and AcceptFilter https none
to the end of the /etc/apache2/apache2.conf
file. This way, the error will no longer be displayed.
Create a site.local url
Modifying the url is not necessarily very useful. However, don't be fooled. It not only allows you to have custom urls but also to host multiple sites on the Linux subsystem.
We will now create a blog
directory in the D:\Sites
folder. Then we will create the symbolic link between this directory and the /var/www/blog
folder.
sudo ln -s /mnt/d/Sites/blog /var/www/blog
By running the ls -l
command in the /var/www
directory, we notice that we now have three directories. The two we saw earlier: html
and project
. We also find our new blog
directory which is directly linked to the /mnt/d/Sites/blog
directory.
We will now create our own Apache configuration file.
Simply create a file that we will name blog.conf
in the /etc/apache2/sites-available
directory.
sudo touch /etc/apache2/sites-available/blog.conf
In which we will put the following content :
<VirtualHost *:80>
ServerName www.blog.local
ServerAlias blog.local
ServerAdmin webmaster@localhost
DocumentRoot /var/www/blog
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.blog.local.log
CustomLog /var/log/apache2/error.blog.local.log combined
</VirtualHost>
All we have to do is activate the new configuration and restart the apache2
service.
sudo a2ensite blog.conf
Then we restart the Apache service.
sudo service apache2 restart
You can now put whatever content you want in the D:\Sites\blog
directory. For the example we will put a basic html template.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog</title>
</head>
<body>
<h1>My awesome blog</h1>
</body>
</html>
Unfortunately, if we go to the url blog.local
, we get a DNS error (DNS_PROBE_FINISHED_NXDOMAIN). In other words, the default DNS used by the computer does not recognise this url. This is perfectly normal. You will simply have to tell it manually.
To do this, go to the C:\Windows\System32\drivers\etc
directory and open the hosts
file.
Then you just need to add the following lines at the end of the file :
::1 www.blog.local
127.0.0.1 www.blog.local
::1 blog.local
127.0.0.1 blog.local
This file is protected by administrator rights. To modify it, you just need to launch a text editor such as NotePad++ or Visual Studio Code as an administrator. You can then modify this file.
Now, if we go to the url blog.local
, you should find the blog page.
Enable url rewriting
If you want to use a framework such as Symfony or Laravel, you will have to activate the url rewriting.
To correct this problem, you will just have to execute the following commands :
sudo a2enmod rewrite
Then restart the Apache service.
sudo service apache2 restart
This manipulation will allow, via the use of a .htaccess
file, to rewrite the Apache rules.
👍 Normally, with all this information in hand, you should be ready to create your website.
Deleting a site
In some cases, you may want to delete a site. It's very simple. Just delete the configuration files located in/etc/apache2/sites-available
and /etc/apache2/sites-enabled
and then delete the site folder in /var/www
.
sudo rm /etc/apache2/sites-available/project_name.conf
sudo rm /etc/apache2/sites-enabled/project_name.conf
sudo rm /var/www/project_name
All that remains is to delete the log files corresponding to this configuration. These log files are located in the /var/log/apache2
directory.
sudo rm /var/log/apache2/project_name.log
You can now restart the Apache service to take into account the new changes.
sudo service apache2 restart
I really hope that this article has helped you or made you want to discover new technologies 💻.
Cover by Christopher Gower