Nginx for dummies

By | May 19, 2017

I was installing nginx as reverse proxy again. And find that some crib note will be nice.


In theory you have to request the package which resolve all dependencies. But I found that EPEL has nginx version 0.6.39 and I go to make nginx from sources.

First download the latest version from

tar zxf nginx-0.8.53.tar.gz
cd nginx-0.8.53

Then run ./configure and look for misses.
I need pcre and md5. So I was downloaded them ( md5 in openssl )

sudo yum install pcre-devel.x86_64
sudo yum install openssl-devel.x86_64

then configuring again with all paths, compiling and install

make clean
./configure \
prefix=/usr \
–conf-path=/etc/nginx/nginx.conf \
–http-log-path=/var/log/nginx/access.log \
–error-log-path=/var/log/nginx/error.log \
–pid-path=/var/run/nginx/  \
–lock-path=/var/lock/nginx.lock \
–http-client-body-temp-path=/var/tmp/nginx/client/ \
–http-proxy-temp-path=/var/tmp/nginx/proxy/ \
user=nginx \
group=nginx \
–with-sha1-asm \
–with-sha1=/usr/include \
–without-http_fastcgi_module \
–without-http_geo_module \
–without-http_autoindex_module \
–without-http_memcached_module \
–without-http_ssi_module \
–without-http_upstream_ip_hash_module \
–with-http_sub_module \
–with-http_ssl_module \
–with-http_gzip_static_module \
sudo make install

I have RHEL so paths specific for RHEL. Other variants you can find in wiki. I remove non-required fastcgi, geo, memcached и ssi. I dont plan to balance loading and making indexes, so upstream_ip_hash and autoindex removed, ssl added just in case, stub_status for nice graphs on, and gzip_static checking gzip placed near so we can make precache. Sub allow to add or remove something quickly. The rest is standard.

Some compile warnings for depricated function we are ignoring :)

Because install is not adding user make it manually

sudo useradd -M -r -d /var/www -s /sbin/nologin -c ‘Nginx unprivileged user’ nginx

group will auto add

Configuring proxy-pass for Apache

( in case of WordPress )

In default configuration we have to change

worker_processes  3;

by available cores

define log format:

    log_format  main  ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for” “$gzip_ratio”‘;

In the end the gzip ratio for analysis

adding gzip and define cache place with 100MB size

    proxy_cache_path  /var/tmp/nginx/proxy/one  levels=1:2   keys_zone=one:100m;

gzip  on;
gzip_http_version 1.1;
gzip_comp_level 5;
gzip_types  text/plain text/css
application/x-javascript text/xml
application/xml application/xml+rss

Define default server rewrite any unknown to main server

    server {
listen 80 default_server;
server_name _;
rewrite  ^$request_uri?;

Main server

    server {
listen 80;
root /www/main;

access_log  /var/log/nginx/main.access.log  main;

Errors returned from static file for hide any private info.

        error_page  404 500 501 502 504 /error.html;

location = /error.html {

Adding status url

         location = /nginx_status {
stub_status on;
access_log off;
deny all;

Maintenance page with 503 status code to avoid indexing the page

         error_page 503 /maintenance.html;

location /maintenance.html {

and define the main location with proxying to backend

         location / {

if (-f $document_root/maintenance.html) {
return 503;

proxy_intercept_errors     on;

proxy_cache            one;
proxy_cache_key        “$request_method|$http_if_modified_since|$http_if_none_match|$host|$request_uri”;
proxy_cache_valid      200 301 302 304 1h;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;


Take attention for proxy_intercept_errors all errors from backend rewrote but keep status unchanged.

Key for cache is very important. $host and $request_uri is required. $request_method protect GET from HEAD requests. $http_if_modified_since and $http_if_none_match protect normal answers with 200 status from empty 304 unchanged response.

Static files nginx should find them-self. WP add version as parameter for browser cache update, so adding the version to regexp.

         location ~* ^.+\.(jpg|jpeg|gif|css|png|js|ico|xml|swf)(\?.*)?$  {
expires max;

To prevent apache config downloading

         location ~ /\.ht {
deny  all;

Here you can download full sample of nginx.conf. You can also will find the development server with backend errors.

Here you can find standard script for manage nginx. I was take the script from some site ages ago probably from

In Apache config you have to change port to 8080 just in example :)

sudo sed -i s/80/8080/ /etc/httpd/conf/httpd.conf

Run and check

So we can add nginx to system startup and start

sudo chmod +x /etc/rc.d/init.d/nginx
sudo /sbin/chkconfig –add nginx
sudo /sbin/chkconfig –level 35 nginx on
sudo /etc/init.d/httpd stop
sudo /etc/init.d/nginx start
sudo /etc/init.d/httpd start

Usually on working server I start nginx first on 8080 to check the interworking every time some plugins do something wrong.

Check list:

  • normal page. You can put phpinfo for avoid any WP features
  • errors like 404 and 500 ( trigger_error )
  • /maintenance.html
  • page with no-cache eg /wp-login.php, authorizing and comments
  • ajax can be cached or not
  • plugins
  • static files check extentions

WordPress is good CMS in term of caching management. Every private page has no-cache in the headers in login, admin or comments pages. Additionally every logged user receive no-cache every time take attention for this when you are checking the proxy cache and use private tabs in your browser to avoid authorizing cookies.

Additionally you have to note about ajax requests. If private it should contain no-cache ( WP has function nocache_headers() ). Otherwise you have to take attention on caching key because body is not included into key you have to put something in the request url like ajax.php?cache_key=val1,val2,val3. Better to add some hash function, but just values is acceptable. Note that different requests will have different request url and vise versa.

But not all is perfect. For example comments cached and will not updated immediately after new comment come in. But in general this configuration is ok and system became faster.


take a look into cached pages

sudo grep -har ‘KEY:’ /var/tmp/nginx/proxy/one

Check if cookies cached

sudo grep -hari ‘cookie’ /var/tmp/nginx/proxy/one

PS. Please, do not forget to remove any cached plugins like WP Super Cache. And you have to use system cron to run WP cron jobs:
in wp-config.php place the const

  1. define‘DISABLE_WP_CRON’, true;

In crontab write something like ( for every site if WPMU )

*/5 * * * * nice -20 wget -O /tmp/wp-cron.log -o /dev/null

Here we run every 5 minutes WP dispatch, writing logs into /tmp/wp-cron.log and ignoring the rest. Nice for decrease the priority.

Leave a Reply

Your email address will not be published. Required fields are marked *