Zach Adams Web Developer and Programmer

Ultimate Guide to Setup a Wordpress Server

May 25, 2014

If you’re anything like me server’s piss you off. Not because they aren’t cool, but because you’ll get to a point where you have everything setup the way you want then you run into an issue that nobody on the internet has experienced. Worse still I’ll have to start over completely with a new distro because the one you want to use isn’t supported by someone or whoever. So this is the Ultimate Guide to Setting up a WordPress Server for complete noobs who know almost nothing about linux or servers. This setup is a simple LEMP stack designed not to be too complicated for beginners. For more High Performance servers see my other post here.

First off you need a server. As opposed to getting a physical computer and setting it up to run linux it’s become far easier to just pay someone else to host it. I can personally vouch for Linode however if you’re looking for something a little cheaper DigitalOcean will do just fine. Sign up and create your droplet/linode.

Now comes a big fork in the road. Which distro? Distros come in all shapes and colors and each run differently. You’ll hear strong opinions on both sides for every distro. However I’m using Ubuntu 14.04 LTS. Why? Because since it’s an LTS it will be supported for quite some time to come, and not a whole lot of distros can claim that. Plus most server guide’s and tutorials use Ubuntu 14.04. If you know what the hell you’re doing, get off my blog, but otherwise use a different distro but be warned a lot of the rest of this tutorial won’t apply.

Download and install Putty so you can connect to your server, just put the IP address and your username should be root and whatever your password is.

Initial Server Setup

The first and most important command to run is

sudo apt-get update

because this will update all your software that we’ll be downloading.

Next we want to install MySQL and PHP using the following commands:

sudo apt-get install mysql-server php5-mysql

When it asks for a username and password for root make sure it’s different from your SSH root password, this is for the MySQL database.

Now we’ll securely install MySQL with this command:

sudo mysql_install_db

And we’ll  set it up with this:

sudo /usr/bin/mysql_secure_installation

When it asks for your root password enter the one you used to setup MySQL with. You don’t need a new root password, you’ll want to remove anonymous users and disallow root login remotely. Remove the test database and access to it and reload the privilege tables and you should be good!

Now let’s setup the MySQL server WordPress will run on. Run this command and enter your root password you used in the installation

mysql -u root -p

Now run the following commands with YOURPASSWORD replaced with your real password

CREATE DATABASE wordpress;
CREATE USER wpuser@localhost;
SET PASSWORD FOR wpuser@localhost= PASSWORD("YOURPASSWORD");
GRANT ALL PRIVILEGES ON wordpress.* TO wpuser@localhost IDENTIFIED BY 'YOURPASSWORD';
FLUSH PRIVILEGES;
exit;

Fantastic now we have a MySQL database to use!

Webserver Setup

Now we’ll install a webserver. There are two popular webservers, Apache and Nginx. Both have proven that they are very capable, however I’ll be using Nginx because of it’s easy configuration and the way it’s event-based vs process-based like Apache. You can read more about the comparison here.

We’ll install Nginx using this:

sudo apt-get install nginx

And we’ll start it using this

sudo service nginx start

Now we’ll install PHP and a bunch of other useful tools!

sudo apt-get install php5-fpm php-pear php5-common php5-mysql php-apc php5-gd

Next we’ll fix a security issue in PHP by opening this file

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

Find this segment by pressing Ctrl+W and searching for this:

cgi.fix_pathinfo=0

Save and close the file.

Now we’ll configure PHP to listen to the correct place. Open up the following file:

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

Find the following line

listen = 127.0.0.1:9000

And change it to

listen = /var/run/php5-fpm.sock

Now you can restart PHP to apply the changes:

sudo service php5-fpm restart

Webserver Configuration

Now we’ll do some tweaks so the webserver will serve the correct files and do caching correctly.

First run the the following command to open the Nginx Configuration file

sudo nano /etc/nginx/nginx.conf

And add the following lines directly under the http subsection

port_in_redirect off;
gzip_types text/css text/xml text/javascript application/x-javascript;
gzip_vary on;

Now we’ll remove the default Nginx website configuration with this command

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

And replace it using this command

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

Enter the following and switch out the bolded sections with your site info

server {
    ## Your website name goes here.
    server_name domainname.com www.domainname.com;
    ## Your only path reference.
    root /home/master/applications/zachadams/public_html/;
    listen 80;
    ## This should be in your http block and if it is, it's not needed here.
    index index.html index.htm index.php;
    
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }
    location = /apple-touch-icon.png { access_log off; log_not_found off; }
    location = /apple-touch-icon-precomposed.png { access_log off; log_not_found off; }
    location ~ /. { deny  all; access_log off; log_not_found off; }

    location / {
        # This is cool because no php is touched for static content
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }
    location ~ .php$ {
        fastcgi_buffers 8 256k;
        fastcgi_buffer_size 128k;
        fastcgi_intercept_errors on;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
    location ~* .(css|js|png|jpg|jpeg|gif|ico)$ { expires 1d; } 
}

Now make a directory and give it the proper permissions using these commands:

mkdir -p /home/master/applications/zachadams/public_html/
chown www-data:www-data /home/master/applications/zachadams/public_html/
chmod 775 /var/www

That’s it, Nginx is configured! Restart Nginx and PHP using these commands:

service nginx restart
service php5-fpm restart

Installing WordPress

Kickass! If anything hasn’t gone wrong yet we’re ready to install WordPress. To start run the following commands:

cd /tmp
wget http://wordpress.org/latest.tar.gz
tar zxvf latest.tar.gz
cd wordpress
mv * /home/master/applications/zachadams/public_html/
cd /home/master/applications/zachadams/public_html/
sudo chown www-data:www-data * -R 
cd ~

Now to setup the WordPress Configuration run

cp /home/master/applications/zachadams/public_html/wp-config-sample.php /home/master/applications/zachadams/public_html/wp-config.php

Now edit the wp-config.php file with:

sudo nano /home/master/applications/zachadams/public_html/wp-config.php

Now find the following and replace it with your MySQL database info from earlier

define(‘DB_NAME’, ‘database_name_here’);
define(‘DB_USER’, ‘username_here’);
define(‘DB_PASSWORD’, ‘password_here’);

Now we can access the WordPress Installation by visiting http://youripaddress.com/wp-admin/install.php and entering the information we used to set it up.

Setting Up Security

You can secure a lot of WordPress using plugins and the like, however we need to ensure that our server is secure first. The most common attack against web servers is against SSH, so we’ll setup some basic protection against brute force and the like using fail2ban.

First let’s install fail2ban:

sudo apt-get install fail2ban

Next let’s copy the configuration file so we can make changes to it:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Now let’s open up the configuration file:

sudo nano /etc/fail2ban/jail.local

Make the following changes:

  • Under ignoreip add any IP Addresses you want fail2ban to ignore
  • Increase the bantime. By default it’s set to 10 minutes however persistent bots may stick around longer so if you’re concerned about anybody getting blocked out you can set it to anywhere from a day to a week
  • maxretry is the number of times somebody has to try to login before getting banned. 3 is the default but you can raise it without much concern

Sweet! Your SSH is now secure against most bots! Restart fail2ban to push the changes into effect.

sudo service fail2ban restart

Varnish Configuration

WARNING: WordPress is now setup and ready  to go, for 90% of all sites you don’t need to continue, you’re done. Read my other post about Essential WordPress Plugins to further improve your site. However if you’re looking at more than 100,000 hits a day you’ll probably want Varnish installed.

For noobs, here’s a description of Varnish. Lets say a WordPress page is like a house. People want to see your house so when they request to see your house PHP build’s it for you and the webserver shows it to the client. Nginx and PHP-FPM do this very quickly and for most sites they’re enough, however if you have 100,000 people wanting to view your site it becomes a huge stress on the server, Nginx and PHP can’t keep up. Basically what Varnish does is takes a picture of the house and gives that to people instead. Everytime a user requests a page that Varnish hasn’t cached yet Nginx and PHP build it and Varnish takes a picture to use. Using Varnish a small server can handle up to anywhere from 100,000 users to 100 million users a day.

Install Varnish with the following

sudo apt-get install varnish

Remove the default configuration with this command

sudo rm /etc/varnish/default.vcl

And replace it with this

sudo nano /etc/varnish/default.vcl

Enter the following configuration file: default.vcl

Now edit the varnish configuration with this command

sudo nano /etc/default/varnish

Find the following section under Alternative 2

DAEMON_OPTS=”-a :6081 
 -T localhost:6082 
 -f /etc/varnish/default.vcl 
 -S /etc/varnish/secret 
 -s malloc,256m”

And replace it with this

DAEMON_OPTS=”-a :80 
 -T localhost:6082 
 -f /etc/varnish/default.vcl 
 -S /etc/varnish/secret 
 -s malloc,64m

Awesome, now we need to change the port Nginx listens to by editing the following file

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

Replace:

listen 80;

With:

listen 8080;

Now restart Nginx and Varnish

service nginx restart
service varnish restart

Kickass! You’re all set! Remember to read my other post about Essential WordPress Plugins especially the section about Varnish.

Comments

Abbas says:
June 24th 2014 at 12:00am
Great guide setting the server up. Do you believe this would also create a fairly secure setup or would you recommend something else on that front?
Iskandar says:
June 12th 2016 at 12:00am
Hi, have some issue with Wordpress login. I guess it's related with the varnish setting. I wonder how to fix it? Thanks.

Leave a Reply

Your email address will not be published. Required fields are marked *