How did I setup a wordpress hosting in AWS using nginx+php-fpm

Well, for a long time I have been looking for the perfect WordPress hosting setup. I end up using the combination of nginx, php-fpm and memcached. The other option is using apache and php while the difference is the way these two web server handle request and use php. As far as I understand, nginx has a more simple way of dealing with php using php-fpm and the way it handle modules and caching boosts the performance.

So even though the nginx configuration is like a nightmare I start giving it a try and after so many challenges I end up making it working! Obviously, the apache configuration is much simpler but if you need to satisfy millions of users then nginx can be a better option.

In my experience I used an EC2 t2.medium instance (just for 5 hosts) and Amazon Linux AMI as OS. So now we are going to install the services and modules before starting the configurations.

First we install the followings and create a cache directory for nginx fast-cgi:

yum install nginx
yum install php56-fpm
mkdir -p /var/cache/nginx/
yum install php56-mysqlnd #if needed
yum install memcached #if needed

(I assumed your MySQL is hosted in another server.)

And then we create the root directory for websites with a simple default html file. The nginx process is the owner along appropriate permissions cause no one supposed to change it except us!

mkdir -p /var/nginx/sites/default
echo 'You should not be here!' > /var/nginx/sites/default/index.html
chown -R nginx:nginx /var/nginx/sites/default
chmod -R 701 /var/nginx/sites/default 

and then making the website root directory with right owner and permissions (the ftp-user group contains all users for that group and all of them only are able to access to this directory).

mkdir -p /var/nginx/sites/abcd.com
chown -R nginx:abc-ftp /var/nginx/sites/abcd.com
chmod -R 711 /var/nginx/sites/abcd.com 

Appendix 1 and 3 should be available in proper directory and appendix 2 template should be used for adding additional websites to host.

And finally test the configurations: service nginx configtest

Now it’s time to start the engine! service nginx start; service php-fpm start;

now copy your wordpress source in /var/nginx/sites/abcd.com/ folder and you should be able to browse your website(s) and just use the wizard to setup database connection.

Once you entered the wordpress admin panel you can install W2 Total Cache plugins which can be configured to use memcached for a boost in performance. After all the performance is mostly about caching so maybe in another post I explain more about wordpress caching options.

Please remember to change the user and group in /etc/php-fpm.d/www.conf file:
user = nginx
group = nginx

Continue reading

How to test PHP sessions in Memcached?

Well, just run this code :D

<?php
    header('Content-Type: text/plain');
    session_start();
    if(!isset($_SESSION['visit']))
    {
        echo "This is the first time you're visiting this server\n";
        $_SESSION['visit'] = 0;
    }
    else
            echo "Your number of visits: ".$_SESSION['visit'] . "\n";

    $_SESSION['visit']++;

    echo "Server IP: ".$_SERVER['SERVER_ADDR'] . "\n";
    echo "Client IP: ".$_SERVER['REMOTE_ADDR'] . "\n";
    print_r($_COOKIE);
?>

Preparing web server in Amazon Linux

Once you install an EC2 instance with Amazon Linux AMI you will need to install web server and other requirement of setting up a website.

We are going to install httpd (webserver), php (scripting), mysqli (db client) and memcached (caching).

First things first, we do a clean up in case this has been used before:

yum update -y 
yum remove -y mysql*
yum remove -y http*
yum remove -y php*

and let the installation begin:

yum install -y httpd24 
yum install -y mod24_security memcached 
yum install -y php55 php55-mysqlnd php55-pecl-memcached php-pear php55-gd php55-devel php-channel-phpunit php-channel-amazon php55-cli  
yum install -y mysql55 mysql55-devel mysql55-libs 

Next, we need to do some httpd configurations like enabling mod-rewrite (if we need it!) and turning off signatures for security:

vi /etc/httpd/conf/httpd.conf

We a re going to add this to end of the file:

# Disable ETag headers
FileETag none

# Hide Apache and PHP info
Header unset Server
Header unset X-Powered-By

# Don't expose server versions
ServerSignature Off
ServerTokens Prod

# Enable server-status for internal IP
<Location /server-status>
   SetHandler server-status
   Order Deny,Allow
   Deny from all
   Allow from 127.0.0.1
</Location>

# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
KeepAlive On

# Configure /var/www/html
<Directory "/var/www/html">
	Options FollowSymLinks
	AllowOverride All
	DirectoryIndex index.html index.php
	Order allow,deny
	Allow from all
</Directory>

We also need to do minor php configurations to enable sessions being saved in centralized memcached server (if you dont want to store sessions in memcached then just ignore this):

vi /etc/php.ini

And adding/editing the followings. The time zone should be changed to your own timezone, memory limit is 128 by default and you may want to increase it.

date.timezone = Asia/Kuala_Lumpur
memory_limit = 256M
session.save_handler = memcached
session.save_path = "192.168.1.2:11211"

*Please note, in case you are going to use memcache instead of memcached (which are two different things) you should specify protocol in save_path (i.e. tcp://192.168.1.2:11211).

At the end we need to do some Linux stuff!! Here is the explanation in order: making www group, adding current user to that group, take ownership of website directory, grant default permissions to website directory, grant specific permission to directories, grant specific permission to files, auto-start httpd service, auto-start memcached service, start httpd, start memcached.

groupadd www
usermod -a -G www ec2-user
chown -R root:www /var/www
chmod 2775 /var/www
find /var/www -type d -exec chmod 2775 {} +
find /var/www -type f -exec chmod 0664 {} +
chkconfig httpd on
chkconfig memcached on
service httpd start
service memcached start

echo "<?php phpinfo(); ?>" > /var/www/html/info.php

And we are all set ;)