96

We are using Nginx to serve static files on a development platform. As it is a development platform, we'd like to disable caching so that each change is propagated to the server. The configuration of the VHost is quite simple:

server {
  server_name  static.server.local;
  root /var/www/static;

  ## Default location
  location / {
    access_log        off;
    expires           0;
    add_header        Cache-Control private;
  } 
}

When we access an HTML file (http://static.server.local/test.html), we have no issue: the server returns a code 304 Not Modified as long as the file is not changed, and a 200 OK response with the modified file when the file is changed.
However, it seems to behave differently with a Javascript or a CSS file. Once the file is changed, we get a 200 OK response as expected, but with the old text.
Is there an internal cache mechanism in Nginx that could explain this behaviour? Or some configuration that we should add?

As a side note, here is the header returned by Nginx when the file has been modified (it seems correct):

Accept-Ranges:bytes
Cache-Control:max-age=0
private
Connection:keep-alive
Content-Length:309
Content-Type:text/css
Date:Fri, 13 May 2011 14:13:13 GMT
Expires:Fri, 13 May 2011 14:13:13 GMT
Last-Modified:Fri, 13 May 2011 14:13:05 GMT
Server:nginx/0.8.54

Edit
After trying different settings with the expires directive and Cache-Controlheader, I made some further investigations. In fact, the server is installed on a VirtualBox guest Ubuntu, and data are read from a shared folder that is on the Mac OSX host.
If the file is edited from an IDE (NetBeans) on the host, it seems that changes do not appear whereas if I edit it directly on the guest (using VIM), it is refreshed.
The strange thing is it does not behave similarly with HTML files.
Quite puzzling.

Edit 2 (ANSWER)
Indeed, the origin of the issue was more on the VirtualBox side. Or rather a conflict between VirtualBox and the "sendfile" option of the server.
This link VirtualBox Hates Sendfile gave me the solution: switch the sendfile flag in the server configuration to off:

sendfile  off;

Hope this could also help other person using VirtualBox for development. :)
There are some additional information on the VirtualBox forum.

mmoya
  • 284
  • 2
  • 8
Olivier Chappe
  • 961
  • 1
  • 7
  • 4
  • 3
    Are you running nginx in a vagrant vm and using shared fs? There have been several reports of your symptoms using that combination in #nginx. – kolbyjack May 13 '11 at 15:46
  • 3
    I could literally hug you!! Have spent 48 hours cursing and going completely mad with this exact issue.., recompiled nginx a few times, sacrificed some small fluffy creatures to assorted deities, learnt the cache directives backwards...all to find out it's one a line oddity to fix thanks to VirtualBox being weird! – James Butler Dec 11 '11 at 17:10
  • 15
    It would be a lot more clearer if you would post your answer as answer and accept it so everyone can see that this problem was solved. – Zombaya Jun 20 '12 at 22:37
  • I got hit by this bug this morning. Wouldn't have realised it was down to the shared folder without this. Thanks! – JaffaTheCake Dec 18 '12 at 08:50
  • Thx! As I understand it's no another way to fix this bug for now? What if I need sendfile be enabled?:-) – Dmitry Belaventsev Feb 10 '13 at 17:16
  • Ugh, ran into this as well. For clarity, the "server configuration" described above is the nginx config file. – Steve Bennett Mar 23 '14 at 04:24
  • Please, make a new message with answer and mark it as `best answer` – gam6itko Feb 02 '15 at 12:19

5 Answers5

59

Since the answer is somehow hidden in the question - here is the solution for nginx in a VirtualBox environment as standalone answer.

In your nginx config (usally /etc/nginx/nginx.conf) or vhost config file change the sendfile parameter to off:

sendfile  off;

While sendfile is at the heart of Nginx's fame (blazing-fast low-level static file serving efficiency) it might be a bane for local development, e.g. Javascripts that change often and need to be reloaded. Nonetheless Nginx sendfile is smart and probably isn't most people's issue; check your browser's "disable cache" options as well!

Charney Kaye
  • 123
  • 1
  • 7
lorem monkey
  • 825
  • 1
  • 7
  • 10
  • 5
    +1 though the answer should explain _why_ that's necessary instead of effectively leaving readers to find/re-read the question looking for references. Make the answer stand on it's own -> better. – AD7six Nov 19 '14 at 10:00
  • 2
    This seems to be the answer for me. The problem seems to occur with the specific combination of Sendfile, VirtualBox and an OSX host. https://abitwiser.wordpress.com/2011/02/24/virtualbox-hates-sendfile/ https://forums.virtualbox.org/viewtopic.php?f=1&t=24905 – Steve Bennett Feb 28 '15 at 23:34
  • 1
    `sendfile` is fine for even a local development environment; it's only VirtualBox in which it's broken. Which is one reason (of many) I recommend avoiding VirtualBox... – Michael Hampton Jan 01 '17 at 06:56
  • thanks for the save, strange issue with Vagrant / VirtualBox / Ubuntu / Wordpress, I'm guessing my PROD environment is safe with sendfile on as default. – sonjz Mar 31 '17 at 19:46
  • Solves my problem with nginx and docker – PascalTurbo Sep 07 '17 at 18:03
15

set your expires tag to

expires off;

and it should not set any expires headers at all, it could also be your browser caching files incorrectly

anthonysomerset
  • 3,983
  • 2
  • 20
  • 24
  • Unfortunately, I have tried this as well as `expires -1` and the behavior is still the same. – Olivier Chappe May 13 '11 at 15:06
  • Concerning the browser, I have thought of this possibilities: I was first trying with Chrome, and after modifying a file opened it for the first time in Firefox: I still got the first version of the file. – Olivier Chappe May 13 '11 at 15:08
  • also the cache-control header should probably be CACHE-CONTROL:NO-CACHE – anthonysomerset May 13 '11 at 15:11
  • or remove the cache control header altogether - sorry couldnt edit previous comment – anthonysomerset May 13 '11 at 15:17
  • Thanks for those ideas, I've tried different combinations and then investigated for other possible sources: it seems that Nginx might not be the culprit here. See my edit. – Olivier Chappe May 13 '11 at 15:54
  • 1
    On Windows, "expires off" still doesn't disable caching of html files. Super frustrating when I update a file in my IDE, but !$#%ing nginx serves an old version. – Dan Dascalescu Oct 31 '14 at 02:59
4

This is late, but still marked unanswered, so I will take a stab. Just for giggles, have you tried:

location ~* \.(css|js)$ {
    expires 0;
    break;
}

Haven't tried this myself, but have learned to try this kind of thing with Nginx in a server container from time to time when I have issues similar to this...

ColtonCat
  • 738
  • 3
  • 7
4

This is old bug in VirtualBox (see: #819, #9069, #12597, #14920) where vboxvfs seems to have some problems with mmapped access to files which are synched.

This may happen when you edit the file outside of VM, and you expect to see the same change within the VM.

To workaround this problem, you need to disable the kernel sendfile support to deliver files to the client by disabling EnableSendfile option. This is especially trouble for NFS or SMB mounted files.

For Nginx (change in nginx.conf), e.g.

sendfile off;

Similar for Apache (in httpd.conf or in vhosts file), e.g.

<Directory "/path-to-nfs-files">
  EnableSendfile Off
</Directory>

After the change reload the Apache.


Other potential solution is just remember to not edit the files on the host, or try to re-edit the same file, but within the VM.


Another workaround includes dropping the Linux pagecache, e.g.

echo 1 > /proc/sys/vm/drop_caches

Or to clear the caches every second (as per this post), try:

watch -n 1 $(sync; echo 1 > /proc/sys/vm/drop_caches)

Note: Number 1 stands for freeing pagecache, 2 for dentries and inodes, 3 for pagecache, dentries and inodes.


The above problem can be replicated by the following mmap-test program, see: mmap-problem.c.

kenorb
  • 5,943
  • 1
  • 44
  • 53
2

If nothing mentioned above helps and still Nginx returns old content of your files it may be problem related to open_file_cache.

See as reference:

k2s
  • 121
  • 2