Deploying NGINX-based web server | Part 2 – LEMP

Alright, Debian VM sorted. Now, it’s time to get our hands dirty! Well, sort of… Mine already were. Did I ever mention I cycle to work every day? Well, for once I didn’t check weather forecasts yesterday and… I hope those mud stains actually wash off. I need to finally sort out that front mudguard!

Alright! Enough about my adventures, let’s get to work!

Note: Since last post I’ve also installed a couple extra packages like sudo and vim. sudo allows me to run commands with elevated privileges. vim is my favourite text editor. If you wish to install sudo, do:

su - # You will be asked for root password. If you authenticate successfully, you will now be logged in as root
apt update # Update package lists
apt install sudo # Install sudo package
usermod -aG sudo tecden # Add user tecden to sudo group. This is required to be able to use sudo. Otherwise we're not allowed to
exit # Log out of root account
exit # Log out of tecden account. This is required in order for the group settings to apply. If you don't log out, you won't be able to use sudo


LEMP consists of Linux (that we’ve installed in my last post), NGINX, MariaDB and PHP. We will need to install those packets in order to use them (obviously!). Additionally, we will install WordPress to make sure everything is working correctly.

Now, after you log in again, you should be able to use sudo to run commands as superuser!


Let’s start with NGINX as it should be enough to already present some content:

sudo apt update # Update package lists
sudo apt install nginx # Download and install NGINX

After NGINX is installed, it should automatically start. However, we want NGINX to start automatically whenever we boot our computer. To make NGINX start after boot, do:

sudo systemctl enable nginx

To confirm is NGINX is running, do:

sudo systemctl status nginx

If it’s up and running, your terminal should show something like this:

Additionally, we can check if anything is listening on port 80 (HTTP):

ss -tulpn | grep 80

We should get something like this:

Great! Let’s see if our browser shows us something. In your browser, go to the VM’s IP address. In my case, it’s

Woohoo! For now we won’t be seeing more as we want to use something a little more interactive (static HTML websites are passé).

MariaDB and PHP

Let’s install everything that we will need to get our dynamic page up and running

sudo apt install mariadb-server php-fpm php-mysql 

A whole lot of packages will install. But don’t worry, everything is going according to the plan:

After everything is installed, let’s harden our MariaDB installation a little. This is to prevent most obvious vulnerabilities that would be a result of default installation. To make our DB a bit more secure, run:

sudo mysql_secure_installation

This will take you through a couple of questions. First, provide your root password when asked Enter current password for root (enter for none). Now, when asked if you want to change the root password, say no and then for every other following step after that say yes. Every question is explained during the hardening.

Now, let’s make sure we can still log in to our database:

sudo mysql

You should see something like this:

Let’s list all available databases. Type in:

show databases;

You should see the list of databases:

As you can see, we don’t have many databases as we haven’t done anything yet. Let’s create a new database for our website with command:

create database mysite;

This will create a database named (you guessed it!) mysite. Now, let’s create a user that our WordPress site will use to communicate with the database.

Note: We should never use root account for anything but maintenance.

To create a user, use:

CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'your_password';

And give it full control over mysite database:

GRANT ALL ON mysite.* TO 'wordpress'@'localhost';

After the user is created & all necessary permissions are granted, let’s save and move on:


Whole process looks like this:


All components are there and ready for WordPress. Let’s download the latest WordPress version then

mkdir /tmp/wp # Create 'wp' folder in /tmp/ directory
cd /tmp/wp # Change directory to /tmp/wp
wget # Download latest WordPress release
tar xf latest.tar.gz # Unpack the archive to current folder

We should now have two objects in /tmp/wp directory: latest.tar.gz archive and wordpress folder. Let’s move the wordpress folder to /var/www/ directory and rename it to, for example, mysite:

sudo mv wordpress /var/www/mysite # This will move wordpress directory to /var/www and rename it to mysite.

Now we have to configure WordPress. Don’t you worry though! It ships with a sample config that we can use to configure our website. Let’s copy the sample config:

cd /var/www/mysite # Move to our wordpress directory
cp wp-config-sample.php wp-config.php # Create a copy of sample config named "wp-config.php"

And let’s edit it:

nano wp-config.php

Change following lines:

In “define(‘DB_NAME’, ‘database_name_here‘);” line change bold text to mysite
In “define(‘DB_USER’, ‘username_here‘);” line change bold text to wordpress
In “define(‘DB_PASSWORD’, ‘password_here‘);” line change bold text to your password. For example, YellowHorse123 (I’m terrible at this, I know. ).

Your file will look like this:

Now, save the changes and let’s move on to the next step which is correcting permissions on the /var/www/mysite folder.

To change permissions, do

sudo chown -R www-data:www-data /var/www/mysite # This will change the directories owner and group from tecden to www-data.
sudo chmod -R 755 /var/www/mysite # This changes permissions of the contents of mysite directory and the directory itself.

When that’s done, all we have to do is configure NGINX to serve our website:

sudo nano /etc/nginx/sites-available/oursite # this will take us to an editor so we can create a file called "oursite"

And paste following contents. Replace values indicated by comments (text after #):

server {
        listen 80;
        root /var/www/mysite;
        index index.php index.html index.htm index.nginx-debian.html;
        server_name; #change the IP address to your VM's IP address if you don't have DNS set up to resolve hostname. If you don't have DNSes set up and you don't provide the IP address, you won't be able to access your website through the IP. If you have DNS records in place, remove the IP address and leave just the hostname.
        client_max_body_size 3M; # This is to avoid problems uploading pictures to WordPress. You can change this value if needed
        location / {
                try_files $uri $uri/ /index.php$is_args$args;}
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; # This may change over time. Please check /var/run/php/ directory for phpX.X-fpm.sock file in case you're getting 502 Bad Gateway error.
                fastcgi_connect_timeout 300s;
                fastcgi_read_timeout 300s;
                fastcgi_send_timeout 300s;}

        location ~ /\.ht {
                deny all;}

Save the file and close the text editor. We will now have to create a symbolic link from /etc/nginx/sites-available/mysite to /etc/nginx/sites-enabled/mysite:

sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/mysite

Moment of truth! Let’s restart NGINX:

sudo systemctl restart nginx

If everything goes smoothly, you shouldn’t see any messages. If something goes wrong and you see errors, head to /var/log/nginx/error.log for clues.

Let’s browse to (or if you’ve configured DNS) and we should be welcomed by the WordPress installation screen:

Installation itself is very easy and you should be fine to carry it out on your own since all the hard work has been done 🙂

In next article, we will look at monitoring so we know when our VM is in trouble!

Leave a Reply

Your email address will not be published. Required fields are marked *