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.