Tutorial: Install a LEMP web server on a Linux virtual machine in Azure

This article walks you through how to deploy an NGINX web server, MySQL, and PHP (the LEMP stack) on an Ubuntu VM in Azure. The LEMP stack is an alternative to the popular LAMP stack, which you can also install in Azure. To see the LEMP server in action, you can optionally install and configure a WordPress site. In this tutorial you learn how to:

  • Create an Ubuntu VM (the 'L' in the LEMP stack)
  • Open port 80 for web traffic
  • Install NGINX, MySQL, and PHP
  • Verify installation and configuration
  • Install WordPress on the LEMP server

This setup is for quick tests or proof of concept.

Open Azure Cloud Shell

Azure Cloud Shell is a free, interactive shell that you can use to run the steps in this article. Common Azure tools are preinstalled and configured in Cloud Shell for you to use with your account. Select Copy to copy the code, paste it in Cloud Shell, and then press Enter to run it. There are a few ways to open Cloud Shell:

Select Try It in the upper-right corner of a code block. Example of Try It for Azure Cloud Shell
Open Cloud Shell in your browser. Launch Azure Cloud Shell button
Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal. Cloud Shell button in the Azure portal

If you choose to install and use the CLI locally, this tutorial requires that you are running the Azure CLI version 2.0.30 or later. Run az --version to find the version. If you need to install or upgrade, see Install Azure CLI.

Create a resource group

Create a resource group with the az group create command. An Azure resource group is a logical container into which Azure resources are deployed and managed.

The following example creates a resource group named myResourceGroup in the eastus location.

az group create --name myResourceGroup --location eastus

Create a virtual machine

Create a VM with the az vm create command.

The following example creates a VM named myVM and creates SSH keys if they do not already exist in a default key location. To use a specific set of keys, use the --ssh-key-value option. The command also sets azureuser as an administrator user name. You use this name later to connect to the VM.

az vm create \
    --resource-group myResourceGroup \
    --name myVM \
    --image UbuntuLTS \
    --admin-username azureuser \

When the VM has been created, the Azure CLI shows information similar to the following example. Take note of the publicIpAddress. This address is used to access the VM in later steps.

  "fqdns": "",
  "id": "/subscriptions/<subscription ID>/resourceGroups/myResourceGroup/providers/Microsoft.Compute/virtualMachines/myVM",
  "location": "eastus",
  "macAddress": "00-0D-3A-23-9A-49",
  "powerState": "VM running",
  "privateIpAddress": "",
  "publicIpAddress": "",
  "resourceGroup": "myResourceGroup"

Open port 80 for web traffic

By default, only SSH connections are allowed into Linux VMs deployed in Azure. Because this VM is going to be a web server, you need to open port 80 from the internet. Use the az vm open-port command to open the desired port.

az vm open-port --port 80 --resource-group myResourceGroup --name myVM

SSH into your VM

If you don't already know the public IP address of your VM, run the az network public-ip list command. You need this IP address for several later steps.

az network public-ip list --resource-group myResourceGroup --query [].ipAddress

Use the following command to create an SSH session with the virtual machine. Substitute the correct public IP address of your virtual machine. In this example, the IP address is azureuser is the administrator user name set when you created the VM.

ssh azureuser@

Install NGINX, MySQL, and PHP

Run the following command to update Ubuntu package sources and install NGINX, MySQL, and PHP.

sudo apt update && sudo apt install nginx && sudo apt install mysql-server php-mysql php-fpm

You are prompted to install the packages and other dependencies. This process installs the minimum required PHP extensions needed to use PHP with MySQL.

Verify installation and configuration

Verify NGINX

Check the version of NGINX with the following command:

nginx -v

With NGINX installed, and port 80 open to your VM, the web server can now be accessed from the internet. To view the NGINX welcome page, open a web browser, and enter the public IP address of the VM. Use the public IP address you used to SSH to the VM:

NGINX default page

Verify and secure MySQL

Check the version of MySQL with the following command (note the capital V parameter):

mysql -V

To help secure the installation of MySQL, including setting a root password, run the mysql_secure_installation script.

sudo mysql_secure_installation

You can optionally set up the Validate Password Plugin (recommended). Then, set a password for the MySQL root user, and configure the remaining security settings for your environment. We recommend that you answer "Y" (yes) to all questions.

If you want to try MySQL features (create a MySQL database, add users, or change configuration settings), login to MySQL. This step is not required to complete this tutorial.

sudo mysql -u root -p

When done, exit the mysql prompt by typing \q.

Verify PHP

Check the version of PHP with the following command:

php -v

Configure NGINX to use the PHP FastCGI Process Manager (PHP-FPM). Run the following commands to back up the original NGINX server block config file and then edit the original file in an editor of your choice:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default_backup

sudo sensible-editor /etc/nginx/sites-available/default

In the editor, replace the contents of /etc/nginx/sites-available/default with the following. See the comments for explanation of the settings. Substitute the public IP address of your VM for yourPublicIPAddress, confirm the PHP version in fastcgi_pass, and leave the remaining settings. Then save the file.

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    # Homepage of website is index.php
    index index.php;

    server_name yourPublicIPAddress;

    location / {
        try_files $uri $uri/ =404;

    # Include FastCGI configuration for NGINX
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;

Check the NGINX configuration for syntax errors:

sudo nginx -t

If the syntax is correct, restart NGINX with the following command:

sudo service nginx restart

If you want to test further, create a quick PHP info page to view in a browser. The following command creates the PHP info page:

sudo sh -c 'echo "<?php phpinfo(); ?>" > /var/www/html/info.php'

Now you can check the PHP info page you created. Open a browser and go to http://yourPublicIPAddress/info.php. Substitute the public IP address of your VM. It should look similar to this image.

PHP info page

Install WordPress

If you want to try your stack, install a sample app. As an example, the following steps install the open source WordPress platform to create websites and blogs. Other workloads to try include Drupal and Moodle.

This WordPress setup is only for proof of concept. To install the latest WordPress in production with recommended security settings, see the WordPress documentation.

Install the WordPress package

Run the following command:

sudo apt install wordpress

Configure WordPress

Configure WordPress to use MySQL and PHP.

In a working directory, create a text file wordpress.sql to configure the MySQL database for WordPress:

sudo sensible-editor wordpress.sql

Add the following commands, substituting a database password of your choice for yourPassword (leave other values unchanged). If you previously set up a MySQL security policy to validate password strength, make sure the password meets the strength requirements. Save the file.

ON wordpress.*
TO wordpress@localhost
IDENTIFIED BY 'yourPassword';

Run the following command to create the database:

cat wordpress.sql | sudo mysql --defaults-extra-file=/etc/mysql/debian.cnf

Because the file wordpress.sql contains database credentials, delete it after use:

sudo rm wordpress.sql

To configure PHP, run the following command to open a text editor of your choice and create the file /etc/wordpress/config-localhost.php:

sudo sensible-editor /etc/wordpress/config-localhost.php

Copy the following lines to the file, substituting your WordPress database password for yourPassword (leave other values unchanged). Then save the file.

define('DB_NAME', 'wordpress');
define('DB_USER', 'wordpress');
define('DB_PASSWORD', 'yourPassword');
define('DB_HOST', 'localhost');
define('WP_CONTENT_DIR', '/usr/share/wordpress/wp-content');

Move the WordPress installation to the web server document root:

sudo ln -s /usr/share/wordpress /var/www/html/wordpress

sudo mv /etc/wordpress/config-localhost.php /etc/wordpress/config-default.php

Now you can complete the WordPress setup and publish on the platform. Open a browser and go to http://yourPublicIPAddress/wordpress. Substitute the public IP address of your VM. It should look similar to this image.

WordPress installation page

Next steps

In this tutorial, you deployed a LEMP server in Azure. You learned how to:

  • Create an Ubuntu VM
  • Open port 80 for web traffic
  • Install NGINX, MySQL, and PHP
  • Verify installation and configuration
  • Install WordPress on the LEMP stack

Advance to the next tutorial to learn how to secure web servers with SSL certificates.