Install LEMP on Ubuntu WSL on Windows 10

1:26 am Windows Development

To facilitate web development, I wanted the same environment on my Windows 10 desktop as exists on my Ubuntu VPS server. With WSL (Windows Subsystem for Linux), I can have the same LEMP (Linux, Nginx, MySQL, and PHP) setup on my Windows 10 desktop.

See my previous post, Install Subversion on Ubuntu WSL on Windows 10, to get an Ubuntu-flavored WSL working on your Windows 10 system.

Instructions to install LEMP on Ubuntu WSL are almost the same as what I used to install LEMP on my Ubuntu server (see Install Ubuntu, LEMP, and WordPress on an Unmanaged VPS).

Install PHP

The latest Ubuntu WSL version is 18.04.1 LTS, which supports the latest PHP 7.2 version.

# Install PHP 7.2 and support packages:
# - php7.2-cli - PHP command line
# - php-mysql - PHP library to call MySQL database
# - php-fpm - PHP FastCGI Process Manager for Nginx integration
sudo apt install php7.2 php7.2-cli php7.2-mysql php7.2-fpm

# List the installed packages and grep for php-specific packages:
dpkg --get-selections | grep -i php

# Get the version of PHP installed
php -version

Install MySQL

# Install MySQL server.
sudo apt install mysql-server

# Get version of MySQL server and CLI installed
mysqld --version
mysql --version

# Start MySQL server
sudo service mysql start
sudo service mysql status

# Log into MySQL server as root user with blank password.
sudo mysql -u root
mysql> show databases;
mysql> quit

Note: Instead of using the “quit” command to exit the MySQL client, you can also use the “exit” command. Semi-colon termination (for example, “quit;” or “exit;”) are optional for these close connection commands.

By default, the MySQL server is configured to only allow root MySQL login from the root Linux user. Thus, we had to use “sudo mysql -u root” above. If we wish to allow a non-root Linux user to login using the root MySQL user (eliminate need for “sudo”), we’ll need to change how the root MySQL user is athenticated (switch to “mysql_native_password” plugin instead of the “auth_socket” plugin).

# Log into MySQL server as root user with blank password.
sudo mysql -u root

# Allow connection from a non-root Linux user
mysql> use mysql;
mysql> update user set plugin='mysql_native_password' where User='root';
mysql> flush privileges;

# Exit MySQL client.
mysql> quit

# Log into MySQL server as root user without "sudo".
mysql -u root
mysql> show databases;
mysql> quit

If you wish to secure the MySQL server, you can use the convenient “mysql_secure_installation” utility. Run the utility to enable password validation, set a root user password, remove anonymous users, disable remote root login, and remove the test database. You can re-run the utility again to reset the root user password if you need to.

# Run utility to secure MySQL server
sudo mysql_secure_installation

# Log into MySQL server as root user with password prompt
mysql -u root -p
mysql> show databases;
mysql> quit

If you wish to go back to using a blank MySQL root password, run the following to disable password validation and set a blank root password:

mysql -u root -p
mysql> uninstall plugin validate_password;
mysql> set PASSWORD for root@localhost=PASSWORD('');
mysql> quit

Install Nginx

# Install Nginx
sudo apt install nginx

# Start Nginx server
sudo service nginx start

Browse to http://localhost/ and you should see the initial Nginx welcome page.

Start the PHP-FPM service so Nginx can execute PHP scripts.

# Locate unix socket file which PHP-FPM service will listen to.
grep "listen =" /etc/php/7.2/fpm/pool.d/www.conf
# output: listen = /run/php/php7.2-fpm.sock

# Start PHP-FPM service.
sudo service php7.2-fpm start

Edit the default Nginx server block file to use the PHP-FPM service:

sudo nano /etc/nginx/sites-available/default

In the “default” server block file, change the following:

server {
        # Add index.php to the list if you are using PHP
        #index index.html index.htm index.nginx-debian.html;

        # Add index.php to front of "index" to execute it first
        index index.php index.html index.htm index.nginx-debian.html;

        # pass PHP scripts to FastCGI server
        #
        #location ~ \.php$ {
        #       include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        #}

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # Make sure unix socket path matches PHP-FPM configured path above
                fastcgi_pass unix:/run/php/php7.2-fpm.sock;

                # Prevent ERR_INCOMPLETE_CHUNKED_ENCODING when browser hangs on response
                fastcgi_buffering off;
        }
}

Restart the Nginx service to have the changes take effect:

sudo service nginx restart

Test PHP and MySQL Integration

Create a PHP test script by running this edit command:

sudo nano /var/www/html/info.php

In the “info.php” file, input the following content:

<?php
phpinfo();
?>

Browse to http://localhost/info.php and you should see a page containing information about the PHP installation.

Create a PHP MySQL test script by running this edit command:

sudo nano /var/www/html/mysql.php

In the “mysql.php” file, input the following content:

<?php
// HTML response header
header('Content-type: text/plain');

// Database connection parameters
$DB_HOST = 'localhost';
$DB_PORT = 3306; // 3306 is default MySQL port
$DB_USER = 'root';
$DB_PASS = ''; // blank or password (if you set one)
$DB_NAME = 'mysql'; // database instance name

// Open connection (all args can be optional or NULL!)
$mysqli = new mysqli($DB_HOST, $DB_USER, $DB_PASS, $DB_NAME, $DB_PORT);
if ($mysqli->connect_error) {
  echo 'Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error . PHP_EOL;
} else {
  // Query users
  if ($result = $mysqli->query('SELECT User FROM user')) {
    echo 'Database users are:' . PHP_EOL;
    for ($i = 0; $i < $result->num_rows; $i++) {
      $result->data_seek($i);
      $row = $result->fetch_assoc();
      echo $row['User'] . PHP_EOL;
    }
    $result->close();
  } else {
    echo 'Query failed' . PHP_EOL;
  }
}

// Close connection
$mysqli->close();
?>

Browse to http://localhost/mysql.php and you should see a page listing the MySQL database users.

If you have problems, you can debug by enabling PHP-FPM error logging. Edit the configuration for the PHP-FPM pool:

# Edit www.conf file and add an error_log directive.
sudo nano /etc/php/7.2/fpm/pool.d/www.conf
    # Add an error log file location in the "/tmp" directory
    ;php_admin_value[error_log] = /var/log/fpm-php.www.log
    php_admin_value[error_log] = /tmp/fpm-php.log

# Restart PHP-FPM service for change to take effect
sudo service php7.2-fpm restart

Note: There exists a “/etc/php/7.2/fpm/php.ini” configuration file but that is not used by the Nginx PHP-FPM connection. Also, putting the error log file in a directory other than the “/tmp” directory (like “/var/log”) may not work due to permission issues.

Info above derived from:

Leave a Comment

Your comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.