Million of visitors per day with a super cheap php mysql server using nginx and varnish

Million of visitors per day with a super cheap  php mysql server using nginx and varnish
by Janeth Kent Date: 28-05-2013 apache ubuntu nginx varnish mysql php

These instructions are the rather verbose, but hopefully easy enough to follow, steps to build a new Linux server using Varnish and Nginx to build a php application on a cheap server , all costing under $15 a month, capable of sustaining million hits per day, (we use blitz.io to test it).

Million hits per day on a cheap virtual server

Install Ubuntu 11.10 (Oneiric) on a new virtual private server- it needs to be 11.10 for all the packages that I’m going to list to work out of the box, but it’s all possible to do with other distributions.

You can use Amazon EC2 to build the test server, but Linode are also very good.

Let's start

Public DNS Name: server1.yourserver.com (example)
Public IP Address: 123.123.255.255 (example)

Login to the server as root

login as ubuntu via ssh, then run the sudo -i command to enter as root

ssh [email protected]
sudo -i

Configure a firewall first

It’s important to configure a firewall, since we’re going to be installing various network services which by default listen on all interfaces.For Ubuntu, this is easy, simply use the ufw package.

Execute the following commands to configure it:

ufw allow ssh
ufw allow http
ufw logging off
ufw enable

Once this is done, your server has a relatively secure firewall, though it’s worth looking at fail2ban to prevent brute force password attacks.

Note:If you’re using Amazon EC2, you’ll also need to open the Security Group to allow traffic on port 80. You can do this using the AWS Security Groups Console, you might need to change the region. Select the security group you used when you started the instance, and then click “Inbound”, then select “HTTP” from the drop down menu, then finally click “Add Rule”. You don’t need to restart the instance for it to take effect.

Install and Configure MySQL

apt-get update
apt-get install mysql-server

When prompted, set a mysql “root” user password

mysql -u root -p

When prompted, enter your newly set root password

At the mysql> prompt, run the following 4 commands, create your database and replacing ENTER_A_PASSWORD with a password of your own

CREATE DATABASE mydatabase;
GRANT ALL PRIVILEGES ON mysatabase.* TO "my_user"@"localhost" IDENTIFIED BY "ENTER_A_PASSWORD";
FLUSH PRIVILEGES;
EXIT

That’s MySQL installed, ready for the PHP and Web server installation (nginx).

Install and configure PHP

We need to install not just PHP, but the PHP FPM system, APC, and the MySQL module

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

Edit /etc/php5/fpm/php.ini and add these lines at the bottom:

[apc]
apc.write_lock = 1
apc.slam_defense = 0

Edit /etc/php5/fpm/pool.d/www.conf

Replace

listen = 127.0.0.1:9000

with

listen = /dev/shm/php-fpm-www.sock

Below that, insert these 3 lines

listen.owner = nginx
listen.group = nginx
listen.mode = 0660

Then, further down in the same file, replace these 2 lines

user = www-data
group = www-data

with

user = nginx
group = nginx

Save the file, PHP FPM is now complete, but it won’t work until we install nginx, so don’t worry about starting it now.

Install and Configure Nginx

Instructions based on the Nginx website.

Download the nginx secure key to verify the package

cd /tmp/
wget http://nginx.org/keys/nginx_signing.key
apt-key add /tmp/nginx_signing.key

Add the sources to the APT sources file by running these 2 commands (the >> is important!)

echo "deb http://nginx.org/packages/ubuntu/ lucid nginx" >> /etc/apt/sources.list
echo "deb-src http://nginx.org/packages/ubuntu/ lucid nginx" >> /etc/apt/sources.list

Download and install nginx by running

apt-get update
apt-get install nginx

When that completes, nginx will be installed, but needs configuring for your php app

nginx configuration files are in /etc/nginx

First, edit /etc/nginx/nginx.conf

Inside the http section , insert the following line so that when you later add varnish in front, things don’t break all over the place:

port_in_redirect off;

Next, cd to /etc/nginx/conf.d and create a new file, /etc/nginx/conf.d/drop with the contents of the following (configuration good for wordpress too)

# Most sites won't have configured favicon or robots.txt
# and since its always grabbed, turn it off in access log
# and turn off it's not-found error in the error log
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; }

# Rather than just denying .ht* in the config, why not deny
# access to all .invisible files
location ~ /\. { deny  all; access_log off; log_not_found off; }

Then, replace /etc/nginx/conf.d/default.conf with the contents of the following changing all entries for domainname.com with your own domain name (there’s 3 entries, including 1 near the bottom)

server {
    ## Your website name goes here.
    server_name domainname.com www.domainname.com;
    ## Your only path reference.
    root /var/www/;
    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;

    include conf.d/drop;

        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:/dev/shm/php-fpm-www.sock;

        }

}

Make a directory, /var/www/ and set the ownership:

mkdir -p /var/www/
chown nginx:nginx /var/www/
chmod 775 /var/www

That’s nginx configured, restart it and the PHP FPM service by running:

service nginx restart
service php5-fpm restart

Now, you’re actually ready to start your php app!

Change the owner of your app directory

chown -R nginx:nginx /var/www

Once it’s done, if you’ve not had any errors and your domain name is pointing at the right IP (this is important!), then you’ll be able to visit your domain and see your homepage.

Even if the server is running, but it’s still too slow for our goal

Time to install varnish 3!

apt-get install varnish

Edit /etc/varnish/default.vcl replace the contents with this content

# This is a basic VCL configuration file for varnish.  See the vcl(7)
# man page for details on VCL syntax and semantics.
# 
# Default backend definition.  Set this to point to your content
# server.
# 
# THIS IS VALID FOR WORDPRESS CONFIGURATION
# 

backend default {
    .host = "127.0.0.1";
    .port = "8080";
	.connect_timeout = 600s;
	.first_byte_timeout = 600s;
	.between_bytes_timeout = 600s;
	.max_connections = 800;
}


acl purge {
        "localhost";
}

sub vcl_recv {
	set req.grace = 2m;

  # Set X-Forwarded-For header for logging in nginx
  remove req.http.X-Forwarded-For;
  set    req.http.X-Forwarded-For = client.ip;


  # Remove has_js and CloudFlare/Google Analytics __* cookies.
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|has_js)=[^;]*", "");
  # Remove a ";" prefix, if present.
  set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");



# Either the admin pages or the login
if (req.url ~ "/wp-(login|admin|cron)") {
        # Don't cache, pass to backend
        return (pass);
}


# Remove the wp-settings-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

# Remove the wp-settings-time-1 cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

# Remove the wp test cookie
set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");

# Static content unique to the theme can be cached (so no user uploaded images)
# The reason I don't take the wp-content/uploads is because of cache size on bigger blogs
# that would fill up with all those files getting pushed into cache
if (req.url ~ "wp-content/themes/" && req.url ~ "\.(css|js|png|gif|jp(e)?g)") {
    unset req.http.cookie;
}

# Even if no cookies are present, I don't want my "uploads" to be cached due to their potential size
if (req.url ~ "/wp-content/uploads/") {
    return (pass);
}

# Check the cookies for wordpress-specific items
if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
        # A wordpress specific cookie has been set
    return (pass);
}



	# allow PURGE from localhost
	if (req.request == "PURGE") {
		if (!client.ip ~ purge) {
			error 405 "Not allowed.";
		}
		return (lookup);
	}


	# Force lookup if the request is a no-cache request from the client
	if (req.http.Cache-Control ~ "no-cache") {
		return (pass);
	}


# Try a cache-lookup
return (lookup);

}

sub vcl_fetch {
	#set obj.grace = 5m;
    set beresp.grace = 2m;

}

sub vcl_hit {
        if (req.request == "PURGE") {
                purge;
                error 200 "Purged.";
        }
}

sub vcl_miss {
        if (req.request == "PURGE") {
                purge;
                error 200 "Purged.";
        }
}

Edit /etc/default/varnish

Change the section

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

to

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

Next, we need to edit the nginx configuration to listen on port 8080, instead of port 80 – Varnish is going to be running on port 80 instead.

Edit /etc/nginx/conf.d/default.conf and replace

listen 80;

with

listen 8080;

Save the file, then run

service nginx restart
service varnish restart

There it is, million hits per day on a box costing less than $20 a month, all thanks to varnish and nginx, easy!

 
by Janeth Kent Date: 28-05-2013 apache ubuntu nginx varnish mysql php hits : 7879  
 
Janeth Kent

Janeth Kent

Licenciada en Bellas Artes y programadora por pasión. Cuando tengo un rato retoco fotos, edito vídeos y diseño cosas. El resto del tiempo escribo en MA-NO WEB DESIGN AND DEVELOPMENT.

 
 
 

Related Posts

How to fix excessive MySQL CPU usage

What happens if we realise that a series of databases that we thought were optimised through the use of indexes, have begun to consume CPU usage time of a server…

How to connect to MySQL with Node.js

Let's see how you can connect to a MySQL database using Node.js, the popular JavaScript runtime environment. Before we start, it is important to note that you must have Node.js installed…

How To Use Varnish As A Highly Available Load Balancer On Ubuntu 20.04 With SSL

Load balancing with high availability can be tough to set up. Fortunately, Varnish HTTP Cache server provides a dead simple highly available load balancer that will also work as a…

htaccess Rules to Help Protect from SQL Injections and XSS

This list of rules by no means is a sure bet to secure your web services, but it will help in preventing script-kiddings from doing some basic browsing around. MySQL injection…

MySQL 8.0 is now fully supported in PHP 7.4

MySQL and PHP is a love story that started long time ago. However the love story with MySQL 8.0 was a bit slower to start… but don’t worry it rules…

Linux For Dummies: Permissions

In the previous articles I made a short introduction to the Unix world and in the following article I have dealt with the basic commands for the file system management. Today we are…

Linux for Dummies: Ubuntu Terminal

I introduced in the previous article, available here, the basic concepts concerning the Linux world. Today we are going to have a look to some basic operations that we can perform…

Must-Have htaccess Tips for you to Avoid Duplicate Content on Your Site

In order to be able to implement these tips it is necessary that your Apache server already has the mod_rewrite module activated. mod_rewrite and .htaccess are used together so that…

The Best RSS Readers for Ubuntu

Even if most of the tech experts actively claim that RSS (Rich Site Summary) is dead especially after Google Reader was discontinued 5 years ago but it isn’t yet as…

How to install Letsencrypt Certificates with Certbot in Ubuntu

In this article we will explain how to install, manage and configure the SSL Security certificate, Let's Encypt in NGINX server used as proxy. This certificate is free but does…

How to Set up a Fully Functional Mail Server on Ubuntu 16.04 with iRedMail

Setting up your own mail server from scratch on Linux is complex and tedious, until you meet iRedMail. This tutorial is going to show you how you can easily and…

GIMP 2.10 released: Features 32-bit support, new UI and A Ton Of Improvements

It's been over a half-decade since the GIMP 2.8 stable debut and today marks the long-awaited release of GIMP 2.10, its first major update in six years. And among other…