How to setup a LEMP Server on your Virtual Private Server

linode server

This guide is based on the Linode VPS I currently use, but can be applied easily to other hosting providers, such as RackSpace Amazon and more.

Finally I got it: Linode as my hosting provider. Since the several problems I have got on Dreamhost – such midnight crashes, old PHP version, poor support service and several downtimes – I have choosed my next provider. With the same amount of money, since I run a VPS on Dreamhost too, I have such a better service, since I can do on my VPS whatever I’d like.

The configuration: Ubuntu + Nginx + MariaDB + PHP

You can choose between several distributions for your Linode account, including Fedora or CentOS, but since on my everyday computing I use Ubuntu, so it’s much easier to use an Ubuntu / Debian instead of another distribution.

Let’s start – A new Linode server

The fist step it’s quite easy: once you have got your Linode account, you go through your Linode’s web UI, and choose your server: size, operating system (Ubuntu 16.04 LTS is my personal choice) and the root user password.
Just wait few minutes and your machine it’s ready to be up and running.

Connect to your new Server

If you work under a Linux environment, a Mac just open your terminal and type:

ssh root

The IP address of your server it’s located in your Linode control panel under the “Remote Access” tab.

If you work with Windows you can use Kitty to connect at your server. You can get a look on an article where I speak about Kitty for connecting at your server. You just need to follow the first part of the article.

When you’re asked for a password, type the root password you entered while setting up the new server in the Linode panel.

Setup Ubuntu

Now the next step it’s to configure the basic of Ubuntu to get it work and make it a bit more secure.

Update the server

Of course the first step is update the server. So just do:

sudo apt-get update && sudo apt-get upgrade

Set up the timezone

Linode comes with nodes from all over the world, since my users are mostly in Europe I have choosed the London based Linode datacentre, but the time zone in London it’s different from the one in Rome. So to set the timezone in the server type in your terminal:

dpkg-reconfigure tzdata

and just follow the few steps. Then to verify the date it’s correct type:


Create a new user

The user you’re logged in right now has a lot of power. It can do anything, so it’s not raccomandable having a root user only.
So we’re going to set up a new user with normal permissions.

To add a new user just type:


and than add it to the group of users with special privileges (the sudoers group).

usermod -a -G sudo 

Now your new user can do anything on your server, but for some operations it will have to type the word sudo in front of those commands.

Now we can logoff from the terminal and back log in with the new user just created.

Improve Ubuntu Security

A possible type of attack to your server could be done by somebody tring to reach your server’s IP and try guessing your password. Of course we don’t want that, so we have to do something to make our installation a bit more secure.

Disable to root user from remote

All Ubuntu servers have by default a root user. This is not so secure. What we will do to avoid that it’s prevent the remote login of the root user, and then we will change the SSH port from 22 to another one of your choice. The important thing it’s that you will remember it! In this example I will set the port to 52050.

About the choose of the SSH port you should take one higher than 49152 since the range of ports 0-1024 are “Well Known Ports”, while the ports from 1024 to 49151 are “Registered Ports”. Dynamic or private ports are from 49152 up to 65535, so the best choice it’s a port inside this range.

sudo nano /etc/ssh/sshd_config

then once you’re in nano using the arrows to move inside the files change the port line to:

# What ports, IPs and protocols we listen for
Port 52050

and set the line PermitRootLogin to no.
At this point we can save the file and restart the SSH service:

sudo service ssh restart

Next when we connect to the server, we have to make sure we “tell” to our terminal we are no more using the port 22:

ssh @ -p 52050

More security setting setup

We can a bit more deep in the security settings of our VPS, setting up some tools to disable login attempts with dictionary attacks, adding a firewall and get an email every time somebody use the “sudo” keywork.

Setup Fail2Ban – prevent dictionary attacks

Fail2Ban it’s a security tool developed to prevent dictionary attacks. What Fail2Ban does it’s a monitoring of the various services, such as Apache, SSH, NGINX and more. It bans an user if it is doing too many login attempts.

To install it just run this command:

sudo apt-get install fail2ban

Now to configure it:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

In the SSH-DDOS section set enabled to true.
Next set the port to 52050 (or whatever you used in the step above) in the sections SSH-DDOS and SSH.

Once you saved the file just restart Fail2Ban:

sudo service fail2ban restart

Setup a firewall

For this step we’re going to use the iptables: linux kernel provided firewall so we can manually approve the connections.

Since the firewall has no rules setted up by default

sudo iptables -L

to check the rules, we have to set them up: we will allow the ports for HTTP(80), HTTPS(443) and SSH(52050).
On top of those I’ll add some ports for testings, pinging and for Mobile Shell access.

sudo nano /etc/iptables.firewall.rules

# Allow all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0

-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d -j REJECT

# Accept all established inbound connections

# Allow all outbound traffic

# Allow HTTP and HTTPS.
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT

# Allow SSH connections
# The -dport number should be the same port number you set in sshd_config
-A INPUT -p tcp -m state --state NEW --dport 52050 -j ACCEPT

# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT

# Allow ports for testing
-A INPUT -p tcp --dport 8080:8090 -j ACCEPT

# Allow ports for Mobile Shell
-A INPUT -p udp --dport 60000:61000 -j ACCEPT

# Add logging for denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7

# Reject all other inbound - default deny unless explicitly allowed policy


And then we can finally activate the firewall rules:

sudo iptables-restore < /etc/iptables.firewall.rules

Now we have to activate those rules on the boot:

sudo nano /etc/network/if-pre-up.d/firewall

putting in this file:

 #!/bin/sh /sbin/iptables-restore > /etc/iptables.firewall.rules

the last step of this procedure it’s adding execution permissions to that script:

sudo chmod +x /etc/network/if-pre-up.d/firewall

VPS stability improvements

If the memory of our VPS runs out, the best option it’s a reboot. It’ll take at most one or two minutes, but if we leave the VPS swapping memory, the swapping state will stay on the server per hours.

To make it happen, add to the file




The first condition vm.panic_on_oom=1 means: enable a kernel panic if the machine runs out of memory.
The second line tells to reboot the VPS after 10 seconds from the panic condition.

Install the server side components

And now we are in the funny section. The server it’s secured, up and running but you cannot serve any webpage from it. So let’s start installing the server components.

Install a compiler

If you need to install from source (compile) packages, so you nedd a compiler. This can also be needed if you need to use for example Python.

sudo apt-get install build-essential

Install Maria DB

Since SUN has bought MySQL AB, and then Oracle has bought SUN, the community and his creator, Micheal “Monty” Widenius, have been creating a fork of the original MySQL. MariaDB has been recently implemented by Wikipedia, and it works fine with my WordPress installation.

I can choice to use MariaDB 10.6 , to choice the version more helpful for you go there: MariaDB repository and follow the steps to see what lines add to your sources file. The wizard will ask you for the physical position of the mirror, and since my server it’s located in UK I have used a repository in the Netherland.

sudo nano /etc/apt/sources.list

and add this code for MariaDB 10.6:

<code>#</code> MariaDB 10.6 repository list - created 2021-10-04 14:28 UTC <code>#</code> <a href=""></a> deb [arch=amd64,arm64,ppc64el] <a href=""></a> bionic main deb-src <a href=""></a> bionic main

Please choice the MariaDB version it’s more useful for you, if you are not sure it’s a better choice MariaDB 5.5.

Improve MariaDB shape and performances

The Optimize Table operation it’s the equivalent of defagmenting in Old windows machines (ok, maybe not the same, this is just an example). The optimize table it’s very important task. We must not forget it, but anybody always do.

We can lunch a cronjob: it will keep our database tables in a perfect shape for us:

crontab -e

and add this line:

@weekly mysqlcheck -o --user=root --password= -A

I know looks wierd to have a mysqlxxx command, but since the MariaDB it’s a fork of MySQL everything works just like in MySQL.

Keep MySQL data backupped.

All of us know: the most scary thing for a System administrator it’s the data loss. So let’s do something for preventing data loss from our databases. We will use the automysqlbackup package.

Let’s install it:

sudo apt-get install automysqlbackup

and configure it:

sudo nano /etc/default/automysqlbackup

The lines in this file we have to change are:


that I change in:


If an error occour you can always get an email changing the line with MAILADDR to MAILADDR=””.

Install NGINX

To have NGINX installed, we need to just run:

sudo apt-get install nginx

And that’s it: if you open your browser at your VPS ip address you should read “Welcome to Nginx!”.

Install PHP

sudo apt-get install php php-pear php-cli php-common php-curl php-dev php-fpm php-gd php-imagick php-imap php-intl php-mcrypt php-memcache php-ming php-mysql php-mysqlnd php-ps php-pspell php-recode php-snmp php-sqlite php-tidy php-xmlrpc php-xsl

Install PhpMyAdmin

The first step it’s just to run the command:

sudo apt-get install phpmyadmin

and next it’s to configure the phpmyadmin ngnix config file:

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

and put in the phpmyadmin parameters, them goes into the server {} section. This is how your clean installation should look like (please note the PHP section as well, above the PhpMyAdmin settings too.

server {
#listen 80; ## listen for ipv4; this line is default and implied
#listen [::]:80 default ipv6only=on; ## listen for ipv6

root /usr/share/nginx/www;
index index.html index.htm;

# Make site accessible from http://localhost/
server_name localhost;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to index.html
try_files $uri $uri/ /index.html;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules

location /doc/ {
alias /usr/share/doc/;
autoindex on;
deny all;

# Only for nginx-naxsi : process denied requests
#location /RequestDenied {
# For example, return an error code
#return 418;

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#error_page 500 502 503 504 /50x.html;
#location = /50x.html {
# root /usr/share/nginx/www;

# pass the PHP scripts to FastCGI server listening on
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
# # With php5-cgi alone:
# # With php5-fpm:
# fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
location /phpmyadmin {
root /usr/share/;
index index.php index.html index.htm;
location ~ ^/phpmyadmin/(.+\.php)$ {
try_files $uri =404;
root /usr/share/;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
location ~* ^/phpmyadmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
root /usr/share/;
location /phpMyAdmin {
rewrite ^/* /phpmyadmin last;

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#location ~ /\.ht {
# deny all;

# another virtual host using mix of IP-, name-, and port-based configuration
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# root html;
# index index.html index.htm;
# location / {
# try_files $uri $uri/ /index.html;
# }

# HTTPS server
#server {
# listen 443;
# server_name localhost;
# root html;
# index index.html index.htm;
# ssl on;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_timeout 5m;
# ssl_protocols SSLv3 TLSv1;
# ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
# ssl_prefer_server_ciphers on;
# location / {
# try_files $uri $uri/ /index.html;
# }

Now a last reboot for NGINX:

/etc/init.d/nginx reload

And you should be able to see your PhpMyAdmin installation up and running at this web address:


Next step could be set up your website.
That’s it. If you have any trouble, question or notice a mistake just leave a comment below.

2 pensieri su “How to setup a LEMP Server on your Virtual Private Server

Lascia un Commento!