2

I've got a VPS where I'm running my Rails app using Nginx and Unicorn. I was successful to add expires headers to JS and CSS files, however I cannot force Nginx to cache images as well (according to YSlow and Google PageSpeed Insights).

Here's my server block:

server {
  listen   80;
  root /home/rails/public;
  server_name _;
  index index.htm index.html;

  location / {
    try_files $uri/index.html $uri.html $uri @app;
  }

  location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
    try_files $uri @app;
  }

  location @app {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

  location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    expires max;
  }

}

The last piece of code is how I have acheived chaching of CSS and JS, but it is not working for images. What am I doing wrong? Should I do some additional changes elsewhere?

Thanks a lot!

kellins
  • 25
  • 4

1 Answers1

1

You have two location blocks matching images :

location ~* ^.+\.(jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
    try_files $uri @app;
}

And

location ~* .(jpg|jpeg|png|gif|ico|css|js)$ {
    expires max;
}

Nginx will stop at the first matching regex location block so the second location block is never used for jpg, jpeg, png, gif and ico files.

Update : details for the fallback caching

server {
  listen   80;
  root /home/rails/public;
  server_name _;
  index index.htm index.html;

  location / {
    try_files $uri/index.html $uri.html $uri @app;
  }

  location ~* ^.+\.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires max;
    try_files $uri @app;
  }

  location ~* ^.+\.(zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|mp3|flv|mpeg|avi)$ {
    try_files $uri @app;
  }

  location @app {
    if ($uri ~* ^.+\.(jpg|jpeg|png|gif|ico|css|js)$) {
        expires max;
    }
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }

}
Xavier Lucas
  • 12,815
  • 2
  • 44
  • 50
  • thank you for your answer, how do you recommend to accomplish it? Exclude images from both of them and creating a separate one for images that will have both `try_files` and `expires` ? – kellins Oct 01 '14 at 10:21
  • I did it by the above described way, fortunatelly it works (big thank you!), but it doesn't work for favicon. Can you suggest how to acheive caching for favicon as well? – kellins Oct 01 '14 at 10:50
  • @kellins Is the favicon provided by the fallback location @app? Do you try to achieve caching only in the case that static files aren't served by the fallback or you want it cached in both cases? – Xavier Lucas Oct 01 '14 at 11:52
  • For uknown reason it wasn't working for favicon and after a while it was :) So thanks a lot for your time. And yes, I would like to be able to cache assets in either case. – kellins Oct 01 '14 at 12:23
  • @kellins Ok so it's kinda double caching. You'll have to set the expires directive in the fallback block and filter by extension. – Xavier Lucas Oct 01 '14 at 12:57
  • So you don't recommend that? This is what I've got now `location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ { try_files $uri @app; expires max; }` – kellins Oct 01 '14 at 14:24
  • @kellins Check updated answer. – Xavier Lucas Oct 01 '14 at 14:44
  • thank you, is this with double caching or some kind of recommended? :) – kellins Oct 01 '14 at 17:20