The Perfect Web Server – Part 1

Is there such a thing as a perfect web server? If so, how will you deploy it? What all do you need to take care of when doing so? The name is a bit misleading – there is no such thing as a perfect web server. But we can come close to perfection with hard work, dedication and skill.

This is a post series on creating a near perfect web server. I hope that it will be useful to those budding server admins out there… so here goes.

There are a few good design elements to keep in mind when architecting any server or cloud deployment. They are:

  • Operational Excellence – Run, manage and monitor production workloads to deliver business value and continuously improve on supporting processes and events.
  • Security – Protect information, systems and assets from attacks.
  • Reliability – Auto recover workloads from infrastructure, system or power failures.
  • Performance Efficiency – Use computing resources efficiently to support on demand changes for delivering worload with maximum performance to meet the SLA.
  • Cost Optimization – Avoid unnecessary cost or replace resources with cost effective resources without impacting the best practices and business needs.
LEMP Stack

Considering the above, I am going to show you how to deploy a LEMP stack. LEMP stands for Linux, Nginx, MySQL, PHP – these are the components which need to be configured to get a secure and efficient web server that runs PHP applications.

Nginx has several advantages over Apache web server. It is secure, fast and efficient. It can handle a large number of connections with a low resource usage. Nginx handles static content by itself, but passes the dynamic content (php files) to a php-fpm process. This process returns HTML that Nginx sends to the client. Apache uses per directory configuration done using .htaccess files, while Nginx does not do per directory configuration at all. This makes Apache more flexible – users of shared hosting can do limited web server configuration themselves without needing to reload Apache. But it is not really a disadvantage as Nginx gets a performance boost by not having to read the directory structure for configuration files. Also, it is better security-wise as responsibility for configuration of .htaccess files lie with the user in the case of Apache; the user may not secure their .htaccess files.

Enough with the theory… I will add references at the end of this article, should you be interested in a long read.

Hands On!

First, create an account with a cloud provider. I use DigitalOcean as it is easy, has lots of tutorials and is cost effective. This blog is also hosted on DigitalOcean.

Start a $5 basic droplet (virtual machine / instance) with the minimum specs available – 1vCPU, 1 GB RAM, 25 GB SSD.

  1. Login to http://cloud.digitalocean.com/ and set up 2-step authentication.
  2. Create a new project and add your domain to it. You may need to change the nameservers to DigitalOcean ones, at your domain registrar. Also create an A record for your domain / subdomain pointing to your droplet.
  3. Create a $5 droplet with Ubuntu 20.04 LTS as the OS
    1. select your preferred datacenter location. It is recommended to choose a location that is close to you for least latency.
    2. Select additional options – tick “user data” and “monitoring”.
    3. enter the following user data
apt update
apt install nginx mysql-server php-fpm php-mysql -y

4. select / add an ssh key, used to login to the droplet

5. choose a hostname, say, wp-on-lemp

6. add a tag, say, nginx. this will be used later, when creating a firewall for the droplet.

7. Go to Manage > Networking > Firewalls and create a firewall with open ports 80, 443 and 22. Enter the droplet tag to apply the firewall to the droplet.

4. login to the droplet using the given public IP and your SSH key. If you are using OpenSSH,

ssh root@<public IP> -i /path/to/private/key

You will find that certain things are already installed, due to the user data script – nginx, mysql server and php.

Create a user

Note that you are logged in as root. This is insecure, so create a user account and copy over the ssh folder. The below script can do this for you, just change the USERNAME variable to your user.

adduser $USERNAME
usermod -aG sudo $USERNAME
rsync --archive --chown=${USERNAME}:${USERNAME} ~/.ssh /home/$USERNAME

Next, secure the MySQL server. Set a strong root password and note it down.

sudo mysql_secure_installation

Create a folder to hold your website and change the folder owner to your username.

sudo mkdir /var/www/wpbeta
sudo chown -R $USER:$USER /var/www/wpbeta

NGINX configuration

Create an nginx configuration file for our website. This will be used to configure the web server properly.

Assuming that our website is wpbeta.cloudpixels.in,

sudo nano /etc/nginx/sites-available/wpbeta.cloudpixels.in.conf

This will open a nano text editor. Paste the below code into it.

server {
    listen 80;
    server_name wpbeta.cloudpixels.in;
    root /var/www/wpbeta;

    index index.html index.htm index.php;

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

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;

    location ~ /\.ht {
        deny all;


Enable / Activate the website by creating a link in the sites-enabled folder.

sudo ln -s /etc/nginx/sites-available/wpbeta.cloudpixels.in.conf /etc/nginx/sites-enabled/

Check the config file syntax, if it is successful, reload nginx to start serving the new site.

sudo nginx -t
sudo systemctl reload nginx

Nginx has been configured to serve your website.

In Part 2, we will start a WordPress site after creating a MySQL database. Later parts will involve optimizing it, securing it, adding a free SSL certificate, enabling HTTP/2, etc. Stay tuned for more.


DigitalOcean LEMP stack





Leave a Reply