I have a php website running on a DigitalOcean droplet (nginx server), and i also use Cloudflare. Recently, my website was hit by something that i yet did not understand.. as my CPU usage was usually 1-2% and it went to 100% for a few hours resulting in my server crashing.

My Cloudflare analytics showed an extremely high number of visitors - of which i am sure was not human traffic.

Cloudflare asked to see my nginx error logs and access logs. Following is their reply -

You have 2 caching headers that are going to expire your assets as soon as they get stored at our edge.

< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0


< Expires:> Thu, 19 Nov 1981 08:52:00 GMT. 

Because the Expires header is set to sometime in the past, the cache is going to be expired the moment it hits our edge. Then you have your cache-control header basically saying do not store any of the assets at our edge, but you have a caching enabled, so our edge will continue to crawl your site. This can cause what looks like a DoS attack against your origin.

Can someone please tell me how can i set my Expires header and Cache-control header on my Nginx server?

Your reply is appreciated, thanks!


You have an incorrect setting in your php.ini file:

The session.cache_limiter value is set to nocache in the default php.ini file and needs to be changed.

session.cache_limiter should be defined and set, either to public which inserts public cache-control headers, or to '' (blank), which doesn't insert any cache-control headers, and the headers sent by your application will then be used, if any.


I've found that with Wordpress (some themes) and other PHP applications sometimes it's near to impossible to get the headers set correctly using PHP. My solution is that I just ignore the headers the application sets and override them with what I want in Nginx. I find this much simpler, much faster, and much more reliable.

If you can work out how to do it from your application and PHP, great, but this way gives you lots of control and it's easy. Building nginx with the required module is easier than you might think, it can probably done in 30 minutes based on a guide I link to below.

I have a guide how to set up Nginx and Cloudflare.

Short version of caching header:

  • You want cache-control
  • You don't want pragma

For images use something like this in your location - you need headers-more module compiled into nginx. See part 1 of my tutorial for that.

add_header Cache-Control "public, max-age=691200, s-maxage=691200";
more_clear_headers Server; more_clear_headers "Pragma"; more_clear_headers "Expires";

For pages I don't cache on CloudFlare, but I do use nginx fast_cgi page cache, which is in my tutorial.

For CloudFlare you may need to use page rules if you need anything tricky, but in general the default settings will cache images but not pages.

  • This is probably all good general advice, but it doesn't really get to the root cause of the problem. – Michael Hampton Apr 24 '16 at 1:25
  • I probably should've said why I gave this advice, rather than answering directly. I'll update my answer. – Tim Apr 24 '16 at 1:56
  • Well then. If you ever want to know why PHP screws up these headers, you can read the other answer. :) – Michael Hampton Apr 24 '16 at 2:05
  • In my case I think it was because of poor Wordpress theme that didn't consider caching at all, as the default theme was fine. Good to have different answers though :) – Tim Apr 24 '16 at 2:28
  • 1
    Tim answer is very good, and so is the articles he wrote, but Michael's solution solved the base of the problem. Thanks to both of you! – codemode Apr 25 '16 at 12:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.