How To Increase Page Load Speed with Apache KeepAlive

The KeepAlive directive for Apache allows a single request to download multiple files. So on a typical page load, the client may need to download HTML, CSS, JS, and images. When KeepAlive is set to “On”, all of these files can be downloaded in a single request. If KeepAlive is set to “Off”, each file download would require it’s own request.

You can control how many files can be downloaded in a single request with the MaxKeepAliveRequests directive, which defaults to 100. If you have pages with a lot of different files, consider putting this higher so that your pages will load in a single request.

One thing to be cautious of when using KeepAlive, is the connections will remain open waiting for new requests once the connection is established. This can use up a lot of memory, as the processes sitting idly will be consuming RAM. You can help avoid this with the KeepAliveTimeout directive, which specifies how long the connections remain open. I generally put this below 5, depending on the average load times of my site.

An important factor when deciding to use KeepAlive is the CPU vs. RAM usage requirements for your server. Having KeepAlive On will consume less CPU as the files are served in a single request, but will use more RAM because the processes will sit idly. Here is an example of KeepAlive settings I use:

KeepAlive             On
MaxKeepAliveRequests  50
KeepAliveTimeOut      3

Once KeepAlive is on you can see the following header in your server’s response:

Connection:  Keep-Alive

How To Increase Page Load Speed with Apache mod_deflate

Apache’s mod_deflate is an Apache module that will compress output from your server before it is sent to the client. If you have newer version of Apache the mod_deflate module is probably loaded by default, but it may not be turned on. To check if compression is enabled on your site, first verify that the module is loaded in your httpd.conf file:

LoadModule deflate_module modules/

Then you can use to following web based tool to verify compression:

For my server, CentOS 6.x, the module was loaded by default but compression was not on until I set up the configuration file. You can place your compression configurations into your httpd.conf file, an .htaccess file, or a .conf file in your httpd/conf.d directory. My base configuration file is as follows:

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/plain 
    AddOutputFilterByType DEFLATE text/css 
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE text/xml

The configuration file specifies that all the html, plain, css, and javascript text files should be compressed before being sent back to the client. When writing your configuration file, you don’t want to compress the images because the images are already compressed using their own specific algorithms and doubling compression just wastes CPU. Depending on the server you are running, you may want a more comprehensive compression schema based on different file types and browsers. More information can be found in the below referenced Apache docs.

Another thing to consider is that while the gzip compression algorithm is fast and efficient for smaller text files, it can be cumbersome on your CPU when trying to compress larger files. Be wary when adding compression to non text files > 50 KB.

When you examine the HTTP headers of your server’s response, you will see the following headers for compressed content:

Content-Encoding: gzip
Vary: Accept-Encoding

Here is another default configuration file taken from Ubuntu 12.10:

<IfModule mod_deflate.c>
    # these are known to be safe with MSIE 6
    AddOutputFilterByType DEFLATE text/html text/plain text/xml    # everything else may cause problems with MSIE 6
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE application/x-javascript application/javascript 
    AddOutputFilterByType DEFLATE application/ecmascript
    AddOutputFilterByType DEFLATE application/rss+xml



How To Set Up mod_security with Apache on Debian/Ubuntu

Installing mod_security

Modsecurity is available in the Debian/Ubuntu repository:

apt-get install libapache2-modsecurity

Verify if the mod_security module was loaded.

apachectl -M | grep --color security

You should see a module named security2_module (shared) which indicates that the module was loaded.

Modsecurity’s installation includes a recommended configuration file which has to be renamed:

mv /etc/modsecurity/modsecurity.conf{-recommended,}

Reload Apache

service apache2 reload

You’ll find a new log file for mod_security in the Apache log directory:

[email protected]:~# ls -l /var/log/apache2/modsec_audit.log
-rw-r----- 1 root root 0 Oct 19 08:08 /var/log/apache2/modsec_audit.log

Configuring mod_security

Out of the box, modsecurity doesn’t do anything as it needs rules to work. The default configuration file is set to DetectionOnly which logs requests according to rule matches and doesn’t block anything. This can be changed by editing the modsecurity.conf file:

nano /etc/modsecurity/modsecurity.conf

Find this line

SecRuleEngine DetectionOnly

and change it to:

SecRuleEngine On

If you’re trying this out on a production server, change this directive only after testing all your rules.

Another directive to modify is SecResponseBodyAccess. This configures whether response bodies are buffered (i.e. read by modsecurity). This is only neccessary if data leakage detection and protection is required. Therefore, leaving it On will use up droplet resources and also increase the logfile size.

Find this

SecResponseBodyAccess On

and change it to:

SecResponseBodyAccess Off

Now we’ll limit the maximum data that can be posted to your web application. Two directives configure these:


The SecRequestBodyLimit directive specifies the maximum POST data size. If anything larger is sent by a client the server will respond with a 413 Request Entity Too Large error. If your web application doesn’t have any file uploads this value can be greatly reduced.

The value mentioned in the configuration file is

SecRequestBodyLimit 13107200

which is 12.5MB.

Similar to this is the SecRequestBodyNoFilesLimit directive. The only difference is that this directive limits the size of POST data minus file uploads– this value should be “as low as practical.”

The value in the configuration file is

SecRequestBodyNoFilesLimit 131072

which is 128KB.

Along the lines of these directives is another one which affects server performance: SecRequestBodyInMemoryLimit. This directive is pretty much self-explanatory; it specifies how much of “request body” data (POSTed data) should be kept in the memory (RAM), anything more will be placed in the hard disk (just like swapping). Since droplets use SSDs, this is not much of an issue; however, this can be set a decent value if you have RAM to spare.

SecRequestBodyInMemoryLimit 131072

This is the value (128KB) specified in the configuration file.

Testing SQL Injection

Before going ahead with configuring rules, we will create a PHP script which is vulnerable to SQL injection and try it out. Please note that this is just a basic PHP login script with no session handling. Be sure to change the MySQL password in the script below so that it will connect to the database:


        $username = $_POST['username'];
        $password = $_POST['password'];
        $con = mysqli_connect('localhost','root','password','sample');
        $result = mysqli_query($con, "SELECT * FROM `users` WHERE username='$username' AND password='$password'");
        if(mysqli_num_rows($result) == 0)
            echo 'Invalid username or password';
            echo '<h1>Logged in</h1><p>A Secret for you....</p>';
        <form action="" method="post">
            Username: <input type="text" name="username"/><br />
            Password: <input type="password" name="password"/><br />
            <input type="submit" name="login" value="Login"/>

This script will display a login form. Entering the right credentials will display a message “A Secret for you.”

We need credentials in the database. Create a MySQL database and a table, then insert usernames and passwords.

mysql -u root -p

This will take you to the mysql> prompt

create database sample;
connect sample;
create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('jesin','pwd');
insert into users values('alice','secret');

Open your browser, navigate to and enter the right pair of credentials.

Username: jesin
Password: pwd

You’ll see a message that indicates successful login. Now come back and enter a wrong pair of credentials– you’ll see the message Invalid username or password.

We can confirm that the script works right. The next job is to try our hand with SQL injection to bypass the login page. Enter the following for the usernamefield:

' or true -- 

Note that there should be a space after -- this injection won’t work without that space. Leave the password field empty and hit the login button.

Voila! The script shows the message meant for authenticated users.

Setting Up Rules

To make your life easier, there are a lot of rules which are already installed along with mod_security. These are called CRS (Core Rule Set) and are located in

[email protected]:~# ls -l /usr/share/modsecurity-crs/
total 40
drwxr-xr-x 2 root root  4096 Oct 20 09:45 activated_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 base_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 experimental_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 lua
-rw-r--r-- 1 root root 13544 Jul  2  2012 modsecurity_crs_10_setup.conf
drwxr-xr-x 2 root root  4096 Oct 20 09:45 optional_rules
drwxr-xr-x 3 root root  4096 Oct 20 09:45 util

The documentation is available at

[email protected]:~# ls -l /usr/share/doc/modsecurity-crs/
total 40
-rw-r--r-- 1 root root   469 Jul  2  2012 changelog.Debian.gz
-rw-r--r-- 1 root root 12387 Jun 18  2012 changelog.gz
-rw-r--r-- 1 root root  1297 Jul  2  2012 copyright
drwxr-xr-x 3 root root  4096 Oct 20 09:45 examples
-rw-r--r-- 1 root root  1138 Mar 16  2012 README.Debian
-rw-r--r-- 1 root root  6495 Mar 16  2012 README.gz

To load these rules, we need to tell Apache to look into these directories. Edit the mod-security.conf file.

nano /etc/apache2/mods-enabled/mod-security.conf

Add the following directives inside <IfModule security2_module> </IfModule>:

Include "/usr/share/modsecurity-crs/*.conf"
Include "/usr/share/modsecurity-crs/activated_rules/*.conf"

The activated_rules directory is similar to Apache’s mods-enabled directory. The rules are available in directories:


Symlinks must be created inside the activated_rules directory to activate these. Let us activate the SQL injection rules.

cd /usr/share/modsecurity-crs/activated_rules/
ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf .

Apache has to be reloaded for the rules to take effect.

service apache2 reload

Now open the login page we created earlier and try using the SQL injection query on the username field. If you had changed the SecRuleEngine directive toOn, you’ll see a 403 Forbidden error. If it was left to the DetectionOnly option, the injection will be successful but the attempt would be logged in the modsec_audit.log file.

Writing Your Own mod_security Rules

In this section, we’ll create a rule chain which blocks the request if certain “spammy” words are entered in a HTML form. First, we’ll create a PHP script which gets the input from a textbox and displays it back to the user.


                echo $_POST['data'];
                <form method="post" action="">
                        Enter something here:<textarea name="data"></textarea>
                        <input type="submit"/>

Custom rules can be added to any of the configuration files or placed in modsecurity directories. We’ll place our rules in a separate new file.

nano /etc/modsecurity/modsecurity_custom_rules.conf

Add the following to this file:

SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_BODY "@rx (?i:(pills|insurance|rolex))"

Save the file and reload Apache. Open in the browser and enter text containing any of these words: pills, insurance, rolex.

You’ll either see a 403 page and a log entry or only a log entry based on SecRuleEngine setting. The syntax for SecRule is


Here we used the chain action to match variables REQUEST_FILENAME withform.php, REQUEST_METHOD with POST and REQUEST_BODY with the regular expression (@rx) string (pills|insurance|rolex). The ?i: does a case insensitive match. On a successful match of all these three rules, the ACTIONis to deny and log with the msg “Spam detected.” The chain action simulates the logical AND to match all the three rules.

Excluding Hosts and Directories

Sometimes it makes sense to exclude a particular directory or a domain name if it is running an application like phpMyAdmin as modsecurity and will block SQL queries. It is also better to exclude admin backends of CMS applications like WordPress.

To disable modsecurity for a complete VirtualHost place the following

<IfModule security2_module>
    SecRuleEngine Off

inside the <VirtualHost> section.

For a particular directory:

<Directory "/var/www/wp-admin">
    <IfModule security2_module>
        SecRuleEngine Off

If you don’t want to completely disable modsecurity, use the SecRuleRemoveById directive to remove a particular rule or rule chain by specifying its ID.

<LocationMatch "/wp-admin/update.php">
    <IfModule security2_module>
        SecRuleRemoveById 981173

Further Reading

Official modsecurity documentation



How To Use MySQL Query Profiling

What is the MySQL slow query log?

The MySQL slow query log is a log that MySQL sends slow, potentially problematic queries to. This logging functionality comes with MySQL but is turned off by default. What queries are logged is determined by customizable server variables that allow for query profiling based on an application’s performance requirements. Generally the queries that are logged are queries that take longer than a specified amount of time to execute or queries that do not properly hit indexes.

Setting up profiling variables

The primary server variables for setting up the MySQL slow query log are:

slow_query_log			G 
slow_query_log_file			G 
long_query_time			G / S
log_queries_not_using_indexes	G
min_examined_row_limit		G / S

NOTE: (G) global variable, (S) session variable

slow_query_log – Boolean for turning the slow query log on and off.

slow_query_log_file – The absolute path for the query log file. The file’s directory should be owned by the mysqld user and have the correct permissions to be read from and written to. The mysql daemon will likely be running as `mysql` but to verify run the following in the Linux terminal:

 ps -ef | grep bin/mysqld | cut -d' ' -f1

The output will likely display the current user as well as the mysqld user. An example of setting the directory path /var/log/mysql:

cd /var/log
mkdir mysql
chmod 755 mysql
chown mysql:mysql mysql

long_query_time – The time, in seconds, for checking query length. For a value of 5, any query taking longer than 5s to execute would be logged.

log_queries_not_using_indexes – Boolean value whether to log queries that are not hitting indexes. When doing query analysis, it is important to log queries that are not hitting indexes.

min_examined_row_limit – Sets a lower limit on how many rows should be examined. A value of 1000 would ignore any query that analyzes less than 1000 rows.

The MySQL server variables can be set in the MySQL conf file or dynamically via a MySQL GUI or MySQL command line. If the variables are set in the conf file, they will be persisted when the server restarts but will also require a server restart to become active. The MySQL conf file is usually located in `/etc or /usr`, typically `/etc/my.cnf` or `/etc/mysql/my.cnf`. To find the conf file (may have to broaden search to more root directories):

find /etc -name my.cnf
find /usr -name my.cnf

Once the conf file has been found, simply append the desired values under the [mysqld] heading:

slow-query-log = 1
slow-query-log-file = /var/log/mysql/localhost-slow.log
long_query_time = 1

Again, the changes will not take affect until after a server restart, so if the changes are needed immediately then set the variables dynamically:

mysql> SET GLOBAL slow_query_log = 'ON';
mysql> SET GLOBAL slow_query_log_file = '/var/log/mysql/localhost-slow.log';
mysql> SET GLOBAL log_queries_not_using_indexes = 'ON';
mysql> SET SESSION long_query_time = 1;
mysql> SET SESSION min_examined_row_limit = 100;

To check the variable values:

mysql> SHOW GLOBAL VARIABLES LIKE 'slow_query_log';
mysql> SHOW SESSION VARIABLES LIKE 'long_query_time';

One drawback to setting MySQL variables dynamically is that the variables will be lost upon server restart. It is advisable to add any important variables that you need to be persisted to the MySQL conf file.

NOTE: The syntax for setting variables dynamically via SET and placing them into the conf file are slightly different, e.g. `slow_query_log` vs. `slow-query-log`. View MySQL’s dynamic system variables page for the different syntaxes. The Option-File Format is the format for the conf file and System Variable Name is the variable name for setting the variables dynamically.

Generating query profile data

Now that the MySQL slow query log configurations have been outlined, it is time to generate some query data for profiling. This example was written on a running MySQL instance with no prior slow log configurations set. The example’s queries can be run via a MySQL GUI or through the MySQL command prompt. When monitoring the slow query log, it is useful to have two connection windows open to the server: one connection for writing the MySQL statements and one connection for watching the query log.

In the MySQL console tab, log into MySQL server with a user who has SUPER ADMIN privileges. To start, create a test database and table, add some dummy data, and turn on the slow query log. This example should be run in a development environment, ideally with no other applications using MySQL to help avoid cluttering the query log as it is being monitored:

$> mysql -u <user_name> -p

mysql> CREATE DATABASE profile_sampling;
mysql> USE profile_sampling;
mysql> INSERT INTO users (name) VALUES ('Walter'),('Skyler'),('Jesse'),('Hank'),('Walter Jr.'),('Marie'),('Saul'),('Gustavo'),('Hector'),('Mike');mysql> SET GLOBAL slow_query_log = 1;
mysql> SET GLOBAL slow_query_log_file = '/var/log/mysql/localhost-slow.log';
mysql> SET GLOBAL log_queries_not_using_indexes = 1;
mysql> SET long_query_time = 10;
mysql> SET min_examined_row_limit = 0;

There is now a test database and table with a small amount of test data. The slow query log was turned on but the query time was intentionally set high and the minimum row examined flag kept off. In the console tab for viewing the log:

cd /var/log/mysql
ls -l

There should be no slow query log in the folder yet, as no queries have been run. If there is, that means that the slow query log has been turned on and configured in the past, which may skew some of this example’s results. Back in the MySQL tab, run the following SQL:

mysql> USE profile_sampling;
mysql> SELECT * FROM users WHERE id = 1;

The query executed was a simple select using the Primary Key index from the table. This query was fast and used an index, so there will be no entries in the slow query log for this query. Look back in the query log directory and verify that no log was created. Now back in your MySQL window run:

mysql> SELECT * FROM users WHERE name = 'Jesse';

This query was run on a non indexed column – name. At this point there will be a query in the log with the following info (may not be exactly the same):


# Time: 140322 13:54:58
# [email protected]: root[root] @ localhost []
# Query_time: 0.000303  Lock_time: 0.000090 Rows_sent: 1  Rows_examined: 10
use profile_sampling;
SET timestamp=1395521698;
SELECT * FROM users WHERE name = 'Jesse';

The query has been successfully logged. One more example. Raise the minimum examined row limit and run a similar query:

mysql> SET min_examined_row_limit = 100;
mysql> SELECT * FROM users WHERE name = 'Walter';

No data will be added to the log because the minimum of 100 rows was not analyzed.

NOTE: If there is no data being populated into the log, there are a couple of things that can be checked. First the permissions of the directory in which the log is being created in. The owner/group should be the same as the mysqld user (see above for example) as well as have correct permissions, chmod 755 to be sure. Second, there may have been existing slow query variable configurations that are interfering with the example. Reset the defaults by removing any slow query variables from the conf file and restarting the server, or set the global variables dynamically back to their default values. If the changes are made dynamically, logout and log back into MySQL to ensure the global updates take effect.


Analyzing query profile information

Looking at the query profile data from the above example:

# Time: 140322 13:54:58
# [email protected]: root[root] @ localhost []
# Query_time: 0.000303  Lock_time: 0.000090 Rows_sent: 1  Rows_examined: 10
use profile_sampling;
SET timestamp=1395521698;
SELECT * FROM users WHERE name = 'Jesse';

The entry displays:

  • Time at which the query was ran
  • Who ran it
  • How long the query took
  • Length of the lock
  • How many rows where returned
  • How many rows where examined

This is useful because any query that violates the performance requirements specified with the server variables will end up in the log. This allows a developer, or admin, to have MySQL alert them when a query is not performing as well as it should [opposed to reading through source code and trying to find poorly written queries]. Also, the query profiling data can be useful when it is profiled over a period of time, which can help determine what circumstances are contributing to poor application performance.

Using mysqldumpslow

In a more realistic example, profiling would be enabled on a database driven application, providing a moderate stream of data to profile against. The log would be continually getting written to, likely more frequently than anybody would be watching. As the log size grows, it becomes difficult to parse through all the data and problematic queries easily get lost in the log. MySQL offers another tool, mysqldumpslow, that helps avoid this problem by breaking down the slow query log. The binary is bundled with MySQL (on Linux) so to use it simply run the command and pass in the log path:

mysqldumpslow -t 5 -s at /var/log/mysql/localhost-slow.log

There are various parameters that can be used with the command to help customize output. In the above example the top 5 queries sorted by the average query time will be displayed. The resulting rows are more readable as well as grouped by query (this output is different from the example to demonstrate high values):


Count: 2  Time=68.34s (136s)  Lock=0.00s (0s)  Rows=39892974.5 (79785949), root[root]@localhost
  SELECT PL.pl_title, P.page_title
  FROM page P
  INNER JOIN pagelinks PL
  ON PL.pl_namespace = P.page_namespace
  WHERE P.page_namespace = N

The data being displayed:

  • Count – How many times the query has been logged
  • Time – Both the average time and the total time in the ()
  • Lock – Table lock time
  • Rows – Number of rows returned

The command abstracts numbers and strings, so the same queries with different WHERE clauses will be counted as the same query (notice the page_namespace = N). Having a tool like mysqldumpslow prevents the need to constantly watch the slow query log, instead allowing for periodic or automated checks. The parameters to the mysqldumpslow command allow for some complex expression matching which help drill down into the various queries in the log.

There are also 3rd party log analysis tools available that offer different data views, a popular one being pt-query-digest.

Query breakdown

One last profiling tool to be aware of is the tool which allows for a complex break down of a query. A good use case for the tool is grabbing a problematic query from the slow query log and running it directly in MySQL. First profiling must be turned on, then the query is ran:

mysql> SET SESSION profiling = 1;
mysql> USE profile_sampling;
mysql> SELECT * FROM users WHERE name = 'Jesse';

After profiling has been turned on, the SHOW PROFILES will show a table linking a Query_ID to a SQL statement. Find the Query_ID corresponding to the query ran and run the following query (replace # with your Query_ID):


Sample Output:

1 starting 0.000046
2 checking permissions 0.000005
3 opening tables 0.000036

The STATE is the “step” in the process of executing the query, and the DURATION is how long that step took to complete, in seconds. This isn’t an overly useful tool, but it is interesting and can help determine what part of the query execution is causing the most latency.

For a detailed outline of the various columns:

For a detailed overview of the various “steps”:

NOTE: This tool should NOT be used in a production environment rather for analyzing specific queries.

Slow query log performance

One last question to address is how the slow query log will affect performance. In general it is safe to run the slow query log in a production environment; neither the CPU nor the I/O load should be a concern ¹ ². However, there should be some strategy for monitoring the log size to ensure the log file size does not get too big for the file system. Also, a good rule of thumb when running the slow query log in a production environment is to leave long_query_time at 1s or higher.

IMPORTANT: It is not a good idea to use the profiling tool, SET profiling=1, nor to log all queries, i.e. the general_log variable, in a production, high workload environment.


The slow query log is extremely helpful in singling out problematic queries and profiling overall query performance. When query profiling with the slow query log, a developer can get an in-depth understanding of how an application’s MySQL queries are performing. Using a tool such as mysqldumpslow, monitoring and evaluating the slow query log becomes manageable and can easily be incorporated into the development process. Now that problematic queries have been identified, the next step is to tune the queries for maximum performance.

cPanel Optimize Website No longer working

When client tries to enable or disable “Optimize Website” in cPanel, this error is shown:

OptimizeWS::optimizews(,) failed: Modification of non-creatable array value attempted, subscript -1 at /usr/local/cpanel/Cpanel/ line 104, <HC> line 52.

Here is a Solution:

To be certain you are not over-writing any existing data:

# mv /home/[cPanel user]/.htaccess /home/[cPanel user]/.htaccess.bak
# echo > /home/[cPanel user]/.htaccess; chown [cPanel user].[cPanel user] /home/[cPanel user]/.htaccess

cPanel >> Software/Services >> Optimize Website should work as expected once there is an existing .htaccess file with some content in /home/[cPanel user]/.htaccess

Let me know if anything else is needed, i’ll make sure it get fixed for you.


How To Use Nginx As Reverse Proxy Server

Nginx is an open source Web server and a reverse proxy server. You can use nginx for a load balancing and/or as a proxy solution to run services from inside those machines through your host’s single public IP address such as In this post, I will explain how to install nginx as reverse proxy server for Apache+php5 domain called and Lighttpd static asset domain called You need to type the following commands on vm00having an IP address only.

DNS Setup

Make sure both and point to public IP address

Install nginx server

Type the following command to install nginx web server:
$ cd /tmp
$ wget
# rpm -iv nginx-release-rhel-6-0.el6.ngx.noarch.rpm
# yum install nginx

Sample outputs:

Loaded plugins: rhnplugin
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package nginx.x86_64 0:1.2.1-1.el6.ngx will be installed
--> Finished Dependency Resolution
Dependencies Resolved
 Package      Arch          Version                   Repository    Size
 nginx        x86_64        1.2.1-1.el6.ngx           nginx        331 k
Transaction Summary
Install       1 Package(s)
Total download size: 331 k
Installed size: 730 k
Is this ok [y/N]: y
Downloading Packages:
nginx-1.2.1-1.el6.ngx.x86_64.rpm                  | 331 kB     00:00
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Warning: RPMDB altered outside of yum.
  Installing : nginx-1.2.1-1.el6.ngx.x86_64                          1/1
Thanks for using NGINX!
Check out our community web site:
If you have questions about commercial support for NGINX please visit:
  Verifying  : nginx-1.2.1-1.el6.ngx.x86_64                          1/1
  nginx.x86_64 0:1.2.1-1.el6.ngx

Configure the nginx web server as reverse proxy

Edit /etc/nginx/conf.d/default.conf, enter:
# vi /etc/nginx/conf.d/default.conf
Add/correct as follows:

## Basic reverse proxy server ##
## Apache (vm02) backend for ##
upstream apachephp  {
      server; #Apache1

## Lighttpd (vm01) backend for ##
upstream lighttpd  {
      server; #Lighttpd1

## Start ##
server {

    access_log  /var/log/nginx/log/www.example.access.log  main;
    error_log  /var/log/nginx/log/www.example.error.log;
    root   /usr/share/nginx/html;
    index  index.html index.htm;

    ## send request back to apache1 ##
    location / {
     proxy_pass  http://apachephp;
     proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
     proxy_redirect off;
     proxy_buffering off;
     proxy_set_header        Host            $host;
     proxy_set_header        X-Real-IP       $remote_addr;
     proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
## End ##

## START ##
server {
   access_log  /var/log/nginx/log/  main;
   error_log   /var/log/nginx/log/;
   root        /usr/local/nginx/html;
   index       index.html;

   location / {
        proxy_pass  http://lighttpd;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;
        proxy_buffering off;
        proxy_set_header        Host  ;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
## END  ##

Turn on Nginx

Type the following commands:
# chkconfig nginx on
# service nginx start

Configure firewall

Set firewall as follows:

  • Drop all INPUT/OUTPUT chain traffic by default.
  • Only open tcp port and/or 443 on eth0 only.
  • Set eth1 as trusted device so that communication take place between nginx reverse proxy and Apache/Lighttpd backend servers.

Run the following command to set and customize firewall as described above:
# system-config-firewall-tui
You can edit /etc/sysconfig/iptables manually and set the firewall too.


Edit /etc/sysctl.conf as follows:

# Execshild
kernel.exec-shield = 1
kernel.randomize_va_space = 1

# IPv4 settings
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Increase system file descriptor limit to
fs.file-max = 50000

# Increase system IP port limits
net.ipv4.ip_local_port_range = 2000 65000

# Ipv6
net.ipv6.conf.default.router_solicitations = 0
net.ipv6.conf.default.accept_ra_rtr_pref = 0
net.ipv6.conf.default.accept_ra_pinfo = 0
net.ipv6.conf.default.accept_ra_defrtr = 0
net.ipv6.conf.default.autoconf = 0
net.ipv6.conf.default.dad_transmits = 0
net.ipv6.conf.default.max_addresses = 1

Load new Linux kernel settings, run:
# sysctl -p

Update / Install Packages Under Redhat Enterprise / CentOS Linux Version 6.x

How do I use yum command to update and patch my Red hat Enterprise Linux / CentOS Linux version 6.x server via RHN / Internet? Can I use up2date command under RHEL 6?

up2date command was part of RHEL v4.x or older version. You need to use yum command to update and patch the system using RHN or Internet. Use yum command to install critical and non-critical security updates as well as binary packages. Login as the root user to install and update the system.

Task: Register my system with RHN

To register your system with RHN type the following command and just follow on screen instructions (CentOS user skip to next step):
# rhn_register

Task: Display list of updated software (security fix)

Type the following command at shell prompt:
# yum list updates

Task: Patch up system by applying all updates

To download and install all updates type the following command:
# yum update

Task: List all installed packages

List all installed packages, enter:
# rpm -qa
# yum list installed

Find out if httpd package installed or not, enter:
# rpm -qa | grep httpd*
# yum list installed httpd

Task: Check for and update specified packages

# yum update {package-name-1}
To check for and update httpd package, enter:
# yum update httpd

Task: Search for packages by name

Search httpd and all matching perl packages, enter:
# yum list {package-name}
# yum list {regex}
# yum list httpd
# yum list perl*

Sample output:

Loading "installonlyn" plugin
Loading "security" plugin
Setting up repositories
Reading repository metadata in from local files
Installed Packages
perl.i386                                4:5.8.8-10.el5_0.2     installed
perl-Archive-Tar.noarch                  1.30-1.fc6             installed
perl-BSD-Resource.i386                   1.28-1.fc6.1           installed
perl-Compress-Zlib.i386                  1.42-1.fc6             installed
perl-DBD-MySQL.i386                      3.0007-1.fc6           installed
perl-DBI.i386                            1.52-1.fc6             installed
perl-Digest-HMAC.noarch                  1.01-15                installed
perl-Digest-SHA1.i386                    2.11-1.2.1             installed
perl-HTML-Parser.i386                    3.55-1.fc6             installed
perl-libxml-perl.noarch                  0.08-1.2.1             base
perl-suidperl.i386                       4:5.8.8-10.el5_0.2     updates

Task: Install the specified packages [ RPM(s) ]

Install package called httpd:
# yum install {package-name-1} {package-name-2}
# yum install httpd

Task: Remove / Uninstall the specified packages [ RPM(s) ]

Remove package called httpd, enter:
# yum remove {package-name-1} {package-name-2}
# yum remove httpd

Task: Display the list of available packages

# yum list all

Task: Display list of group software

Type the following command:
# yum grouplist

Installed Groups:
   Engineering and Scientific
   MySQL Database
   System Tools
   Text-based Internet
   Legacy Network Server
   DNS Name Server
   Dialup Networking Support
   FTP Server
   Network Servers
   Legacy Software Development
   Legacy Software Support
   Development Libraries
   Web Server
   Printing Support
   Mail Server
   Server Configuration Tools
   PostgreSQL Database
Available Groups:
   Administration Tools
   Development Tools
   GNOME Software Development
   X Software Development
   GNOME Desktop Environment
   Authoring and Publishing
   Games and Entertainment
   Java Development
   X Window System
   Windows File Server
   KDE Software Development
   KDE (K Desktop Environment)
   Sound and Video
   FreeNX and NX
   News Server
   Yum Utilities
   Graphical Internet

Task: Install all the default packages by group

Install all ‘Development Tools’ group packages, enter:
# yum groupinstall "Development Tools"

Task: Update all the default packages by group

Update all ‘Development Tools’ group packages, enter:
# yum groupupdate "Development Tools"

Task: Remove all packages in a group

Remove all ‘Development Tools’ group packages, enter:
# yum groupremove "Development Tools"

Task: Install particular architecture package

If you are using 64 bit RHEL version it is possible to install 32 packages:
# yum install {package-name}.{architecture}
# yum install mysql.i386

Task: Display packages not installed via official RHN subscribed repos

Show all packages not available via subscribed channels or repositories i.e show packages installed via other repos:
# yum list extras
Sample output:

Loading "installonlyn" plugin
Loading "security" plugin
Setting up repositories
Reading repository metadata in from local files
Extra Packages
DenyHosts.noarch                         2.6-python2.4          installed
VMwareTools.i386                         6532-44356             installed
john.i386                             installed
kernel.i686                              2.6.18-8.1.15.el5      installed
kernel-devel.i686                        2.6.18-8.1.15.el5      installed
lighttpd.i386                            1.4.18-1.el5.rf        installed
lighttpd-fastcgi.i386                    1.4.18-1.el5.rf        installed
psad.i386                                2.1-1                  installed
rssh.i386                                2.3.2-1.2.el5.rf       installed

Task: Display what package provides the file

You can easily find out what RPM package provides the file. For example find out what provides the /etc/passwd file:
# yum whatprovides /etc/passwd
Sample output:

Loading "installonlyn" plugin
Loading "security" plugin
Setting up repositories
Reading repository metadata in from local files
setup.noarch                             2.5.58-1.el5           base
Matched from:
setup.noarch                             2.5.58-1.el5           installed
Matched from:

You can use same command to list packages that satisfy dependencies:
# yum whatprovides {dependency-1} {dependency-2}
Refer yum command man page for more information:
# man yum