Install WordPress with LEMP Stack and Let’s Encrypt Certificate on Ubuntu Server 20.04

LEMP stack in ubuntu image. Just a featured image.

Today I am going to show you how to install WordPress with Linux, Nginx, MariaDB, PHP (LEMP stack) and Let’s Encrypt SSL/TLS Certificate on Ubuntu 20.04. Make sure to follow every step exactly as mentioned to avoid any problem. If you face any problem during the process, feel free to comment under this post.

Prerequisites

  • Basic knowledge of Ubuntu.
  • Non-Root user account with sudo privileges OR Root user account.
  • An SSH Client (I personally use Termius and CMD).
  • Caffeine to keep you focused (Not Compulsory).

Step 1 – Install NGINX

sudo apt update
sudo apt install nginx
sudo systemctl stop nginx.service
sudo systemctl start nginx.service
sudo systemctl enable nginx.service

Paste/Enter these commands one by one. Press Y if asked. Once done, Nginx will be installed successfully.

Step 2 – Install MariaDB

sudo apt install mariadb-server mariadb-client
sudo systemctl stop mariadb.service
sudo systemctl start mariadb.service
sudo systemctl enable mariadb.service
sudo mysql_secure_installation

Paste/Enter these commands one by one. When prompted, answer like this :

Enter current password for root (enter for none): Enter
Set root password? [Y/n]: Y
New password: Enter password
Re-enter new password: Repeat password
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y

Once done, MariaDB will be installed successfully.

Step 3 – Install PHP

sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.4-fpm php7.4-common php7.4-mysql php7.4-gmp php7.4-curl php7.4-intl php7.4-mbstring php7.4-xmlrpc php7.4-gd php7.4-xml php7.4-cli php7.4-zip

The above commands will install PHP 7.4.x (latest) and related modules. Once done, PHP will be installed successfully. To confirm the installation, use the command below.

php -v

It’ll give you an output similar to this :

PHP 7.4.3 (cli) (built: Feb 23 2020 07:24:28) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.3, Copyright (c), by Zend Technologies

Now that PHP is installed, Let’s edit the PHP Configuration file.

sudo nano /etc/php/7.4/fpm/php.ini

Find and edit the below settings :

memory_limit = 256M
post_max_size = 64M
upload_max_filesize = 128M
max_execution_time = 300
max_input_vars = 3000

Once done, Restart Nginx and PHP services by using the following commands :

sudo systemctl restart nginx.service
sudo systemctl restart php7.4-fpm.service

Step 4 – Create Database for WordPress

sudo mysql -u root -p
CREATE DATABASE DatabaseName;
CREATE USER 'username'@'localhost' IDENTIFIED BY 'password';
GRANT ALL ON DatabaseName.* TO 'username'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;
FLUSH PRIVILEGES;
EXIT;

Replace the DatabaseName, username and password with whatever you want to use.

Step 5 – Install WordPress

cd /tmp
wget https://wordpress.org/latest.tar.gz
tar -xvzf latest.tar.gz
sudo mv wordpress /var/www/html/domain.com
sudo chown -R www-data:www-data /var/www/html/domain.com/
sudo chmod -R 755 /var/www/html/domain.com/
sudo find /var/www/html/domain.com/ -type d -exec chmod 755 {} \;
sudo find /var/www/html/domain.com/ -type f -exec chmod 644 {} \;

Make sure to change domain.com with your domain name.

Step 6 – Set Up NGINX Server Block and Let’s Encrypt Certificate

From here on you’ll have to be extra careful. Let’s proceed.

Use this command to create and edit Nginx Server Block :

sudo nano /etc/nginx/sites-available/domain.com

Add all this in the server block :

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

    server_name  domain.com www.domain.com;
    root   /var/www/html/domain.com;
    index  index.php;

    include snippets/well-known;

    access_log /var/log/nginx/domain.com.access.log;
    error_log /var/log/nginx/domain.com.error.log;

    client_max_body_size 100M;

    autoindex off;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include fastcgi_params;
    }
}

Install Certbot by using this command :

sudo apt install certbot

Then enter these commands :

sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp www-data /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt
sudo nano /etc/nginx/snippets/well-known

Paste all this and save the file :

location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/lib/letsencrypt/;
default_type "text/plain";
try_files $uri =404;
}

Change the DNS of your domain so that it points to your server. Then enter these commands :

sudo ln -s /etc/nginx/sites-available/domain.com /etc/nginx/sites-enabled/
sudo systemctl restart nginx.service
sudo certbot certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt/ -d domain.com -d www.domain.com
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

If there is no problem with your DNS, your Let’s Encrypt Certificate will be issued successfully.

Now edit the Nginx Server Block again.

sudo nano /etc/nginx/sites-available/domain.com

Replace everything in it with :

server {
    listen 80;
    server_name www.domain.com domain.com;
    include snippets/well-known;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name domain.com www.domain.com;
    root /var/www/html/domain.com;
    index index.php;

    if ($host != "domain.com") {
           return 301 https://domain.com$request_uri;
       }

    include snippets/well-known;
    ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/domain.com/chain.pem;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 30s;

    access_log /var/log/nginx/domain.com.access.log;
    error_log /var/log/nginx/domain.com.error.log;

    client_max_body_size 100M;

    autoindex off;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ .php$ {
         include snippets/fastcgi-php.conf;
         fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include fastcgi_params;
    }
}

Restart Nginx :

sudo systemctl restart nginx

Make sure to change domain.com with your domain name. If you mess up, your site won’t work.

Step 7 – Create a Cron Job

Open Cron using this command :

sudo crontab -e

Paste this and save :

0 1 * * * /usr/bin/certbot renew >> /var/log/letsencrypt/renew.log

This will renew the Let’s Encrypt Certificate automatically.

Now all you need to do is open your website and set up your wordpress site.
Use the database, username and password created in Step – 4.

Enjoy.