Install & Configure WordPress Site with Nginx on Ubuntu

WordPress is the most popular CMS (content management system) on the planet, it powers more than 40% of the web, and that’s for pretty good reasons; it’s completely free and open-source, allowing anyone to set up and manage blogs and even complex ecommerce sites with …

WordPress is the most popular CMS (content management system) on the planet, it powers more than 40% of the web, and that’s for pretty good reasons; it’s completely free and open-source, allowing anyone to set up and manage blogs and even complex ecommerce sites with little to no technical expertise.

WordPress has seen incredible adoption, and is used by the likes of TechCrunch, Facebook, Vogue, and other big brands. After the initial setup, almost all administration can be done through the web frontend.

This tutorial will be focussing on setting up a WordPress instance on a LEMP stack (Linux, Nginx, MySQL, and PHP) on an Ubuntu server. I’ve used Microsoft Azure in this tutorial, the steps will be the same for any other cloud provider be it DigitalOcean, Linode, AWS, etc.

Step 1: Creating a Virtual Machine

Any basic virtual machine running Ubuntu 20.04 will suffice:

  • 1 GB RAM
  • 1 vCPU
  • 20 GB Storage

Pick the server location that’s closest to your website viewers for lower latency.

Step 2: Updating the DNS Entry

Note down the IP address of the virtual machine, and go to your domain registrar and add two A records for the same IP address:

  • Enter @ in the host section, your IP address in the value section, and update TTL to 3600.
  • Enter www in the host section, your IP address in the value section, and update TTL to 3600

Step 3: Configuring the Virtual Machine for WordPress

Now, let’s configure our server:

Step 3.1: Connect to the Server via SSH

Open up the terminal on your device, and run this command:

ssh root@123.45.67.89

If you chose a username while creating the virtual machine, use that instead of root, and replace 123.45.67.89 with the IP address of your VM.

You’ll be prompted with “The authenticity of host…”, just type yes, and then enter the password.

Step 3.2: Configure Automatic Updates

Let’s update packages and configure automatic updates so that our server gets patched automatically.

# Update packages
sudo apt update && apt upgrade

# Install unattended-upgrades
sudo apt install unattended-upgrades

# Configure unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

# Test unattended-upgrades
sudo unattended-upgrades --dry-run --debug

Step 3.3: Creating a “sudo” user

If your cloud provider didn’t ask you to choose a username while creating it, you are given root access to your server; it is recommended to not use the “root” user, which has unlimited privileges and can execute any command, even ones that could potentially disrupt your server.

Let’s create a new user on a server that can use “sudo” to do day-to-day administration tasks.

# Create a new user
adduser username

# Add user to the "sudo" group
usermod -aG sudo username

# Check user's group
groups username

# Switching users
su - username
su - root

Step 3.4: Configure SSH Keys

Using SSH keys instead of passwords provides you with better security, as SSH keys are far more long and complex than any password could ever be; you can also add an extra password to the SSH keys, requiring both the SSH key and the password to access the server.

Log out of the server or just open up a new terminal on your computer to create SSH keys:

# Create ssh keys
ssh-keygen -b 4096 

# View ssh keys
ls -l ~/.ssh

# Add public key to server
ssh-copy-id -i ~/.ssh/keyname.pub username@123.45.67.89

# Switch ssh keys on client
ssh-add ~/.ssh/keyname

During the ssh-keygen process, you’ll be prompted for file location, use the default one or give a new location by typing in /home/username/.ssh/keyname, and enter a strong password for the SSH key.

In the .ssh folder, there’ll be two files, the one with “.pub” extension is your public key, the other one is your private key, never share the private key with anyone.

You might get a message like Could not open a connection to your authentication agent when switching SSH keys, you’ll need to start ssh-agent first using:

eval `ssh-agent`

Once done, you can log in to the server by just using the ssh username@123.45.67.89 command without entering the user password, although you will need to enter the password of your SSH key.

Step 3.5: Disable root login

Now that we have a new user with limited privileges that can run “sudo” commands and can access the server via SSH keys; let’s lock down our root user, as it is usually the most targeted account by hackers.

To do so, type in sudo nano /etc/ssh/sshd_config, and update PermitRootLogin to no and add AllowUsers username as shown below:

Disable root login via SSH

Optionally, you can also go ahead and disable password-based login via SSH for all users, including the new user account we just created, by updating these values in the same sshd config file:

# Disable password-based login via ssh for all users [optional]
PasswordAuthentication no
ChallengeResponseAuthentication no

Once done, save the file using Ctrl + O & Ctrl + X, and restart the sshd service using this command:

sudo systemctl restart sshd

Now, your server is ready to install WordPress, let’s get into it.

Step 4: Installing EasyEngine

We’ll be using EasyEngine to install WordPress on our server, EasyEngine is a free and open-source automation script by rtCamp, that allows you to create WordPress sites with simple commands.

You don’t have to worry about setting up individual components like Nginx, MySQL, PHP, etc., everything is taken care by EasyEngine.

The latest version of EasyEngine uses Docker, but you don’t really need to know about docker, it’s pretty simple to configure and is loved by developers and freelancers alike.

To start, type in this command:

wget -qO ee rt.cx/ee4 && sudo bash ee

It will take a few minutes to install all the necessary softwares and configure them, once done, you’ll be greetd with something like this:

ee successfully setup.
+-------------------+-----------------------------------------------------------------------------------------+
| OS                        | Linux 5.4.0-105-generic #119-Ubuntu SMP XXX XXX X XX:XX:XX UTC 2022 x86_64 |
| Shell                     | /bin/bash                                                                                                                    |
| PHP binary           | /usr/bin/php8.0                                                                                                          |
| PHP version         | 8.0.17                                                                                                                          |
| php.ini used         | /etc/php/8.0/cli/php.ini                                                                                              |
| EE root dir            | phar://ee.phar                                                                                                            |
| EE vendor dir       | phar://ee.phar/vendor                                                                                                |
| EE phar path        | /root                                                                                                                           |
| EE packages dir   |                                                                                                                                    |
| EE global config  |                                                                                                                                    |
| EE project config |                                                                                                                                    |
| EE version            | 4.5.3                                                                                                                           |
+------------------+-----------------------------------------------------------------------------------------+
/usr/sbin/cron
/usr/bin/crontab
-----> Adding ssl-renew cron
no crontab for root
-----> Run "ee help site" for more information on how to create a site.

Alright, EasyEngine has been successfully installed on your and is ready for you to create websites.

Step 5: Creating a WordPress Site

Run the following commands to create a WordPress site with Redis cache and get an SSL certificate from Let’s Encrypt:

sudo ee site create example.com --type=wp --cache --ssl=le

Replace example.com with your domain name, once completed, you’ll be greeted with something like this:

Starting site creation.
Configuring project.
Creating WordPress site example.com
Copying configuration files.
Starting site's services.
Downloading and configuring WordPress.
Moved /var/www/htdocs/wp-config.php to /var/www/wp-config.php successfully
Checking and verifying site-up status. This may take some time.

Installing WordPress site.
Success: https://example.com has been created successfully!
Enter your mail id: mail@example.com
Starting SSL verification.
The authorization check was successful!
Executing first request.
Requesting first certificate for domain example.com.
Certificate received
Certificate stored
Success: SSL verification completed.
Starting site's services.
Site entry created.
Creating cron entry
Success: Cron created successfully
+------------------------+----------------------------------------+
| Site                              | https://example.com                          |
+------------------------+----------------------------------------+
| Site Root                      | /opt/easyengine/sites/example.com |
+------------------------+----------------------------------------+
| Site Title                       | example.com                                     |
+------------------------+----------------------------------------+
| WordPress Username  | XXXXXXXX-XXXXXXX                         |
+------------------------+----------------------------------------+
| WordPress Password   | XXXXXXXXXXXXXXXXXX                    |
+------------------------+----------------------------------------+
| Alias Domains             | None                                                   |
+-----------------------+-----------------------------------------+
| DB Host                      | global-db                                             |
+-----------------------+-----------------------------------------+
| DB Name                    | example_com                                      |
+-----------------------+-----------------------------------------+
| DB User                      | example.com-XXXXXX                         |
+-----------------------+-----------------------------------------+
| DB Password              | XXXXXXXXXXXX                                   |
+-----------------------+-----------------------------------------+
| E-Mail                        | admin@example.com                          |
+-----------------------+-----------------------------------------+
| SSL                             | Enabled                                                |
+-----------------------+-----------------------------------------+
| SSL Wildcard              | No                                                        |
+-----------------------+-----------------------------------------+
| Cache                         | Enabled                                                |
+-----------------------+-----------------------------------------+
| Proxy Cache               | Off                                                        |
+-----------------------+-----------------------------------------+

You’ll be prompted for an email address, and a random username & password will be generated for both your WordPress site and the database, I recommend deleting that user and creating a new account.

Step 6: Setting up Multiple WordPress Sites

With the same EasyEngine command used above, multiple other websites can be created and hosted on the same server, do check your RAM and storage before hosting multiple sites on the same server.

However, since EasyEngine v4 uses Docker, there’s a limitation of 31 networks per machine. EasyEngine creates one network per site, and it also needs few Docker networks for global services.

This limits the number of sites per server to 27.

You can use WordPress Multisite to get around this limitation, as the Multisite is counted as a single site, this can help reduce overall burden and in a way enforce usage of quality codes.

Or, you can just spin up a new server once you reach the 27 site limit.

Useful EasyEngine Commands

# View site information
ee site info example.com

# View installation logs
cat /opt/easyengine/logs/install.log

# View error logs
cat /opt/easyengine/logs/ee.log

EasyEngine also has a list of all the commands.

Set up WordPress with Nginx Conclusion

Automated scripts like EasyEngine have made it incredibly easy to configure and install WordPress sites on a self-hosted web server, there is a helpful EsayEngine community on GitHub.

You should look into Admin Tools which can be accessed from example.com/ee-admin, to learn about all the cool admin tools that come preinstalled with EasyEngine like opcache-gui, MailHog, etc.

Photo by Fikret tozak on Unsplash