Generating PDFs in Rails with PDFKit and deploying to a server

I’ve been using the rather excellent PDFKit library on a recent Ruby on Rails project to generate PDF reports.  The API is perfect: have some HTML, give me a PDF back.

In my controller I simply have:

def download_pdf
  html = render_to_string(:action => '../pdf/my_template', :layout => false)
  pdf =

Where the :action option is a path to a view file.   What could be simpler?  To get this up and running there were a couple steps.  First add a line to the Gemfile

gem 'pdfkit'

and then install the wkhtmltopdf library using

brew install wkhtmltopdf

And then I tried to deploy to a server…

Very pleased with my new sexy PDF reports I wanted to push my code to the server.  I did a quick

sudo apt-get install wkhtmltopdf

to grab the package, loaded up the site and hit the download button: Internal Server Error. Wat!? Looking in the log file:

command failed: "/usr/bin/wkhtmltopdf" "--page-size" "Letter" 
"--margin-top" "0.75in" "--margin-right" "0.75in" "--margin-bottom" 
"0.75in" "--margin-left" "0.75in" "--encoding" "UTF-8" "--print-media-type" 
"--quiet" "-" "-"

Huh? I then tried to run the command from the command line to see if I could get a more useful error message:

$ wkhtmltopdf google.pdf
wkhtmltopdf: cannot connect to X server

Damn. It turns out that the standard wkhtmltopdf package needs the server to have a window manager running and the chances are your server, like this one, doesn’t have a GUI interface.  So what now?  Well after a bit of Googling I was starting to get worried, until somebody (I forget where, but thank you!) mentioned that the binaries that can be downloaded from the project’s repo are built against qt and don’t depend on X running! Result!

Looking at the installation instructions page we find this snippet of joy labelled ‘Or….’ under Linux (Ubuntu):

# first, installing dependencies
sudo aptitude install openssl build-essential xorg libssl-dev

# for 64bits OS
tar xvjf wkhtmltopdf-0.9.9-static-amd64.tar.bz2
mv wkhtmltopdf-amd64 /usr/local/bin/wkhtmltopdf
chmod +x /usr/local/bin/wkhtmltopdf

This worked perfectly and all that remained was to tell PDFKit where to find this new binary. I put a pdfkit.rb in my initializers directory with the following in:

PDFKit.configure do |config|
     config.wkhtmltopdf = '/usr/local/bin/wkhtmltopdf' if Rails.env.production?

Bingo! PDF downloads are now running on the site.

By Adam Pope

Adam is our tech God, and it's not just his name that's holy - his knowledge of code borders on the supernatural, and whilst he doesn't like to brag, he finished top of his class at university. (Yep, the very top).

When he isn't crafting masterpieces on the web he is knocking them up in the kitchen, his legendary curry being an office mainstay here at Storm.

Adam was recently named as one of South West Business Insider's 42 under 42 for 2012. →


  1. What would we’ve done, if there wasn’t such thing as Google ;) Anyway, thank you solving the problem and posting this here. Now we know where to search for solution.

  2. this really save my time alot. had found other weird solution such as xvfb-run and strace wkhtmltopdf. luckily i tried yours first and it worked!

  3. Hello, I am new to Ruby and wondering where do I put the:

    PDFKit.configure do |config|
    config.wkhtmltopdf = ‘/usr/local/bin/wkhtmltopdf’ if Rails.env.production?

    in the pdfkit.rb file? I’m getting the same error that you were so I’m wondering how to fix it. Thank you

  4. Hi Adam,

    Thank you for your reply. I tried that, and it cleared that one error. However I am getting another error now. Here is what its saying

    Missing template welcome/index, application/index with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in: * “/home/mds/Desktop/mustacheapp2/app/views”

    Now I have both of those templates in 2 folders which are in the views folder. I also have the templates defined in the routes file, but for some reason this error is still occurring. Any idea why? Thank you for your help

  5. Hi Eric, not sure I can really help on that one I’m afraid. If you have the files /app/views/welcome/index.html.erb and /app/views/application/index.html.erb then there must be something else going on.

  6. Thats okay Adam. It turns out that I actually got it working. I had to add a mustache handler file to the initializers folder.
    mustache_template_handler.rb :

    # Tell Rails how to render mustache templates
    module MustacheTemplateHandler
    #assigns contains all the instance_variables defined on the controller’s view method
    “Mustache.render(#{template.source.inspect}, assigns).html_safe”

    # Register a mustache handler in the Rails template engine
    ActionView::Template.register_template_handler(:mustache, MustacheTemplateHandler)