Skip navigation

Nginx Image Filter Module is a fantastic module for serving resized images. Mu WordPress can use a lot of cpu’s and ram for image serving and this module can eliminate this problem. With this set up I was able to take my resized image serving up to 5000 requests per second. (2500 r/ps non cached, 5000 r/ps proxy cached)

As outlined in my other nginx image filter module post you need to implement the image at configuration time when you build nginx.

You have one nginx instance dedicated to image resizing and requests for image resizes get proxied to the nginx image serving instance from your main nginx server.

Resized images and cropped images are served like so:

Resize

http://subdomain.muinstall.com/ngimages/resize/files/2009/04/24879.jpg?w=120&h=120

Crop

http://subdomain.muinstall.com/ngimages/crop/files/2009/04/24879.jpg?w=120&h=120

You must include both w and h for width and height. If you miss either of these parameters you’ll get 415 errors.

Install Nginx Image Server:

sudo apt-get install libgd2-xpm-dev
./configure --prefix=/usr/local/nginx_images --with-http_image_filter_module
make
make install

Copy /etc/init.d/nginx /etc/init.d/nginx_images

Make changes to following lines on /etc/init.d/nginx_images.

DAEMON=/usr/local/nginx_images/sbin/$NAME
PIDFILE=/usr/local/nginx_images/logs/$NAME.pid

Here is the config for the nginx image server (/usr/local/nginx_images/conf/nginx.conf):

user  www-data;
worker_processes  1;

events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    log_format small '$body_bytes_sent $request_time $request_uri $args $status $uri';

    sendfile        on;
    keepalive_timeout  65;

    server {
    listen       81;
    server_name  localhost;
    access_log  logs/host.access.log  small;

        location / {
                    root   html;
                    index  index.html index.htm;
        }

        location /crop/ {
                set $width $arg_w;
                set $height $arg_h;
                proxy_set_header Host $http_host;
                proxy_pass http://127.0.0.1:80;
                image_filter   crop  $arg_w $arg_h;
                error_page     415   = /empty;
        }

        location /resize/ {
                set $width $arg_w;
                set $height $arg_h;
                ### if we don't set proxy header as http_host the host is read a 127.0.0.1
                proxy_set_header Host $http_host;
                proxy_pass http://127.0.0.1:80;
                image_filter   resize  $arg_w $arg_h;
                error_page     415   = /empty;
        }
        location = /empty {
            empty_gif;
        }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }

    }
}

Here is what you add to your main nginx mu install server conf:

    location ~* ^.+\.(jpg|jpeg|gif|png|xml|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$
    {
   	access_log  /usr/local/nginx/logs/statics.access.log small;
        root /home/mu/public_html;
	if ($request_uri ~* "/ngimages" ) {
		error_page 404 = @ngimages;
	}
	rewrite ^/resize/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
        rewrite ^/crop/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
	rewrite ^/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
        break;

    }
    location @ngimages {
        access_log  /usr/local/nginx/logs/ngimages.access.log small;
        proxy_read_timeout 10;
        proxy_cache_key $host$request_uri$args;
        proxy_cache_valid  200 304 7d;
        proxy_cache_valid  301 302 1h;
        proxy_cache_valid  404 403 402 401 504 502 20m;
        proxy_cache_valid  any 1m;
        proxy_cache two;
        proxy_set_header Host $http_host;
        rewrite ^/ngimages/(.*) /$1 break;
        proxy_pass http://127.0.0.1:81;
        }

wp-config at the bottom after abs path define and before require wp-settings:

if ( !defined('ABSPATH') )

	define('ABSPATH', dirname(__FILE__) . '/');

if ( !defined('WP_CONTENT_DIR') )
	define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );

if( !defined( "UPLOADBLOGSDIR" ) )
	define( "UPLOADBLOGSDIR", 'wp-content/blogs.dir' );

if( !defined( "UPLOADS" ) )
	define( "UPLOADS", UPLOADBLOGSDIR . "/{$_SERVER['HTTP_HOST']}/files/" );

if( !defined( "BLOGUPLOADDIR" ) )
	define( "BLOGUPLOADDIR", WP_CONTENT_DIR . "/blogs.dir/{$_SERVER['HTTP_HOST']}/files/" );

One Comment

  1. Just wanted to tell you that you can do the same by using proxy_store instead of proxy_cache. Mirroring instead of caching – which might be a better option in some cases:

    Might need some further editing for MU, I’ve only tested it with plain wordpress 2.9.

    I’ve been running out of worker processes for the resizing nginx on a busy site, still looking into that:
    2010/06/22 17:06:40 [alert] 56986#0: 8192 worker_connections are not enough.

    Also, check out the constant WPMU_ACCEL_REDIRECT in wp-config.php (you have to add it if it’s missing.

    If you set it to true, blogs.php uses X-Accel-Redirect instead of readfile() to serve the file. Offloads the work from PHP to nginx.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.