Jeff Palmer

Technology, and so on and such like.

Controlling the Website Cache With Nginx and Cloudflare

My good friend David told me about an amazing service called Cloudflare. They offer a ton of features including DNS, CDN, and other cool stuff.

After recently moving my site to Jekyll / Octopress, I was looking for a way to programmatically expire the cache for my index.html page. I mean, what good is it to update your site, if nobody can see the new content?

In nginx, I added the following to my server block:

expires 30d;
add_header Cache-Control "public";

The above will set an expire date for 30 days, and set the Cache-Control header to public, and max-age=2592000

The only problem is, the index.html page would also be cached for this duration. Thankfully, Cloudflare has a pretty solid API where I found information on invalidating a specific page. So, I added new invalidate and purge tasks to the Octopress Rakefile that looked like this:

desc "Purge all Cloudflare-cached assets"
task :purge do
  CFtoken = ENV['CFtoken']
  CFemail = ENV['CFemail']
  CFdomain = ENV['CFdomain']
  sh("curl -d a=fpurge_ts -d tkn=#{CFtoken} -d email=#{CFemail} -d z=#{CFdomain} -d v=1")

desc "Invalidate index.html"
task :invalidate do
CFtoken = ENV['CFtoken']
CFemail = ENV['CFemail']
CFdomain = ENV['CFdomain']
CFurl = ENV['CFurl']
sh("curl -d a=zone_file_purge -d tkn=#{CFtoken} -d email=#{CFemail} -d z=#{CFdomain} -d url=#{CFurl}")

Now when you rake deploy it’ll do the usual deploy, but then also invalidate the index.html file at Cloudflare. rake purge will invalidate ALL assets that Cloudflare has cached for your site, and must be called specifically. You probably don’t want to use this feature that often.

And then I added the following to the end of the :deploy task:


Since I store my Rakefile along with my site content in a private git repository using bitbucket, I didn’t want to risk having potentially sensitive information directly in the Rakefile because I may eventually make the repo public. So instead, I added them as environment variables in my ~/.profile, and just have the Rakefile pull that information from my shell environment.