// Tutorial //

How To Install WordPress with Nginx on Ubuntu 14.04

Published on May 15, 2014
Default avatar
By Justin Ellingwood
Developer and author at DigitalOcean.
How To Install WordPress with Nginx on Ubuntu 14.04
Not using Ubuntu 14.04?Choose a different version or distribution.
Ubuntu 14.04

Introduction

WordPress is the most popular CMS (content management system) in the world. It allows you to easily get your site or blog up and running. After installation, you can manage almost everything in an easy web interface.

In this guide, we will go over how to install WordPress on an Ubuntu 14.04 server. For the web server component, we will use nginx, a powerful and efficient web server that has seen wide adoption due to its performance capabilities.

Prerequisites

Before you begin with this guide, there are a few procedures that you should undertake.

First, you will need a non-root user with sudo privileges. You can run through steps 1-4 in the Ubuntu 14.04 initial server setup guide to create this account.

You will also need a LEMP (Linux operating system, Nginx web server, MySQL database, and PHP processing) stack installed and configured on your server. You can learn how to install and set up the necessary components by following our guide on installing a LEMP stack on Ubuntu 14.04 here.

When you have finished with the steps above, you can continue.

Step One — Create a MySQL Database and User for WordPress

The first thing that we need to do to get started with WordPress is to prepare our database.

We have the MySQL database software installed, but we have not created a database for our WordPress information. We also need to create an account that WordPress can use to access the database we will be creating.

We should begin by logging into an interactive session with our MySQL administrative account like this:

mysql -u root -p

You will be prompted for the password that you chose for the MySQL root account when you installed the software. You will be given a MySQL command prompt.

Now, we can create a separate database that will be used exclusively by our WordPress application. The name is not important, but it should probably be descriptive so that you can easily recognize it. In this guide, we will call our database wordpress:

<pre> CREATE DATABASE <span class=“highlight”>wordpress</span>; </pre>

Note the semi-colon (;) that ends the MySQL statement. Each MySQL statement must end with one, so double-check that if you are running into issues.

We have a database now, so we are ready to create a user account. We will then hand over control of the database to this new user so that our application can interact with the database. This system of creating a separate database and user for each application helps keep our data separate from other data being stored by MySQL, which is good for security and data management.

For this guide, we’ll pick wordpressuser for our account name. We’ll assign it a password of password to authenticate with. When you are setting up your own configuration, you should select a more secure password:

<pre> CREATE USER <span class=“highlight”>wordpressuser</span>@localhost IDENTIFIED BY ‘<span class=“highlight”>password</span>’; </pre>

Now, we have a database and a user, but we haven’t established a relationship between the two yet. We need to tell MySQL that our new user can access and control the database. You can do that with this command:

<pre> GRANT ALL PRIVILEGES ON <span class=“highlight”>wordpress</span>.* TO <span class=“highlight”>wordpressuser</span>@localhost; </pre>

Everything should be configured correctly now. We need to flush the privileges to disk so that our current instance of MySQL knows about the privilege changes we have made:

FLUSH PRIVILEGES;

Now, exit the MySQL prompt:

exit

Now we are back in our command prompt, ready to move on.

Step Two — Download WordPress to your Server

Next, we need to download the actual WordPress content onto our server. This is available on the WordPress website.

The latest stable version of the application is always given the same URL, which makes this part easy. We want to download the file to our user’s home directory:

cd ~
wget http://wordpress.org/latest.tar.gz

Our application files have been downloaded as a compressed, archived directory structure stored in a file called latest.tar.gz. We can extract the contents by typing:

tar xzvf latest.tar.gz

This will create a directory called wordpress that contains the site files.

We should take this opportunity to download some additional components that our WordPress instance will need. We can get these directly from Ubuntu’s software repositories using apt:

sudo apt-get update
sudo apt-get install php5-gd libssh2-php

These two packages allow you to work with images and install/update plugins and components using SSH respectively.

Step Three — Configure WordPress

We have the files now, so we can start to configure our WordPress instance.

We need to modify the main configuration file located in our new directory. Move into the directory that you extracted in the last section:

cd ~/wordpress

Inside of this directory, we have a sample configuration file called wp-config-sample.php. This has most of the configuration details correct, so we can copy that to use as the base of our config file:

cp wp-config-sample.php wp-config.php

When we open the file, our first order of business will be to adjust some secret keys to provide some security for our installation. WordPress provides a secure generator for these values so that you do not have to try to come up with good values on your own. These are only used internally, so it won’t hurt usability to have complex, secure values here.

To grab secure values from the WordPress secret key generator, type:

  1. curl -s https://api.wordpress.org/secret-key/1.1/salt/

You will get back unique values that look something like this:

Warning

It is important that you request unique values each time. Do NOT copy the values shown below!

Output
define('AUTH_KEY', '1jl/vqfs<XhdXoAPz9 DO NOT COPY THESE VALUES c_j{iwqD^<+c9.k<J@4H'); define('SECURE_AUTH_KEY', 'E2N-h2]Dcvp+aS/p7X DO NOT COPY THESE VALUES {Ka(f;rv?Pxf})CgLi-3'); define('LOGGED_IN_KEY', 'W(50,{W^,OPB%PB<JF DO NOT COPY THESE VALUES 2;y&,2m%3]R6DUth[;88'); define('NONCE_KEY', 'll,4UC)7ua+8<!4VM+ DO NOT COPY THESE VALUES #`DXF+[$atzM7 o^-C7g'); define('AUTH_SALT', 'koMrurzOA+|L_lG}kf DO NOT COPY THESE VALUES 07VC*Lj*lD&?3w!BT#-'); define('SECURE_AUTH_SALT', 'p32*p,]z%LZ+pAu:VY DO NOT COPY THESE VALUES C-?y+K0DK_+F|0h{!_xY'); define('LOGGED_IN_SALT', 'i^/G2W7!-1H2OQ+t$3 DO NOT COPY THESE VALUES t6**bRVFSD[Hi])-qS`|'); define('NONCE_SALT', 'Q6]U:K?j4L%Z]}h^q7 DO NOT COPY THESE VALUES 1% ^qUswWgn+6&xqHN&%');

These are configuration lines that we can paste directly in our configuration file to set secure keys. Copy the output you received now.

Now, open the WordPress configuration file:

nano wp-config.php

Find the section that contains the dummy values for those settings. It will look something like this:

/var/www/html/wp-config.php
. . .

define('AUTH_KEY',         'put your unique phrase here');
define('SECURE_AUTH_KEY',  'put your unique phrase here');
define('LOGGED_IN_KEY',    'put your unique phrase here');
define('NONCE_KEY',        'put your unique phrase here');
define('AUTH_SALT',        'put your unique phrase here');
define('SECURE_AUTH_SALT', 'put your unique phrase here');
define('LOGGED_IN_SALT',   'put your unique phrase here');
define('NONCE_SALT',       'put your unique phrase here');

. . .

Delete those lines and paste in the values you copied from the command line:

/var/www/html/wp-config.php
. . .

define('AUTH_KEY',         'VALUES COPIED FROM THE COMMAND LINE');
define('SECURE_AUTH_KEY',  'VALUES COPIED FROM THE COMMAND LINE');
define('LOGGED_IN_KEY',    'VALUES COPIED FROM THE COMMAND LINE');
define('NONCE_KEY',        'VALUES COPIED FROM THE COMMAND LINE');
define('AUTH_SALT',        'VALUES COPIED FROM THE COMMAND LINE');
define('SECURE_AUTH_SALT', 'VALUES COPIED FROM THE COMMAND LINE');
define('LOGGED_IN_SALT',   'VALUES COPIED FROM THE COMMAND LINE');
define('NONCE_SALT',       'VALUES COPIED FROM THE COMMAND LINE');

. . .

The file is now suitable for our needs; it is just lacking the information to connect to the database we created. The parameters we need to set are DB_NAME, DB_USER, and DB_PASSWORD.

We can find these parameters in this file and set them up to use the database and user details that we created. My file looks like this:

<pre> . . . // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define(‘DB_NAME’, ‘<span class=“highlight”>wordpress</span>’);

/** MySQL database username */ define(‘DB_USER’, ‘<span class=“highlight”>wordpressuser</span>’);

/** MySQL database password */ define(‘DB_PASSWORD’, ‘<span class=“highlight”>password</span>’); . . . </pre>

When you have made the changes above, save and close the file.

Step Four — Copy the Files to the Document Root

We have our changes to our config files. The next step is to copy them over to our document root so that our web server can find and serve them.

We will use the rsync utility to do the transfer. This has the advantage of preserving permissions, ownership, and ensuring data integrity.

The location of the default document root of nginx on Ubuntu 14.04 is /usr/share/nginx/html/.

However, we are going to set up our document root in /var/www/html/ to avoid modifying a directory location that is controlled by the nginx package. We will change this in our nginx configuration a bit later.

We can create the new document root directory by typing:

sudo mkdir -p /var/www/html

Now, we can copy the files to this location by typing:

sudo rsync -avP ~/wordpress/ /var/www/html/

This will recursively copy the contents of our ~/wordpress directory into our document root.

Next, let’s move over to the document root so that we can adjust some permissions:

cd /var/www/html/

The issue with the directory structure as it stands now is that all of our files have user and group ownership assigned to our regular user. This is fine, except that our web server needs to be able to modify certain directories and files.

We can give this permission without exposing too much of our system by giving the group that our web server runs under group ownership of the files. We can then open up group permissions slightly as needed.

The group that nginx operates under is www-data. For the user portion, enter your user account name. We will demonstrate with an account called demo here:

<pre> sudo chown -R <span class=“highlight”>demo</span>:www-data /var/www/html/* </pre>

This will give our files the necessary ownership.

Before we move on, we should create a new directory for user uploads:

mkdir wp-content/uploads

The new directory should have group writing set already, but the new directory isn’t assigned with www-data group ownership yet. Let’s fix that:

sudo chown -R :www-data /var/www/html/wp-content/uploads

Step Five — Modify Nginx Server Blocks

We have our files and directories configured. Now we need to modify our nginx configuration to serve the content correctly.

We can use the default nginx server block as a base for our new server block. Copy it over like this:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/wordpress

Open the new file we made so that we can make some changes:

sudo nano /etc/nginx/sites-available/wordpress

We will want to make the following changes:

<pre> server { listen 80 default_server; listen [::]:80 default_server ipv6only=on;

    root <span class="highlight">/var/www/html</span>;
    index <span class="highlight">index.php</span> index.html index.htm;

    server_name <span class="highlight">your_domain.com</span>;

    location / {
            <span class="highlight">#</span> try_files $uri $uri/ =404;
            try_files $uri $uri/ <span class="highlight">/index.php?q=$uri&$args</span>;
    }

    error_page 404 /404.html;

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
            root /usr/share/nginx/html;
    }

    location ~ \.php$ {
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            include fastcgi_params;
    }

} </pre>

A summary of changes that you should be making are:

  • Change the value of the root directive to point to our new document root at /var/www/html.
  • Modify the index parameter to look for an index.php file before the other files.
  • Change the value of the server_name directive to point to your server’s domain name or IP address.
  • Adjust the try_files within the location / block to send requests to PHP when they do not exactly match.

Some of these might already be set from your LEMP installation. When you are finished with these changes, save and close the file.

We need to link our new file to the sites-enabled directory in order to activate it. We can do that like this:

sudo ln -s /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/

The file we just linked conflicts with our old default file, since it borrowed so much from it. We need to disable the old file:

sudo rm /etc/nginx/sites-enabled/default

Now, restart the web server and PHP processor to enable our changes:

sudo service nginx restart
sudo service php5-fpm restart

Step Six — Complete the Installation through the Web Interface

Now, our WordPress is ready to go and we can finish the installation through our web browser.

Point your browser to your server’s domain name or IP address, like this:

<pre> http://<span class=“highlight”>your_domain.com</span> </pre>

If this shows your old default nginx page, you may have to refresh the page without the cache.

You will see the basic WordPress welcome stage. Choose your options (Site name, username, password, and email) and then click the “Install WordPress” button:

WordPress install screen

You will have to log in with the account you just created:

WordPress login

You will be presented with your WordPress dashboard, where you can begin customizing your setup and creating content:

WordPress dashboard

Conclusion

You should now have your WordPress instance up and running on an nginx web server in Ubuntu 14.04. WordPress is a fairly flexible platform that you can use to customize your site. Experiment with some different plugins, themes, etc. to find out what works best for you.


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?
10 Comments

I had the same problem where I was running into WordPress asking for FTP or SSH information, but I was able to find a solution on this site.

All I had to do was change the ownership of /var/www/html using the following:

sudo chown -R www-data. /var/www/html

Once that was done, I was able to update plugins and install themes with no issue.

Now, I am no Linux expert, so please let me know if I did something insecure here or if I will run into issues in the future.

I ran through the steps, I am receiving this message “Error establishing a database connection”

This tutorial desperately needs to be updated to include setting up exim4 or some other mail client, otherwise admin mail messages are not sent (new user, forgot password, contact form, etc).

I’ve followed the tutorials I can find, with no success. My contact forms are not working.

I couldn’t find any tutorials ANYWHERE on how to Install 2 Wordpress blogs (not multisite) side by side on NGINX. I also couldn’t find anything on Installing Ghost next to an NGINX WP — so I had to figure it out on my own. After lots of pain & suffering, I got the process worked out. So far anyone who wants to do the same, Here are the steps I took below. I am by no means knowledgeable in server languages or setup, so anyone please feel free to add their own corrections as necessary, or to copy this/add to it on a blog/somewhere online for the benefit of others. I’ve hosted this on Github (for lack of better place to put it) here: https://github.com/sashagolds/tutorials/blob/master/2NGINXWordpress1Ghost-OnUbuntu.md

  1. Set up 3 domains (one for each site) and point them at DO by following this tutorial: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean

  2. Follow Tutorial 1 - https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-server-blocks-virtual-hosts-on-ubuntu-14-04-lts 1.1 set up 3 root directories in /var/www/ and 3 server blocks with a TEST index.html in /etc/nginx/sites-available/: 1 for each WP install, and 1 for Ghost. 1.2 verify that each is set up correctly and works

  3. Follow Tutorial 2 - https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-nginx-on-ubuntu-14-04, doing these steps for each of the 2 WP root directories you set up:

    • step 4
    • step 5 You should have already set up 2 server blocks and linked them to your sites-enabled folder in the first tutorial, so you do not have to REDO it for step 5. Instead, you need to use ‘sudo nano’ to open each of the server blocks you created in tutorial 1 and make them look like the example in step 5, WITH A COUPLE EXCEPTIONS:
      • In your second server block make sure you comment out/delete the line ‘listen [::]:80 default_server ipv6only=on;’ AND the directive ‘default_server’ from ‘listen 80 default_server;’ (as per ‘Create the Second Server Block File’ from Tutorial 1)
      • you should not need to execute ‘sudo ln -s…’’ again as you’ve already done it
      • Make sure you restart nginx and php5 after this is done.
  4. Follow Tutorial 3: https://www.digitalocean.com/community/tutorials/how-to-host-ghost-with-nginx-on-digitalocean 3.1. After step 2, use the ls command to verify the ghost files are unzipped into your base root directory for Ghost from tutorial 1 (/var/www/ghost/ or whatever - I got a weird error because I had accidentally moved the files into /var/www/ghost/ghost instead) 3.2. You should already have set up the server block in tutorial 1, so you just need to ‘sudo nano’ your ghost server block. YOU SHOULD DELETE ALL PRE-EXISTING CONTENT FROM TUTORIAL 1 IN THIS BLOCK, and insert:

server { listen 0.0.0.0:80; server_name your-domain-name; access_log /var/log/nginx/your-domain-name.log;

location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header HOST $http_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://127.0.0.1:2368;
    proxy_redirect off;
}

}

as per step 3. Your symlink should already be set up. 3.3. Type nginx -t or sudo nginx -t to make sure your nginx config files have no errors, restart nginx. * DO NOT FOLLOW STEP 4 * Ghost should run if you ‘cd’ to your Ghost root and type ‘npm start’. If it doesn’t, there is probably something wrong with your config/server block, or you are not in your Ghost root folder. While Ghost is running navigate to your domain and you should see your ghost website. If this works, use Ctrl+C in the command line to close Ghost and move on. 3.6. Go to: http://support.ghost.org/deploying-ghost/ and scroll down to the heading ‘Init Script’ and use this instead of step 4. Restart your server with ‘sudo reboot’. Ghost should run on its own now. 3.7. Don’t forget to CONFIGURE Ghost once it is set up using the config.js in your Ghost root as per http://support.ghost.org/config/

Cheers

Hi,

Everything went fine. After installing wordpress I am getting this “Error establishing a database connection” error. Any idea how could i resolve it?

~$ ls -lr /var/www/html

total 176
-rwxrwxr-x  1 sam www-data  3032 Feb  9 12:39 xmlrpc.php
-rwxrwxr-x  1 sam www-data  4026 Oct 24  2013 wp-trackback.php
-rwxrwxr-x  1 sam www-data 25665 Nov 12  2013 wp-signup.php
-rwxrwxr-x  1 sam www-data 11070 Apr  7 13:15 wp-settings.php
-rwxrwxr-x  1 sam www-data  8235 Nov 13  2013 wp-mail.php
-rwxrwxr-x  1 sam www-data 32671 Apr 13 09:06 wp-login.php
-rwxrwxr-x  1 sam www-data  2359 Oct 24  2013 wp-load.php
-rwxrwxr-x  1 sam www-data  2380 Oct 24  2013 wp-links-opml.php
drwxrwxr-x 12 sam www-data  4096 May  8 10:45 wp-includes
-rwxrwxr-x  1 sam www-data  2932 Sep 24  2013 wp-cron.php
drwxrwxr-x  5 sam www-data  4096 Jul 22 13:07 wp-content
-rwxrwxr-x  1 sam www-data  3087 Oct 24  2013 wp-config-sample.php
-rwxrwxr-x  1 sam www-data  3073 Jul 22 12:43 wp-config.php
-rwxrwxr-x  1 sam www-data  4818 Feb 18 13:45 wp-comments-post.php
-rwxrwxr-x  1 sam www-data   271 Jan  8  2012 wp-blog-header.php
drwxrwxr-x  9 sam www-data  4096 May  8 10:45 wp-admin
-rwxrwxr-x  1 sam www-data  4896 Dec 24  2013 wp-activate.php
-rwxrwxr-x  1 sam www-data  7194 May  7 13:43 readme.html
-rwxrwxr-x  1 sam www-data 19930 Apr  9 16:50 license.txt
-rwxrwxr-x  1 sam www-data   418 Sep 24  2013 index.php

Still doesn’t let you update plugins or install them without the ftp screen like others have stated. It would be great if someone could figure this out and update the tutorial, I always run into this problem. chown -R www-data:www-data /var/www/html is what I usually end up doing I think and it works. Please help

Hello @Kamal Nasser,

I managed to install LEMP (with MariaDB+APC cache) and my wordpress site is running at the moment. There are some weird issues though. Some java script depending wordpress plugins such as visual composer are not working properly. Some widgets such as “like and share buttons” are not working properly. In the homepage, if I disable “like and share” widget, the rest of the widgets appear, but if I enable “like and share” widget, then this widget gets loaded incomplete and the rest widgets does not get displayed. Another weird issue again with the widgets, even I enable or disable “like and share” widget, the widgets only get displayeded on main page. I can not manage to display widgets in sub pages, categories, etc… What do you think? Is it something to do with javascript? Or is there a specific “wordpress” configuration for nginx? ps: url rewrite and everything works. permissions and owner is set correctly. everything is fluid except the things I mentioned above.

Kind regards and looking forward to hear from you.

Cagatay

@water8815:

sudo chmod g+w /var/www/html

should be

sudo chmod -R g+w /var/www/html

Try running that instead.

I can’t delete or install plugins after following this tutorial. Then I press delete on a plugin I get a screen that say to me that I need to enter FTO/SSH2 username/password and keys.

Please help me!

Package php5-gd is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

Package libssh2-php is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
However the following packages replace it:
  php-ssh2

Those step may be obsoleted