Installing NGINX, MySQL, PHP, and WordPress on an Ubuntu system.

Installing NGINX, MySQL, PHP, and WordPress on an Ubuntu system.

This brief course provides you with some extra pointers for working in Linux.


In this lesson, you'll learn how to install WordPress on Ubuntu. For the demonstration here, I'm going to be using Ubuntu 20.04, because it's an LTS release, by the way LTS stands for long term support. Every two years, Ubuntu releases an LTS version and guarantees to support that release for at least five years. You know, it's an LTS release because it will be labeled as such plus it will be an even number major version, representing the year of the release with a minor version of 0.04, representing the month of the release. Of course, the fourth month of the year is April. So, Ubuntu 20.04 is an LTS release that was made available in April of 2020. Other examples of LTS releases include 14.04, 16.04, 18.04, of course, 20.04 and so on.

There are more frequent releases that happen about every six months. And those are really considered development releases. Those development releases are only supported for nine months at a time. So, if you're going to be running Ubuntu in production, I highly recommend using an LTS release, like we're doing here.

I created a virtual machine in virtual box and installed Ubuntu there. If you're also using a virtual machine, you'll want to make sure to configure that virtual machine to use bridged networking. In virtual box, you can go to the settings for the virtual machine. Then click on network and where you see attached to, make sure that it is set to bridged to adaptor. Typically, this is set to NAT by default, but again, you can just come in here, change it to bridge adaptor and then you'll need to select the network interface you are using on your physical machine. In my case, I'm using wifi.

So, I'm going to make sure that is selected. If you are using different virtualization software, such as VMware, just go to the network settings and make sure you are using bridged networking. What bridged networking does is it allows the virtual machine to appear on your network, just like another physical machine. It also allows us to access the virtual machine over the network, which will become very important, near the end of this process.

WordPress is a web application and that means we need to install a web server. The two most popular choices for web servers on Linux are Apache and Nginx. Until recently, Apache was used to host the majority of websites on Linux, but is now the most Nginx is now the popular web server choice on Linux. So, let's go ahead and use Nginx to host our WordPress website.

Before we install any software on an Ubuntu system, we first need to update our local list of available packages and to package versions by running sudo apt update. If you are logged in as the root user, you don't have to use sudo. You could simply run apt update, but I'm logged into the system as a normal non-root user.

In order to elevate my privileges to super-user or root privileges, I need to proceed the command with sudo, because we'll be managing software and services throughout this lesson. We'll continue to use sudo as those actions require super user privileges. So, what happened if you didn't run apt update? Well, you might encounter a situation, where the specific package you are attempting to install is not available. Let's say the last time you ran apt update was two or three weeks ago. At that time, let's also say that Nginx, 1.18.0 was available to be installed. However, since then a bug was fixed and version 1.18.1 replaced version 1.18.0. If you were to try and install Nginx, without running apt update first, your local system would attempt to download the old unavailable version and you'll get an error. By running apt update, your local system will download a list of all the current packages and versions available. So, when installing software on Ubuntu systems, it's best to get in the habit of running apt update, before performing the actual software installation.

Okay, with that explanation out of the way, we can go ahead and install Nginx. Again, installing software requires root privileges. So, I've used the sudo command here to give me those routes privileges. Now it's asking me if I want to continue with the installation. I do, so I'm going to type Y and hit enter to let the installation continue. By the way, you can use the dash Y option to apt install to automatically answer yes to this question. I'll show you that when we install our next piece of software as I want you to see both methods.

At this point Nginx is installed and we can check to see if it's running with systemctl. Sure enough it's running and is set to start on boot. This line that I've highlighted here on your screen, tells us that it is indeed active and running. Now, the word that I've highlighted here, tells us that the service is enabled to start on boot. If you see disabled here that means the service will not automatically start on boot. To make it start on boot, what you would do would be to run sudo systemctl, enable followed by the service name, in this case that would be Nginx.

By the way, if the output from systemctl will not fit on your screen completely, it will display the output using a pager. Here, you'll see that there are some that scrolls off to the right of the screen. And that's indicated by those arrows at the bottom of the screen. Now to exit out of the pager and return back to the command line, simply type Q. Even though the service is reported as running, let's check to see if it's actually working. We can do this with a curl command as it's an easy way to make HTTP requests.

By the way, the IP address of is a loop back address. It's a special IP address that a Linux system uses to communicate with itself. You can also do this. Local host is the host name that represents this computer that I'm using right now. The IP address for local host is, so running curl or curl local host gives us the same results. Anyway, what you see here returned is HTML. Curl doesn't interpret that HTML like a web browser would, we're just making a request and receiving the raw output from the web server. And this is enough information to let us know that Nginx is working properly.

Now, WordPress needs a place to store its data, such as the text of a blog post, the name of the author, the date and time when it was posted, et cetera. All of this type of data is stored in a database. And we're going to use a my SQL database to store that data. Notice that I'm using the -y option to apt install, so that I don't have to wait for apt to prompt me for confirmation. You can think of -y as standing for yes or answer yes.

Now that my SQL is installed. Let's make sure that it's running. By the way the package name was mysql-server, but the service name installed by that package is MySQL. That's why I'm using mysql in the systemctl command. And in this case, it appears to be running and enabled on boot as well. 

Let's create a database that WordPress can use. Now, we need to create a database user that can access that specific database. To create a user, we'll go ahead and use the mysql client. This create user statement, creates a user and sets the password for that user. Here, you can see the username is wordpress@localhost and the password is wordpress123. This grant statement allows full permissions to the WordPress database, to the WordPress database user. To exit out of the MySQL client, type exit and hit enter.

Now, let's test to see if our WordPress user, can access the word press database. To do this, we'll run the my SQL command again and tell it to use the WordPress user to access the WordPress database. The -u option allows us to specify a database user. In this case, that user is WordPress. The -p option will make mysql prompt us for the password.

Finally we're going to specify the database we want to connect to. Now, I'm going to type the password of wordpress123 for the WordPress database user. If you see the mysql prompt, then everything is working just as we want it to. However, if you get an access denied error at this point, try the command again and make sure that you are typing in the password exactly. Let me show you what it looks like, when you miss type the password. I'm just going to arrow up to run the command again and I'm going to miss type the password. If you try this a couple of times and the password is still not working, then perhaps there was a typing mistake, when you created the user's password. To fix that, we'll need to run the mysql command is route and update the password on the account. So, let me show you what that looks like.

Here we're using a set password statement to set the password for the WordPress user. Now, we can try the password again. If you make a mistake in the name of the database, you'll also get an error. And here's what that looks like. So, let's say I accidentally hit the character three, before I hit enter. And of course WordPress 3 is not a database that we've created. So, we'll get an error. If you get an error, always just check your typing. Now again here's what it looks like when everything is working correctly.

All right, we'll go ahead and exit out of our mysql client, because WordPress is written in PHP. We need to install PHP. Specifically we're going to install PHP FPM. FPM stands for Fast CGI Process Manager. In a moment we'll configure Nginx to hand off all of its PHP requests to PHP FPM for processing. In addition to the main PHP service, we need to install some additional PHP modules. For example, WordPress needs to communicate with MySQL. So, we'll install the MySQL module for PHP.

You'll notice that, I've just added the php-mysql package name to the end of the command line. You can install multiple packages at once with apt. So, you don't have to have one apt command per package installation. Anyway, we also need the curl-php module, which is used to make remote requests. We'll also need the MB string module, which allows UTF-8 characters to be handled properly. MB stands for multi-byte and UTF-8 characters are multi byte characters.

Next, we need the image magic PHP module to handle things such as image resizing. Next, we'll install the XML PHP module, which of course provides XML support. And finally we'll add the PHP zip module, which is used to unzip plugins, themes and WordPress update packages. We have PHP FPM and all the required modules installed. Let's make sure that the PHP FPM service is running. I'm not exactly sure of the name of this service, but the good news is that I don't have to know the name. I'm guessing that it will start with PHP, but after that I'm really not sure.

So, what I'm going to do here is hit the tab key twice. Now, I'm presented with all the possible choices that begin with PHP. I'm interested in PHP FPM. So, php.7.4-fpm.service is most likely what I'm looking for. So, I can continue typing the rest of that name out or I can type the next character or two and hit tab again. And that's what I'm going to do. I'll type seven and then hit tab, because there is only one match. It is auto completed. This process of using tab is called command line completion or tab completion. Now, this isn't something that is unique to the systemctl command. You'll find you can use this with many different commands plus file names. At any rate the PHP FPM service appears to be running.

Next, we need to tell Nginx to send all PHP requests to PHP FPM. What we're going to do is update the default configuration that gets installed when the Nginx package gets installed. Let's move into that configuration directory first. The name of the default configuration file is aptly named the fault. Personally, I like to make a backup copy of configuration files before I edit them. This way if I make a mistake or can't seem to get the service back online quickly, I can quickly and easily copy the original configuration file, back into place, restart the service and be in a known good state.

Now, it's time to edit the file and just feel free to use your favorite editor. Personally, I love VIM and would normally use that, but there is a learning curve to VIM. As a matter of fact, I have an entire course on just a VIM itself, but right now I'm gonna go ahead and use nano, because it's a very simple editor that can be used without any additional training. So, if you don't have a favorite editor, just use nano like I'm doing here or if you're a VIM person, go ahead and use that. Or if Emacs is your favorite editor, use that.

Again, it doesn't matter which editor you use. We just need a way to make changes to this file. Let's go to the line of configuration that starts with index. I'm not even going to use nano search feature here. I'm just going to arrow down until I see that line. Here we go. You'll see a note above this line that says, add index.php to the list if you are using PHP. Well, we're using PHP. So, let's do that. So, after the word index here, type index.php, make sure to leave a space before and after index.php. This line of configuration tells Nginx, which files to look for, when a client requests an index of a directory. We want to make sure that index.php comes first, so that if a PHP application lives in that directory, it will get served. So, order is important here.

So again, this line should start out, index space index.php space and then so on. The next piece of configuration we need to change is on the line that starts with tri underscore files. So, I'll just arrow down again. And here we find it. What we're going to do is replace equals 404, with /index.php$is undescore args$args. Be very careful with your typing here. Make sure you type everything as you see here on your screen. A couple of common mistakes that could be made, would be to add additional spaces or use capital letters. Also make sure you leave the semi-colon at the end of the line. Don't delete that. That needs to be there as well.

Now this line of configuration allows you to use pretty permanent links in WordPress. For example, instead of a page on your WordPress site having a path of /question mark p equals one, it could have a nice pretty path of /hello-world. Next we need to come down a few more lines and start uncommenting the example PHP configuration. So, we'll start on commenting here. Comments in Nginx configuration files, start with a pound sign. Now, some people call them hash signs, hashes or number signs. No matter what you call them, just place your cursor over the pound sign or hash sign and then hit the delete key. Or you can place your cursor just one character to the right and hit the backspace key. So, just do whatever works for you.

We're using PHP FPM. So, we'll uncomment this section. However, you'll see the next couple of lines that refer to PHP-CGI and we're not using PHP CGI. So, we'll leave those comments intact will not delete those. However, we do need to make sure to uncomment, the closing bracket before this configuration stands up. If we don't, we'll get a syntax error. Those are all the changes we need to make. So, now we can type control X to exit, type Y, because yes, we do want to save our changes and then hit enter to accept the same file name.

Because we made a configuration change to Nginx, we need to check the configuration for errors. When you run Nginx with a -T option, it tests the configuration file for syntax errors. If it finds one, it will tell you about it and give you a chance to fix it. If you don't test the configuration and it has an error in it. When you go to restart Nginx, it will fail and your web server will be offline, while you fix your mistake. Even though a syntax check doesn't guarantee that we haven't broken anything. It does give us the peace of mind that Nginx, will most likely restart when we go to do so.

Okay, so as you see here on your screen, Nginx reports to us that the syntax is okay. Now we need to tell Nginx to reload or reread its configuration. Let's make sure Nginx is still working after our configuration change. Okay, great. It doesn't appear that we've broken anything. So, now what we need to do is return to our home directory. If you type CD, without any arguments it changes to your home directory. And we can confirm this by checking our present working directory with PWD. You'll notice that our prompt displays, our present working directory. For example, when we were in etc, Nginx site-available that displayed as our prompt. Now, that we're in the home directory, a tilda is displayed as our prompt. And the tilda is a shortcut in Linux to represent your home directory.

Now, it's time to download WordPress. One way to do that directly from the command line is to use curl. We've already used curl a couple of times to make web requests to our local system, but now we're going to use it to download a file. The dash capital O option causes the file to be saved locally with the same name that was used on the remote system. I'm downloading a specific version of WordPress, because it's the current version at the time of this recording. And I know it works with the steps I've shown you here. It allows you to follow along with me exactly. That said WordPress does provide a way to download the latest version of its software by using the URL of

As you probably know, I can't predict the future. So, if you download a later version of WordPress than the one I'm demonstrating with here, then you're on your own if you have any issues. It's probably best just to use the version, I'm using here and then upgrade WordPress via the web interface. And I'll show you how to do that in just a minute.

Now, that we've downloaded our file, let's extract the contents of that file or of that archive. The X option tells tar to extract the contents of the archive. The V option stands for verbose and it makes tar display the files it's operating on. And finally, the F option tells tar to operate on the file that follows. Now, let's move the WordPress application files to the document route of the web server.

We're going to use the WordPress web interface to perform the application configuration. This means WordPress will attempt to write a configuration file to the disc on our Linux server. Also, if we want to allow WordPress to update themes, plugins and even WordPress itself, it will need right permissions to do so. The web server runs as the www-datauser in group. So, let's make the www-datauser the owner of all the application files and make www-data, the group for all those files as well.

The dash capital R option stands for recursive. This means the ownership of every file in directory at and below the specified path will be changed. Let's go ahead and take a quick look in that directory. Okay, it appears that every file in directory is owned by the www.datauser and that every file in directory is in the www-data group. Now, we need to determine the IP address of our server. We can see all of the addresses assigned to all of the network interfaces with the IP space, a command. The first network interfaces named LO and it's the loop back interface. You'll see that it has an IP address of And we've already talked, about this special IP address earlier.

As a reminder this is how a Linux system can communicate with itself via the network stack. Since this is an internal only address, this is not the IP address we're looking for. Typically the second network interface listed in this output is the one that has the system's, primary IP address assigned to it. On this system it's named ENP 0 S3. It might be named something totally different on your system. For example, it might be named ETH 0 or ENP 1 S2 or something else. The name's not important, but the IP address is. The IP address for this system is The chances that this is also your IP address are very, very, very slim. So, make a note of your IP address on your system.

Now, what we're going to do is take your IP address and enter it into a web browser. At this point, you should see a page that has the word press logo and a series of languages for you to select. It should look something very much like you see here on your screen. If you get a timeout error or an unreachable error, then first make sure you typed in the IP address correctly.

If you're using a third party provider to host your server, then look for the server's public IP address, using your provider software or web interface. For example, if your server is an AWS instance, AWS assigns a public IP address that is mapped to the primary IP address of your server. So, you won't see the internet facing public IP address directly on your server. To get that IP address, you would look in the AWS web console for example. If you're in this situation, then type in the public IP address of your server into the browser and try again.

If you still get a timeout or unreachable error, then make sure that there isn't a firewall blocking access to port 80 of your server. You'll have to consult, your specific provider's documentation on how to unblock port 80. So, I'm going to select my language, which is English and click continue. At this point, we can go ahead and click let's go. The database name that we created is WordPress. So, there's nothing to change there. The username that we use for our database was WordPress and the database password for that user is wordpress123. The database host is this host, so we can leave it at local hosts and we do not need to modify the table prefix. So, we'll go ahead and click on submit.

If you get an unable to write to the WP config.php file error, then you need to fix the permissions with a CH own command from earlier in the lesson. Once your screen looks like this, go ahead and click run the installation. Now, we need to fill out this simple form about our blog. So, we'll give our blog a site title of My Fun Blog. Now, we need to pick a username that we'll use to administer our WordPress site. Now, I don't recommend using the username of admin, because every hacker on the internet tries to access every WordPress website using the admin user. So, pick something else, it could be anything. It could be your name. It could be some set of characters that only you know or whatever.

Here, I'm just going to use my name. So, my username will be Jason. WordPress suggests a very strong password here and I'd recommend that you use that, especially for production, but I'm just gonna go ahead and make a very weak password here named jason123. And if you do something like this, we will have to click confirm the use of a weak password. And then here you go ahead and enter your email address. Finally, click install WordPress.

Okay, now we can log in with the username and password that you chose. And of course, in my case it was Jason, jason123. At this point, we see the administration dashboard for WordPress. You can notice here that I have some updates on my system and I suspect you will as well. So, you can go ahead and click on updates and select what you want to update. I'm just going to update this plugin for now and click update plugins. And what's gonna happen is WordPress is going to download the update to that plugin and write the files for that plug into the disc on our Linux system. So again, this is why we changed the ownership to www-data.

Let's take a quick look at our site. So, I'm actually going to right-click here and open up in a new tab. And so, this is what our visitors see, when they visit our website. Let's go ahead and click on hello world. You'll notice that we have a pretty URL here at the top. And that is because we performed that Nginx configuration earlier in the lesson.

So, I'm gonna switch back to the dashboard, go to settings and click on permalinks. And then I like having just the post name. So, that's what I'm going to select. And then I'm going to save my changes. I'll go back to My Fun Blog here. I'll click on that and then click on this hello world post. And now you can see that the pretty permalink is hello-world. Of course, the goal of this project was to learn how to deploy WordPress. So, I'll leave any further exploring of WordPress up to you.

About the Author
Learning Paths

Jason is the founder of the Linux Training Academy as well as the author of "Linux for Beginners" and "Command Line Kung Fu." He has over 20 years of professional Linux experience, having worked for industry leaders such as Hewlett-Packard, Xerox, UPS, FireEye, and Nothing gives him more satisfaction than knowing he has helped thousands of IT professionals level up their careers through his many books and courses.