nginx and WordPress
In my last article, I took an initial look at nginx, the high-performance open-source HTTP that uses a single process and a single thread to service a large number of requests. nginx was designed for speed and scalability, as opposed to Apache, which was designed to maximize flexibility and configuration. But through the years, nginx has become increasingly flexible as well, with a growing number of plugins and modules that can be used to customize its configuration. Between the performance, increasingly good documentation and convenience, it's no wonder nginx has been increasingly popular.
It's also no surprise that WordPress, the open-source blogging and CMS platform, has become hugely popular. I've heard people say that 10% of websites are now run using WordPress. Even if that's not precisely true, there's no doubt that a huge number of sites are powered by WordPress. I'm a mostly satisfied WordPress user, having converted my main site and my two ebook sites to it in the past year after years of using it to power my blog.
So, I thought it would be interesting to demonstrate how easy it is to set up WordPress with nginx, given the popularity of each of these systems alone as well as together. In my last article, I described how you can set up a plain-vanilla PHP system with nginx; WordPress is a bit more complex, but less than you might think. Starting with a bare-bones Linux installation, let's walk through the configuration needed to get WordPress up and running.
The BasicsIn order to install WordPress and nginx together, you're going to need three basic software systems installed: WordPress, nginx and MySQL. The first two are pretty obvious, given this article's goal; the third is a byproduct of using WordPress, which works exclusively with MySQL.
So, on my Ubuntu Linux machine, I would run the following:
$ sudo apt-get install mysql-server mysql-client nginx-core
↪php5-cli php5-fpm php5-mysql
This installs a very large number of packages, but it will give you
the core of what you need to get your system up and running. Notice
that you're not installing WordPress here, so that you can install it
manually, using the source code. Indeed, installing WordPress via
apt-get
also means installing Apache; although it's certainly possible to
undo this choice, the benefits of installing WordPress on your own
outweigh those of doing it via a package manager.
You will, as part of this installation, need to choose a password for your MySQL root user. This is an important part of security on your system, so do try to use a strong password.
Once the package manager completes the installation of the above packages, you'll have a working nginx installation. Try it; you can point your browser at your server's port 80, and you should get the default nginx page indicating that it installed correctly.
Installing WordPressInstalling WordPress is quite straightforward; the complex part will be hooking together nginx with FPM, the PHP version of FastCGI. As you saw if you read my last article (in the June 2016 issue), FPM is the method through which nginx can run PHP in a separate process, without bloating the entire nginx process or reducing performance by very much.
The default location for HTML files in my nginx configuration is /usr/share/nginx/html. Within that directory, there's an index.html file, whose contents provide the default "welcome" page to nginx that you saw earlier.
The thing is, it's probably easiest just to install WordPress in a separate directory. So, I download WordPress and open it up under /usr/share/nginx/wordpress, which is a directory that'll be created anyway, when I open the tarfile. Here's what I did:
$ cd /usr/share/nginx
$ wget https://wordpress.org/latest.tar.gz
$ tar -zvxf latest.tar.gz
Now that WordPress has been installed, you'll want to run it. But you can't do that until you have created a MySQL database, since part of the WordPress installation requires that your database be working and ready.
So, let's create a new MySQL database! There are several ways to do
it. I typically prefer to use the mysqladmin
program, which takes
similar options to the MySQL client, including -u
to indicate which
user you want to use and -p
to indicate that you want to enter a
password. Both will be necessary:
$ mysqladmin create wordpress -u root -p
Note that when I say you want to use the "root" user here, I'm not
referring to the UNIX-level root user. Rather, I'm talking about
the MySQL "root" user, which has ultimate privileges on the database.
When you installed MySQL earlier, you needed to choose a root
password. It's this password that you must enter when prompted,
thanks to the -p
option above.
You can check that your database was created by entering MySQL as root
(once again, with -p
and after entering the root password):
$ mysql -u root -p
Then, issue the command SHOW DATABASES
at the
mysql>
prompt. On my
completely new system, I got the following response:
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| wordpress |
+--------------------+
4 rows in set (0.01 sec)
Notice that there are three databases in the system in addition to the "wordpress" database I created earlier. These are used internally by MySQL. Indeed, you'll now connect from the UNIX shell to the "mysql" database, which is used to run your database:
$ mysql mysql -u root -p
If you prefer, you also can switch to the "mysql" database from within the MySQL client:
mysql> \u mysql
Either way, you should now be connected to the "mysql" database as root. Next, you'll create a "wordpress" user and then allow that user to connect to your MySQL "wordpress" database.
I should note that when I work with consulting clients, it's not unusual for them to use the "root" user for all of their database connections. After all, it's more convenient, right? However, this is almost always a bad idea; you really want to have and use a separate user name for security reasons.
Once connected, you'll create a user, assign it a password and indicate that this new user has full privileges on the "wordpress" database:
mysql> CREATE USER wordpress@localhost;
mysql> SET PASSWORD FOR wordpress@localhost = PASSWORD('my-wp-pw');
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO wordpress@localhost;
mysql> FLUSH PRIVILEGES;
Note that SQL commands are case-insensitive, so you don't need to use CAPITAL LETTERS when entering them. However, I've done so for years, following the advice of Joe Celko's SQL For Smarties books, and I've found that it helps to distinguish between other parts of my programs.
Also note that in the above scenario, you've created a "wordpress" database and a "wordpress" user. Actually, your user isn't named "wordpress" so much as "wordpress@localhost"; when connecting to MySQL, the hostname is taken into account.
Finally, the FLUSH PRIVILEGES
command is necessary to tell MySQL
that it should take the new privileges into account even without doing a
restart of the database server.
Once this is in place, you'll want to test it to make sure you can connect to the "wordpress" database as the "wordpress" user. On the UNIX shell, type:
$ mysql wordpress -u wordpress -p
When prompted for the password, enter the password you used (which is
hopefully not "my-wp-pw" from above). You should see the
"welcome"
message and a mysql>
prompt. If that doesn't work, then
double-check the user name and password that you created, and make sure you
flushed the privileges.
Now that you know your configuration works, you'll set up your WordPress configuration in a file called wp-config.php. This file is in the directory /usr/share/nginx/wordpress, thanks to opening the WordPress tarfile earlier.
A new WordPress installation doesn't have a configuration file; you must copy it from the wp-config-sample.php that comes with the system:
$ cp wp-config-sample.php wp-config.php
Once that's done, open the file, and look for three lines that define
DB_NAME
, DB_USER
and
DB_PASSWORD
. Change all three values to reflect
the database, user name and password you have created here; this is
how WordPress will connect to your database.
Next, you'll need to configure the UNIX-level permissions. Every process runs as a certain user, and nginx is no exception. On Ubuntu machines, both nginx and Apache run as the "www-data" user and group. Using a specific user ID to run such programs allows you to ensure that the correct permissions are in place. However, it also means you need to be sure that the WordPress directory and files are owned by that user.
So, you can say:
$ cd /usr/share/nginx
$ sudo chown -Rv www-data:www-data wordpress
The -R
option tells chown
to work
recursively. The -v
option
turns on "verbose" mode, meaning that you get additional feedback from
the program as it works. I generally prefer to run programs with
-v
to give me more feedback.
Now you have to configure your nginx server. When you installed it, the main configuration file was placed in /etc/nginx/nginx.conf. However, modern nginx configurations also include one file for each server it is running in /etc/nginx/sites-enabled/, with the file /etc/nginx/sites-enabled/default describing the default site.
For the purposes of simplicity, I'm going to assume here that you have a single site, which means you'll be able to modify just the individual "default" file, rather than the overall config file.
As is usual in nginx, the configuration is broken into individual
blocks. server
blocks describe how the HTTP requests coming in
should be handled; in this case, you want anything that arrives on port
80 for any hostname to be passed to PHP. The following server block
does the trick:
server {
listen 80 default_server;
root /usr/share/nginx/wordpress;
index index.php index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
}
Let's go through the above, so you can understand what's happening.
First, you indicate that this server will listen on port 80. Unless
you have a good reason to choose a different port, this is probably
a good idea. Note that if and when you want to use SSL, that goes
on port 443 and also requires a separate server
block. For purposes
of simplicity, let's ignore that here.
You also use default_server
to indicate that if someone provides a
hostname that does go to your IP address, but that is unhandled by any
other hostname, then this server should be used. If your system
handles only one HTTP server, this directive should be set in
your configuration. If your system has multiple virtual HTTP
servers, you'll need to decide which should be the default.
The root
directive describes the directory containing the files
you'll want to serve. After opening the tarfile into
/usr/share/nginx/wordpress, you tell nginx that the directory
contains the PHP programs you want to execute. Actually, it's just
one PHP program in index.php that does all the heavy lifting.
The index
command indicates what files should be read, and in what
order, if you don't provide a filename. Note: indicate that
index.php should be tried first to give WordPress a chance to run
things before static alternatives are attempted.
The server_name
directive tells nginx which name(s) should be
recognized by this server. If you're using default_server
and have
only one virtual host, this doesn't matter all that much.
However, if you have multiple servers, giving a name is a good
idea.
You then indicate, using a location
block, what you want to do when
you receive a request to the "/" URL—meaning, a directory name.
This directive tells nginx that it first should try the URL that you
received, but if that doesn't work, then you should invoke
index.php, passing it the URL and any arguments that you received
with it. In this way, index.php becomes the gatekeeper for any and
all requests you recieve.
You then indicate what to do in case of error, separating 404 ("file not found") from more serious server-side errors (50x errors). nginx comes with static files for these errors; you can modify those files if you want something more informative or whimsical.
Finally, you connect nginx to FPM, the PHP back-end system that I
discussed in my last column. FPM runs PHP in a separate
process, but keeps it going continuously, so you don't have to
start up a new process each time. If you find that php5-fpm
isn't
running, you might need to start it with:
$ sudo php5-fpm restart
Once the above is in place, you can restart nginx:
$ sudo nginx restart
Point your web browser to your WordPress system's IP address or hostname, and you should see a request to choose a language as part of the WordPress installation. If you do, then you've made it; your server is up and running. Move on to the next page to choose a site title, admin user name, password and email address, and you're all set!
Conclusion
As you can see, it's surprisingly easy to set up WordPress with nginx.
Assuming that PHP is installed, and that PHP's FPM system is installed
and running, you actually can get an nginx-powered WordPress blog up
and running in just a few minutes. And although you could install
WordPress via apt-get
or a similar package manager, doing so means
that your updates are at the mercy of the Linux distribution you're
using, which inevitably will lag behind the WordPress distribution
itself, not to mention plugins, which are perhaps one of the most
important parts of the WordPress ecosystem.
nginx is a popular server, and as such, there are lots of sources for information about it. One of the best such sources is the official site of nginx run by the company that has been founded to develop and support it. From that site, you can read a great deal of high-quality documentation, including a Wiki with many user-submitted suggestions.
WordPress, of course, is a hugely popular open-source product. You can read more (lots more) at the WordPress site. And although there are enormous numbers of blogs, books and references for WordPress, I've found that for simple installation and usage, very little documentation is necessary. You can download, install and use it with a minimum of fuss. That said, if and when you do encounter problems, a search at WordPress.org and/or at Stack Overflow generally will solve the problem.