Building a VPS with WordPress on a LEMP Stack

    Tim Carr
    Share

    With site performance a key metric in Google’s ranking algorithms, more WordPress users are turning to dedicated, managed WordPress hosting such as WP Engine, Media Temple or SiteGround.

    However, these can be expensive solutions for some, with costs starting at ~$30/site per month.

    If you’re comfortable with basic server administration and WordPress, it’s possible to setup your own, inexpensive hosting for small WordPress websites, that matches the performance of managed WordPress hosting providers using a LEMP Stack (Linux, nginx, MySQL, PHP).

    Creating a DigitalOcean Virtual Private Server (VPS)

    This article uses DigitalOcean, but you can equally use services such as Linode, Vultr or a number of other providers. The other sections of this guide will equally apply, regardless of who you’re using.

    First, register an account at https://cloud.digitalocean.com/registrations/new.

    Once completed, click the Create Droplet button:

    Create Droplet

    We’ll use the following settings for our VPS:

    • Droplet Hostname: Enter something meaningful – perhaps your company or website name
    • Select Image: Choose Ubuntu 14.04 x64 – this should be selected by default
    • Select Size: We’ll start with the $5/month option, which comes with 512 MB, 1 CPU, 20 GB SSD and 1000 GB Transfer
    • Select Region: Choose a region appropriate to your business. If you’re US based, select a USA region. If you’re UK based, select a UK region.
    • Available Settings: Enabling the Backups option is recommended, as it’ll take nightly snapshots of your server. If something goes wrong, you can then roll back to the previous day’s backup.

    Droplet Hostname

    Click the Create Droplet button, and you’ll then see on screen progress whilst your VPS (Droplet) is created.

    Creating droplet

    Once completed, you’ll see your VPS on screen. Make a note of the IP address:

    VPS

    You’ll also receive an email with your root password, which you’ll need as well.

    Logging into Your VPS

    Next, let’s login to our VPS.

    NOTE: In our example, to keep things simple, we’ll be using a password to login to our server. I’d recommend looking into using SSH keys for additional security.

    Windows

    For Windows users, download PuTTY. Once downloaded, run PuTTY and enter the following information into the dialog box that appears:

    • Host Name: Enter the IP address you made a note of above
    • Connection type: SSH

    PuTTY Configuration

    Click ‘Open’, and you should be presented with a security alert. This tells us that the server’s host key is new, and therefore asking us if we want to trust it. Click ‘Yes’.

    PuTTY Security Alert

    Next, let’s login as the root user. Enter root for login as, and press ‘Enter’. You’ll then be prompted to enter your password; enter the password that was emailed to you. Don’t worry if you can’t see the password as you type it – this is for security. Press ‘Enter’ when done.

    Mac OS X

    For Mac OS X users, open Terminal and enter the following command, replacing 123.123.123.123 with the IP address above:

    ssh root@123.123.123.123

    You’ll be asked to accept the server key – type yes and press ‘Enter’:

    Server Key

    Next, enter your password and press ‘Enter’.

    Changing the Root Password

    The first time you login to your server, you may be prompted to change the root password:

    Root Password

    Enter the current password, and then enter a new password when prompted.

    UNIX Password

    Installing the LEMP Stack on Ubuntu

    WordPress requires Apache or nginx, PHP and MySQL, as well as a few other components to get things working.

    Ubuntu uses a package manager, which can be thought of as a command line based app store. Before we start downloading and installing components from it, we need to update its catalog by entering the following command:

    sudo apt-get update

    Once completed, we can then install our components:

    sudo apt-get install nginx mysql-server php5-fpm php5-mysql php5-curl php5-gd php5-cgi

    You’ll be asked if you want to continue – type in Y, and press enter.

    Components

    Configuring MySQL

    During the installation process, MySQL will ask you to set a new password for the root database user. Note that this is different from the root login for the server. For security, I’d strongly recommend making this a different password than the root login to your server.

    Once the installation has completed, we need to run two more commands to complete the MySQL installation.

    First, enter:

    sudo mysql_install_db

    Then, enter:

    sudo mysql_secure_installation

    • Type in your current MySQL root password, which you set above.
    • Enter n when asked to change the root password (as we’ve already done this, no need to do it again).
    • Enter Y when asked to remove anonymous users.
    • Enter Y when asked to disallow root login remotely.
    • Enter Y when asked to remove the test database and access to it.
    • Enter Y when asked to reload privilege tables.

    Finally, we need to create a MySQL user and database:

    mysql -u root -p

    Enter your MySQL password when prompted, and if correct, you’ll be presented with the MySQL prompt:

    MySQL

    Let’s create our new database and user – replace ‘password’ with a unique password:

    CREATE DATABASE wordpress;
    CREATE USER 'wordpress'@'localhost' IDENTIFIED BY 'password';
    GRANT ALL PRIVILEGES ON * . * TO 'wordpress'@'localhost';
    FLUSH PRIVILEGES;
    exit

    Configuring PHP

    We need to make a slight alteration to get PHP working with nginx:

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

    Configuring PHP

    Hold down the Ctrl key and press W, and you’ll be asked to type into a Search field. Enter:

    fix_pathinfo and press Enter:

    Configuring PHP

    Change the following line:

    ;cgi.fix_pathinfo=1

    to:

    cgi.fix_pathinfo=0

    To save our changes, hold down the Ctrl key and press X, followed by Y and then the Enter key.

    Configuring nginx

    We need to change nginx’s configuration to get things working with WordPress:

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

    Configuring nginx

    Let’s remove the current configuration. Keep pressing Ctrl and K to cut each line of the configuration file, until it’s blank:

    Removing current configuration

    Next, copy the nginx configuration below and paste it into your Terminal/PuTTY window, remembering to change domain.com to your domain name:

    server {
    # Listen on port 80
    listen 80 default_server;

    Document Root

    root /usr/share/nginx;

    Domain(s)

    server_name www.domain.com;

    Index

    index index.php;

    GZIP Compression

    gzip on;
    gzip_types text/plain image/svg+xml text/javascript application/x-javascript text/xml text/css;
    gzip_vary on;

    Cache Static Files

    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff)$ {
    expires 1y;
    }

    Load File

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

    # Pass the PHP scripts to FastCGI server
    location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    }
    }

    To save our changes, hold down the Ctrl key and press X, followed by Y and then the Enter key.

    Creating a SSH Login

    For security reasons, we don’t want to run WordPress as the root user. Let’s go ahead and create a new server user for that purpose:

    sudo adduser wordpress

    Enter a password for this user, and then just press ‘Enter’ on the other fields.

    Creating a SSH Login

    Next, add our new wordpress user to the www-data group. This is the group used by PHP, so when we go to upload WordPress files, they’ll correctly run:

    sudo usermod -a -G wordpress www-data

    We need to tell PHP which user and group can run PHP files:

    sudo nano /etc/php5/fpm/pool.d/www.conf

    Scroll down until you find the user = www-group line, and change this to:

    user = wordpress

    Configure SSH Login

    To save our changes, hold down the Ctrl key and press X, followed by Y and then the Enter key.

    Restart the Server

    To make sure everything’s working, let’s restart the server:

    reboot

    Login and Install WordPress

    To install WordPress, let’s log back into the server and then enter the following commands:

    cd /usr/share/nginx
    wget http://wordpress.org/latest.tar.gz
    tar xfz latest.tar.gz
    mv wordpress/* ./
    rm latest.tar.gz
    rmdir wordpress

    The above commands download WordPress from wordpress.org, extract/unzip it into the /usr/share/nginx/wordpress folder. We then move the contents of that folder back into /usr/share/nginx before removing the original download file and WordPress directory.

    To avoid file permission issues when trying to install Plugins or upload images, let’s recursively set permissions on nginx’s web accessible root folder to the wordpress user and www-data groups that PHP is configured to use:

    sudo chmod g+w /usr/share/nginx -R
    sudo chown -R wordpress:www-data /usr/share/nginx

    Next, in your web browser, load http://123.123.123.123 (or http://www.domain.com, if you’ve set your domain’s A name record to point to your server’s IP address).

    If everything worked, you’ll see the familiar WordPress configuration screen. Click Let’s go!, and then enter the following information on the next screen:

    • Database Name: wordpress
    • User Name: wordpress
    • Password: [the password you entered when setting up MySQL]
    • Database Host: localhost

    WordPress config

    Click Submit, and if the details are correct, you’ll be asked to run the installation:

    Run Installation

    Enter your ‘Site Title’, ‘Username’, ‘Password’ and ‘Email Address’ before clicking Install WordPress

    WordPress Install

    That’s it!

    Conclusion

    We’ve successfully created a VPS on DigitalOcean, and logged into it over SSH. We’ve then installed nginx, PHP and MySQL, and configured each to work with WordPress.

    We’ve also setup a server user, and granted them permissions on our WordPress installation.

    Finally, we confirmed everything worked by running through the WordPress installation process.