I have an origin server behind a nginx proxy in a container, with a CDN in front.

I want my HTML pages to cache on the CDN for 1 minute, so I set the cache-control: public and cache-control: max-age=60 headers on their responses. Obviously on every cache miss the CDN goes all the way to the origin server to re-render the page.

Now, the origin server and the nginx instance are in the same container. What I'd like to do is have nginx cache any origin server response with a cache-control: public header for much longer than 1 minute - basically indefinitely. That's because I know that for as long as the container is around, the origin server will be at the same version and the response will be the same.

The CDN doesn't know this of course, it's just hitting a URL, and that's why the max-age is only a minute - on a new deploy I want the new content to be refreshed on the CDN within a minute - but it'd be great to have nginx as a cache in front of the origin server so that the origin server doesn't have to rerender the same page on every CDN cache miss, if it's actually still running at the same version.

Is there an elegant way to configure nginx cache to do something like this? I.e. ignore the cache-control: max-age header and just cache indefinitely, yet pass that header through so that it gets processed by the CDN?

Using something like proxy_ignore_headers Cache-Control and proxy_cache_valid 200 1y won't work because I don't want to cache every page, only the ones with the cache-control: public header set. I basically just need, for those responses only, to multiply max-age by a lot or statically set it as something really large.

Is this possible? I know it's probably not the model nginx is assuming, with its cache being 'ephemeral' and being automatically blown away when the origin server is redeployed, but currently the only hacky way I can think to do it is to set my max-age headers as 10000x on the origin server and rewrite them to be / 10000 before forwarding on to the CDN - I was really hoping there would be a better way of doing it than that.


Let the backend set the header "X-Accel-Expires" to a very high value (eg. 86400 = 1 day), and unset that header before sending the response to the client (you never know that the CDN "understands" "X-Accel-Expires").

See proxy_cache documentation

  • Amazing, this is exactly the feature I was looking for. Thanks! – davnicwil Jul 6 '20 at 13:50
  • This worked great! Thanks again. By the way it turns out nginx doesn't pass X-Accel- headers to the client by default, so you don't even need to explicitly unset the header with proxy_hide_header – davnicwil Jul 6 '20 at 18:55
  • It took some searching. I first tried with Lua, but Lua couldn't modify proxy_cache_valid, so I went searching how nginx determined how long to cache a given object, when I found this in the manual. – Gerard H. Pille Jul 6 '20 at 19:53

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.