17 June 2016

Nginx Sendfile protection

If you are running some kind of e-commerce store, it’s quite possible that your product images are protected with watermark. At the same time original uploaded images are not available for public access.

All nice and good! But what if some of your partners request access to original images without watermarks?

You can’t just create new url ( something like /images/partner_hidden_1234/i/image.jpg ) and give it to the partner, as it can potentially (and most likely will) leak out.

The other downside is you have no “metering”, meaning you have no idea who access those new urls and how often. Some people may say you have access logs and you may parse those to create stats. Well, yes - you can get some info this way, but only some..

Is there better way? You bet.

Meet Nginx X-Accel-Redirect

The idea here is pretty simple. Here is official doc as well.

  • First we need to define new url for those original images without watermarks. Let say it will look like this:

    /original_imgs/awesome_pic.jpg (note that your actual images may be stored in totally different location on your server, or could even be served from remote locations like S3. This is purely virtual path.)

  • Then we generate keys for every partner that require access to images. You partners will need to provide key in two ways, through GET param or direct embed into URI (you can think of more ways if you want, header etc):

    /original_imgs/awesome_pic.jpg?key=ab234ab or /original_imgs/ab234ab/awesome_pic.jpg

  • Next in Nginx we create new location block, where we rewrite urls to /original_imgs to some back end script:

      location ~ /original_imgs/ {
        rewrite /original_imgs/(.+) /scripts/meter.php?params=$1;
  • Inside of our meter.php script we check if the key is correct, store access info (in Redis for example), throw statsd (or Datadog) metric and if everything looks good - return X-Accel-Redirect header with original image location.

    Here is some pseudocode:

      // Check the key
      // Store access info
      // Return X-Accel-Redirect with path to the original image
      header('Content-type: image/jpeg');
      header("X-Accel-Redirect: /unprotected_originals/awesome_pic.jpg");

    Please note that Content-type header might be necessary, otherwise Nginx may guess your Content-type incorrectly. The other option is to remove Content-type from response headers and leave it to Nginx to decide.

  • Final step is to create internal location in nginx that will be serving protected files ( /unprotected_originals in our example ) to the clients.

      location ~ /unprotected_originals {

    It’s important to note here, that this example is super simple. In reality /unprotected_originals location may use aliases or event point to another server/service.

    The main point here is that when someone tries to access /unprotected_originals directly, they will get 404 error from Nginx because our location is internal.


At this point our original files should be protected from unauthorized access and we have full control and visibility over access patterns, which is VERY important.

If you have some big files, you can apply Sendfile approach to offload file serving to Nginx, which is optimized for the task and release backend resources. Another idea is to provide some temp urls for paid downloads.

As always let me know if you have any questions/suggestions in the comments section below!

Contact me on Codementor

Some popular ones

My books recommendations

Great book for operations people. Helped me to design and build solid deployment pipelines. Awesome advices on automated testing as well. The author advocates against feature branches, every commit goes to master! Scary? I know, but it actually makes sense once you get the idea. Read the book to find out more.

One of those rare books where every word counts!

Classics from John Allspaw who is SVP of Infrastructure and Operations at Etsy (and used to work for Flickr). The book covers very important topics like metrics collection, continuous deployment, monitoring, dealing with unexpected traffic spikes, dev and ops collaboration and much more. Def recommend if you are starting out in the operations field or been doing it for a while ( in latter case you probably read this book already :).

This book is must read for every software engineer, no matter which language you use! It will change your perspective on writing code. I was amazed by the quality of material - very detailed and up to the point.

"The only way to make the deadline -- the only way to go fast -- is to keep the code as clean as possible at all times."

blog comments powered by Disqus