This series of articles is a tutorial to help people with Hosting WordPress on AWS. The aim is to help you set up your own WordPress website hosting on a small AWS instance (t2.micro), then migrate your existing WordPress installs into WordPress or WordPress Multisite (WPMU). The aim is for really high performance websites and great security. This came about because of the poor service I’ve experienced from most web hosts, sometimes taking multiple days to respond even to urgent requests like “help my server is down”. I have four WordPress websites plus a few non-wordpress websites that are PHP or static html, the original plan was to host the Wordpress sites on WordPress Multisite on AWS and the rest using Nginx and HHVM (PHP).
WordPress Multisite was meant to make it easier to update and manage all the WordPress blogs at the same time. In practice it’s fiddly and time consuming but not too difficult to get a set of independent blogs running with different domain names onto WPMU, however there are many drawbacks:
- A lot of plugins don’t work at all on WPMU, and some half work.
- Some themes don’t work well on WPMU.
- It can’t host blogs that need to be on a subdirectory.
- It’s just really fiddly to do some basic things.
So even though I got WPMU working I ended up going with four single site instances of Wordpress. Setup was much quicker and easier, it supports everything I want, and it performs well.
Links to other parts of our tutorial
- Part One, Introduction
- Part Two, Setting up AWS for WordPress with RDS, Nginx, HHVM, PHP, SSMTP
- Part Three, Migrating WordPress Sites Into AWS, including RDS Setup
- Part Four, Wordpress Website Optimization, Nginx Caching and DNS Changes to Go Live
- Part Five, Setting up HTTPS and HTTP/2 using Free Let’s Encrypt Certificates
- Part Six, Setting up CloudFlare free CDN for global caching
Contents of this part of our tutorial
- Important Notes and Recommendations
- Simplifying the Process with Easy Engine
- Nginx, Website, and SSMTP Configuration Files to Download
- Notes, Hints, and Tips
Since I’m an AWS certified architect that seemed like a great place to get a server when I got sick of shared hosting. With the AWS “free tier” giving a year of free service with the t2.micro instance type and associated services I wondered if I could make this very modest setup with 1GB RAM and 10% of a Xeon CPU (burstable) work for the needs of the dozen or so websites I run. In case you’re wondering, the answer turned out to be “yes, quite easily”, now I’m wondering if it could be done on the new t2.nano instances with 500MB RAM.
I don’t want just any web server, I want a fast, secure web server, as performance and https is important to SEO. There are a bunch of prebuilt AWS AMIs (Amazon Machine Images) that would do a lot of this for me, but half of the point of this exercise is to learn more about how Linux works. It’s also important for me to understand how it works so if something breaks on my production websites I can fix it reasonably easily. Here’s the list of technologies I want to use any why:
- Amazon AWS, for the control and flexibility, and the great intro price and very reasonable ongoing price. Specifically we want to use EC2 for compute power, EBS (Elastic Block Store) disks for storage (SSDs), RDS (Relational Database Server) running MySQL or MariaDB for data storage (though I may move back to MySQL on the server once the free tier RDS expires)
- WordPress Multisite, because many of my websites run on Wordpress and I’m tired of having to do updates everywhere
- Nginx, which is a super fast easy to configure web server that’s simple and powerful that uses relatively little memory
- MariaDB, a version of MySQL by the original creators rather than Oracle’s MySQL. This will initially be running in the Amazon RDS system, but it may get moved to the server once my free tier allowance finishes.
- Let’s Encrypt, to provide the server certificate that makes HTTPS possible (and as a bonus is free)
- CloudFlare, a CDN with a free tier that will hugely accelerate our website using it’s network of over 100 servers in many countries. CloudFlare will present https (using http2) to our website users, and will connect to our server using https to our server to securely download the web pages and resources hopefully using http 2.0. It also protects the website against various security issues and DDOS attacks – if some serious widespread issue happens they will often change their systems to protect all their customers before it’s even widely known.
This tutorial doesn’t look at AWS auto scaling because I don’t need it – though it’s not all that difficult to achieve that’s for you to work out. I also haven’t used Cloudfront, the Amazon CDN, as I’ve used the free CloudFlare plan for a couple of years and it works great. CloudFlare has paid plans that add extra features and give you better support.
I looked for a tutorial, and there are bits and pieces available that will be essential to help me achieve this, but there’s no one tutorial that will even get close to achieving this for me. It seems like something others could be interested in, so I thought I’d create a tutorial or guide. This has turned into a mammoth effort that’s taken more than two months to write, including many full days.
Warning – This is Complex
The thing about AWS and managing your own server is it’s not particularly simple. If you’re not comfortable with Linux, SSH, IP addresses, Unix permissions, CIDR and configuring software using command line tools like vi/vim/nano this probably isn’t something you should attempt. As such we’ve kept the basics of getting an AWS server running fairly brief, mostly linking to Amazon’s documentation – if you can’t puzzle your way through in 1-3 hours it’s probably not for you.
Warning Two – No Warranty or Fitness for Purpose Implied
This tutorial is my best effort to help others, no warranty or guarantee applies. There may be security holes, performance issues, you may have significant down time, and by following it you may install an automated process that actually manages to sell your house and spend the money in ‘vegas. Any risk is yours to take. If your server is important to you or your business you should invest in a thorough security review by a professional security firm, and have this work either done or reviewed by an experienced system administrator.
Important Notes, Recommendations, and Reflection
- Take regular snapshots of your EBS volumes – ideally daily while you’re setting things up. They’re differential so they don’t take much space, and they’ve saved me a couple of times when I was a bit liberal with my use of sudo and changing permissions. There’s probably a way to automate this, I’ll look into it some time.
- After going through this whole process my advice is not to bother with WordPress Multisite if you just have a few independent blogs to run. Yes, it works, but it’s much more effort than just setting up a few independent WordPress blogs. Yes it means securing, maintaining and backup up each blog separately, but I think for most people the small overhead of this is outweighed by the complexity of WPMU. Technical people will probably be ok with WPMU. Maybe in a few years when WPMU has matured some more it will be easier. If you want to run a large network of blogs, especially with automatic signup by users, then WPMU is worth a look.
- If I did this again it would probably be with a different Linux, probably Ubuntu LTS, as there’s much more help and community support available and the repositories and software available are more up to date. Amazon Linux is based on an unspecified version of Red Hat Enterprize Linux and is similar to Centos 6 or 7 (Amazon doesn’t say exactly), and finding help is relatively difficult.
- I’ve stopped using HHVM, replaced it with PHP 5.6. This is because HHVM 3.6.6 regularly uses all available RAM, stops responding, and gets restarted by Monit. PHP 5.6 with the opcache is only slightly slower, and should be much more reliable. I spent around 8 hours trying to upgrade to a newer version, but Centos isn’t a support platform so you need a third party repository. I eventually found one, but gave up before I got it working properly on my spot instance. Building HHVM is a significant task, and takes a loooong time even on an m4.2xl instance, and even following various instructions I couldn’t get it working.
- I’d use an install system that set everything up rather than doing it from scratch, but the point of this exercise was to learn, not just to get a server working.
- I’m likely to dump Amazon Linux and move to Ubuntu 16.04 with EasyEngine or similar when it’s available.
Simplifying the Process With Easy Engine
Once you have you server up and running you can use EasyEngine to quickly and easily install Nginx, WordPress, all dependencies, and configure everything. It’s a much quicker way of doing this portion of the install. I found that part wasn’t that time consuming – the more difficult parts are importing your site in, optimizing it for great performance, and troubleshooting. It’s definitely worth using if you want to accelerate that part of the install!
Resources and Configuration Files To Download
Here you can download the various configuration files I ended up with. These have been obfuscated slightly to protect my privacy and security, but should work with very few obvious modifications. If they don’t please comment and I’ll try to help.
Note that half way through writing this tutorial I moved my webroot from /usr/share/nginx/html to /var/www just because I got tired of typing the former, so the tutorial and files supplied here might be slightly inconsistent. I also moved regions from Sydney to Oregon so screenshots may have some variety. These are final configurations that I went live with – they may be updated in future as I refine the configuration further.
Click the links below to download the files. Our current theme doesn’t make these links obvious, but they work.
- Nginx main configuration.
- Nginx startup script (goes in /etc/init.d to enable the command “sudo service nginx start”.
- Nginx site files for WordPress Multisite https configuration, WordPress Multisite Optimised HTTP configuration, Nginx Configuration for PHP and WordPress single site, Nginx Static Website Configuration, WordPress Single Site, and Nginx default site configuration
- Monit main configuration and the Monit monitors configuration
- Cron hourly configuration (changes nginx cache permissions)
- HHVM configuration, and HHVM Configuration for Access Logging (NB: to activate access logging you need to change your init.d/hhvm file as per below)
- init.d startup files for nginx, hhvm, and sshd
- SSMTP config file, \root\.muttrc config, and \root\.muttrc config file
- Siege config file (from \root\.siegerc), siege URLs file.
These configuration files may be updated occasionally. Version history is below.
Configuration file update log:
- 26 March 2016. Updated all nginx config files to exclude some user agents from access log, and so redirect servers log to the same file as the main access log. Updated hhvm to add a timezone. Updated monit to match the new version.
Linux Notes, Hints, and Tips
Here are a few Linux tips I’ve found useful while going through this process:
- Be super careful when you’re root, especially changing ownership and permissions. Some software is really sensitive about owners, groups, and permissions, if you mess it up badly you may have to go back to a backup. Even using “everyone can do anything to this file” permissions (777) some software won’t work.
- A useful command to run as root without having to type “sudo” all the time is “sudo -i”
- To edit a file in a Unix console you’ll need vi, vim, or nano. There are plenty of tutorials on the ‘net about those – take your pick of editor.
- To list all packages installed on Amazon Linux use the command “yum list installed”. To find if a specific package (eg nginx) use “yum list installed | grep nginx”
- Some useful mysql commands for the console include “SELECT User FROM mysql.user;” (to list all MySQL users) “use (databasename);” (to select a database), “show tables;” (to list the tables in the selected database), “select * from wp_pts_users;” (to show all wordpress users)
- Find out which group a user is in with “groups (username)” (eg groups nginx)
Please use the links at the top of the page to navigate to the next part of the tutorial.